From 1318ab37dd3215da648e48ac17096be3ba4bb75c Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Tue, 6 May 2008 12:40:24 +0000 Subject: [PATCH] Fix for template type resolution bug 229917. --- .../parser/tests/ast2/AST2TemplateTests.java | 12 +-- .../parser/tests/ast2/DOMParserTestSuite.java | 3 +- .../parser/cpp/semantics/CPPTemplates.java | 78 +++++++++++-------- .../dom/parser/cpp/semantics/CPPVisitor.java | 30 ++++--- 4 files changed, 74 insertions(+), 49 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 ac48badf12a..fc1db65400e 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 @@ -15,9 +15,6 @@ package org.eclipse.cdt.core.parser.tests.ast2; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType; - -import java.util.Iterator; - import junit.framework.TestSuite; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; @@ -1525,6 +1522,9 @@ public class AST2TemplateTests extends AST2BaseTest { CR = (ICPPTemplateParameter) col.getName(14).resolveBinding(); assertSame(CR, T); + + CR = (ICPPTemplateParameter) col.getName(16).resolveBinding(); + assertSame(CR, T); } // template class Array {}; @@ -2055,7 +2055,7 @@ public class AST2TemplateTests extends AST2BaseTest { // // template // typename _C::value_type GetPair(_C& collection, typename _C::value_type::first_type key); - public void _testBug229917_2() throws Exception { + public void testBug229917_2() throws Exception { BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true); IBinding b0 = bh.assertNonProblem("value_type GetPair", 10, IBinding.class); } @@ -2168,8 +2168,8 @@ public class AST2TemplateTests extends AST2BaseTest { tu.accept(col); IASTName name; - for (Iterator i = col.nameList.iterator(); i.hasNext();) { - name = (IASTName) i.next(); + for (Object element : col.nameList) { + name = (IASTName) element; assertFalse(name.resolveBinding() instanceof IProblemBinding); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java index 9ff8113967d..c80b5604c3c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java @@ -16,7 +16,6 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -import org.eclipse.cdt.core.parser.tests.ParserTestSuite; import org.eclipse.cdt.core.parser.tests.prefix.CompletionTestSuite; /** @@ -24,7 +23,7 @@ import org.eclipse.cdt.core.parser.tests.prefix.CompletionTestSuite; */ public class DOMParserTestSuite extends TestCase { public static Test suite() { - TestSuite suite= new TestSuite(ParserTestSuite.class.getName()); + TestSuite suite= new TestSuite(DOMParserTestSuite.class.getName()); suite.addTest(AST2Tests.suite()); suite.addTestSuite(GCCTests.class); suite.addTest(AST2CPPTests.suite()); 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 941adc82ed0..cff1c068a11 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 @@ -773,63 +773,79 @@ public class CPPTemplates { return result; } + /** + * Checks whether a given name corresponds to a template declaration and returns the ast node for it. + * This works for the name of a template-definition and also for a name needed to qualify a member + * definition: + *
+	 * template <typename T> void MyTemplate<T>::member() {}
+	 * 
+ * @param name a name for which the corresponding template declaration is searched for. + * @return the template declaration or null if name does not + * correspond to a template declaration. + */ public static ICPPASTTemplateDeclaration getTemplateDeclaration(IASTName name) { - if (name == null) return null; + if (name == null) { + return null; + } IASTNode parent = name.getParent(); while (parent instanceof IASTName) { parent = parent.getParent(); } if (parent instanceof IASTDeclSpecifier) { - parent = parent.getParent(); + if (parent instanceof IASTCompositeTypeSpecifier == false + && parent instanceof IASTElaboratedTypeSpecifier == false) { + return null; + } + parent = parent.getParent(); } else { while (parent instanceof IASTDeclarator) { parent = parent.getParent(); } } - if (parent instanceof IASTDeclaration && parent.getParent() instanceof ICPPASTTemplateDeclaration) { - parent = parent.getParent(); - } else { + if (parent instanceof IASTDeclaration == false) { return null; } - + + parent = parent.getParent(); if (parent instanceof ICPPASTTemplateDeclaration) { ICPPASTTemplateDeclaration templateDecl = (ICPPASTTemplateDeclaration) parent; - while (templateDecl.getParent() instanceof ICPPASTTemplateDeclaration) - templateDecl = (ICPPASTTemplateDeclaration) templateDecl.getParent(); - IASTName[] ns = null; + IASTName[] ns; if (name instanceof ICPPASTQualifiedName) { ns = ((ICPPASTQualifiedName) name).getNames(); name = ns[ns.length - 1]; } else if (name.getParent() instanceof ICPPASTQualifiedName) { ns = ((ICPPASTQualifiedName) name.getParent()).getNames(); - } - if (ns != null) { - IASTDeclaration currDecl = templateDecl; - for (int j = 0; j < ns.length; j++) { - if (ns[j] == name) { - if (ns[j] instanceof ICPPASTTemplateId || j + 1 == ns.length) { - if (currDecl instanceof ICPPASTTemplateDeclaration) - return (ICPPASTTemplateDeclaration) currDecl; - return null; - } - } - if (ns[j] instanceof ICPPASTTemplateId) { - if (currDecl instanceof ICPPASTTemplateDeclaration) - currDecl = ((ICPPASTTemplateDeclaration) currDecl).getDeclaration(); - else - return null; //??? this would imply bad ast or code - } - } } else { - while (templateDecl.getDeclaration() instanceof ICPPASTTemplateDeclaration) { - templateDecl = (ICPPASTTemplateDeclaration) templateDecl.getDeclaration(); - } + // one name: use innermost template declaration return templateDecl; } + + // start with outermost template declaration + while (templateDecl.getParent() instanceof ICPPASTTemplateDeclaration) + templateDecl = (ICPPASTTemplateDeclaration) templateDecl.getParent(); + + for (int j = 0; j < ns.length; j++) { + final IASTName singleName = ns[j]; + if (singleName == name) { + if (singleName instanceof ICPPASTTemplateId || j == ns.length-1) { + return templateDecl; + } + return null; + } + if (singleName instanceof ICPPASTTemplateId) { + final IASTDeclaration next= templateDecl.getDeclaration(); + if (next instanceof ICPPASTTemplateDeclaration) { + templateDecl= (ICPPASTTemplateDeclaration) next; + } else { + return null; + } + } + } } - return null; + return null; } public static IASTName getTemplateName(ICPPASTTemplateDeclaration templateDecl) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index fd43ccbf700..5b8c3e43cf2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -778,6 +778,8 @@ public class CPPVisitor { return ((ICPPASTIfStatement)parent).getScope(); } else if (parent instanceof ICPPASTWhileStatement) { return ((ICPPASTWhileStatement)parent).getScope(); + } else if (parent instanceof ICPPASTTemplateDeclaration) { + return ((ICPPASTTemplateDeclaration)parent).getScope(); } } else if (node instanceof IASTStatement) { return getContainingScope((IASTStatement) node); @@ -886,18 +888,30 @@ public class CPPVisitor { name = (IASTName) parent; parent = name.getParent(); } - ICPPASTTemplateDeclaration decl = CPPTemplates.getTemplateDeclaration(name); - if (decl != null) - return decl.getScope(); + ICPPASTTemplateDeclaration tmplDecl = CPPTemplates.getTemplateDeclaration(name); + if (tmplDecl != null) + return tmplDecl.getScope(); if (parent instanceof ICPPASTQualifiedName) { - IASTName[] names = ((ICPPASTQualifiedName) parent).getNames(); + final ICPPASTQualifiedName qname= (ICPPASTQualifiedName) parent; + final IASTName[] names = qname.getNames(); int i = 0; for (; i < names.length; i++) { if (names[i] == name) break; } + if (i == 0) { + if (qname.isFullyQualified()) { + return parent.getTranslationUnit().getScope(); + } + for (int j=1; j < names.length; j++) { + tmplDecl = CPPTemplates.getTemplateDeclaration(names[j]); + if (tmplDecl != null) { + return getContainingScope(tmplDecl); + } + } + } if (i > 0) { - IBinding binding = names[i - 1].resolveBinding(); + IBinding binding = names[i-1].resolveBinding(); while (binding instanceof ITypedef) { IType t = ((ITypedef)binding).getType(); if (t instanceof IBinding) @@ -925,11 +939,7 @@ public class CPPVisitor { } return scope; } - } - else if (((ICPPASTQualifiedName)parent).isFullyQualified()) - { - return parent.getTranslationUnit().getScope(); - } + } } else if (parent instanceof ICPPASTFieldReference) { final ICPPASTFieldReference fieldReference = (ICPPASTFieldReference)parent; IASTExpression owner = fieldReference.getFieldOwner();