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 2e568724fa3..32901bb3d8f 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 @@ -10089,4 +10089,20 @@ public class AST2TemplateTests extends AST2TestBase { public void testInstantiationOfEvalIdWithFieldOwner_511108() throws Exception { parseAndCheckBindings(); } + + // class C {}; + // typedef C D; + // + // template + // void test(); + // + // void foo() { + // test(); + // test(); + // test(); + // test(); + // } + 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 65739ddeea4..7454bd61bc0 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 @@ -3164,4 +3164,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 d951083e52e..e8a16f24ee6 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 @@ -345,6 +345,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) { @@ -371,7 +374,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)) { @@ -394,7 +397,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)) @@ -402,7 +406,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()); } @@ -419,9 +423,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());