From 7fc4c9b937c5ffef9c17673a8cabc0953ee00f01 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sun, 25 Aug 2013 01:55:18 -0400 Subject: [PATCH] Bug 401152 - Incorrect semantic error in class template specialization Change-Id: I962872a55bcc34f6ebfb944b7406c94af8f8d489 Signed-off-by: Nathan Ridge Reviewed-on: https://git.eclipse.org/r/15834 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../parser/tests/ast2/AST2TemplateTests.java | 17 +++++++++++++++++ .../internal/core/dom/parser/ASTQueries.java | 12 ++++++++++++ .../dom/parser/cpp/semantics/CPPTemplates.java | 14 ++++++++++++-- 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 + // struct B {}; + // + // template + // struct A; + // + // template + // struct A, T> { + // void method(); + // }; + // + // template + // void A, 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) {