diff options
3 files changed, 41 insertions, 2 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 69829238703..f71aa75949f 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 @@ -8019,4 +8019,21 @@ public class AST2TemplateTests extends AST2TestBase { public void testInstantiationOfTypedef_412555() throws Exception { parseAndCheckBindings(); } + + // template <class T> + // struct B {}; + // + // template <class Abstract, class T> + // struct A; + // + // template <class T> + // struct A<B<T>, T> { + // void method(); + // }; + // + // template <class T> + // void A<B<T>, T>::method() {} + public void testOutOfLineMethodOfPartialSpecialization_401152() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTQueries.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTQueries.java index fe6042abc05..7c3736634e1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTQueries.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTQueries.java @@ -172,4 +172,16 @@ public class ASTQueries { } return null; } + + /** + * Check whether 'ancestor' is an ancestor of 'descendant' in the AST. + */ + public static boolean isAncestorOf(IASTNode ancestor, IASTNode descendant) { + do { + if (descendant == ancestor) + return true; + descendant = descendant.getParent(); + } while (descendant != null); + return false; + } } 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 f1f1d1d5dec..3806b7a1b41 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 @@ -289,8 +289,18 @@ public class CPPTemplates { if (node.getPropertyInParent() == IASTCompositeTypeSpecifier.TYPE_NAME) return null; if (node instanceof IASTFunctionDefinition) { - name= ASTQueries.findInnermostDeclarator(((IASTFunctionDefinition) node).getDeclarator()).getName().getLastName(); - scope= CPPVisitor.getContainingScope(name); + IASTName functionName= ASTQueries.findInnermostDeclarator(((IASTFunctionDefinition) node).getDeclarator()).getName().getLastName(); + // 'name' may be inside the qualifier of a method name in a out-of-line method definition. + // In such a case, calling getContainingScope() on the method name will attempt to + // resolve the qualifier, which will attempt to resolve 'name', which will get into + // a recursion as 'name' is currently being resolved. Since an out-of-line method + // definition cannot be inside a template scope, we can accurately return null + // in this case. + if (functionName.getParent() instanceof ICPPASTQualifiedName + && ASTQueries.isAncestorOf(functionName.getParent(), name)) { + return null; + } + scope= CPPVisitor.getContainingScope(functionName); break; } if (node instanceof ICPPASTCompositeTypeSpecifier) { |