diff options
3 files changed, 73 insertions, 6 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index c2ad03351a1..6b846e33a3c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -9961,4 +9961,20 @@ public class AST2TemplateTests extends AST2TestBase { public void testNoexceptSpecifierInTypeTemplateArgument_511186() throws Exception { parseAndCheckBindings(); } + + // class C {}; + // typedef C D; + // + // template <typename T, typename = decltype(T().~T())> + // void test(); + // + // void foo() { + // test<C>(); + // test<const C>(); + // test<D>(); + // test<const D>(); + // } + public void testDependentDestructorName_511122() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index db8b8407ba8..79e4d7e5c6b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -3163,4 +3163,51 @@ public class CPPTemplates { } return exec; } + + /** + * Instantiate a plain name (simple-id). + * Only destructor names require instantiation, e.g. the name "~T", when instantiated + * with a parameter map that maps T to C, needs to become "~C". + * + * @param name the name to be instantiated + * @param context the instantiation context + * @param enclosingTemplate The enclosing template definition. This is required because the + * instantiation context doesn't actually store parameter names, so + * we need to walk the chain of enclosing templates to find potential + * template parameter names. + * @return The instantiated name. If the provided name is not a destructor name, or if + * the type named by the destructor name is not mapped to anything in the + * instantiation context's parameter map, the provided name is returned unchanged. + */ + public static char[] instantiateName(char[] name, InstantiationContext context, IBinding enclosingTemplate) { + if (name == null || name.length == 0 || name[0] != '~') { + return name; + } + String typename = new String(name).substring(1); + ICPPTemplateParameterMap map = context.getParameterMap(); + IBinding enclosing = enclosingTemplate; + while (enclosing != null) { + if (enclosing instanceof ICPPTemplateDefinition) { + for (ICPPTemplateParameter param : ((ICPPTemplateDefinition) enclosing).getTemplateParameters()) { + if (param instanceof ICPPTemplateTypeParameter) { + if (param.getName().equals(typename)) { + ICPPTemplateArgument arg = map.getArgument(param); + if (arg instanceof CPPTemplateTypeArgument) { + IType argType = arg.getTypeValue(); + argType = SemanticUtil.getNestedType(argType, CVTYPE | TDEF); + if (argType instanceof ICPPClassType) { + StringBuilder result = new StringBuilder(); + result.append('~'); + result.append(((ICPPClassType) argType).getName()); + return result.toString().toCharArray(); + } + } + } + } + } + } + enclosing = enclosing.getOwner(); + } + return name; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java index 36c5bf82747..58bef145dd4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java @@ -346,6 +346,9 @@ public class EvalID extends CPPDependentEvaluation { if (templateArgs != null) { templateArgs = instantiateArguments(templateArgs, context, false); } + + char[] name = fName; + name = CPPTemplates.instantiateName(name, context, getTemplateDefinition()); ICPPEvaluation fieldOwner = fFieldOwner; if (fieldOwner != null) { @@ -372,7 +375,7 @@ public class EvalID extends CPPDependentEvaluation { boolean nameOwnerStillDependent = false; if (nameOwner instanceof ICPPClassType) { - ICPPEvaluation eval = resolveName((ICPPClassType) nameOwner, null, templateArgs, null, context.getPoint()); + ICPPEvaluation eval = resolveName(name, (ICPPClassType) nameOwner, null, templateArgs, null, context.getPoint()); if (eval != null) return eval; if (CPPTemplates.isDependentType((ICPPClassType) nameOwner)) { @@ -395,7 +398,8 @@ public class EvalID extends CPPDependentEvaluation { IType fieldOwnerClassTypeCV = SemanticUtil.getNestedType(fieldOwnerType, TDEF | REF); IType fieldOwnerClassType = SemanticUtil.getNestedType(fieldOwnerClassTypeCV, CVTYPE); if (fieldOwnerClassType instanceof ICPPClassType) { - ICPPEvaluation eval = resolveName((ICPPClassType) fieldOwnerClassType, fieldOwner, templateArgs, fieldOwnerClassTypeCV, context.getPoint()); + ICPPEvaluation eval = resolveName(name, (ICPPClassType) fieldOwnerClassType, fieldOwner, + templateArgs, fieldOwnerClassTypeCV, context.getPoint()); if (eval != null) return eval; if (!CPPTemplates.isDependentType(fieldOwnerClassType)) @@ -403,7 +407,7 @@ public class EvalID extends CPPDependentEvaluation { } } - return new EvalID(fieldOwner, nameOwner, fName, fAddressOf, fQualified, fIsPointerDeref, templateArgs, + return new EvalID(fieldOwner, nameOwner, name, fAddressOf, fQualified, fIsPointerDeref, templateArgs, getTemplateDefinition()); } @@ -420,9 +424,9 @@ public class EvalID extends CPPDependentEvaluation { return newEvalID; } - private ICPPEvaluation resolveName(ICPPClassType nameOwner, ICPPEvaluation ownerEval, ICPPTemplateArgument[] templateArgs, - IType impliedObjectType, IASTNode point) { - LookupData data = new LookupData(fName, templateArgs, point); + private ICPPEvaluation resolveName(char[] name, ICPPClassType nameOwner, ICPPEvaluation ownerEval, + ICPPTemplateArgument[] templateArgs, IType impliedObjectType, IASTNode point) { + LookupData data = new LookupData(name, templateArgs, point); data.qualified = fQualified; try { CPPSemantics.lookup(data, nameOwner.getCompositeScope()); |