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 41bf6cabf37..37e08cb62d7 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 @@ -3326,7 +3326,7 @@ public class AST2TemplateTests extends AST2BaseTest { // }; // template typename XT::mytype1 XT::m1() {} // template typename XT::mytype2 XT::m2() {} - // template <> typename XT::mytype3 XT::m3() {} + // XT::mytype3 XT::m3() {} public void testMethodImplWithNonDeferredType() throws Exception { final String code = getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); @@ -3352,7 +3352,7 @@ public class AST2TemplateTests extends AST2BaseTest { // template void f(T); // }; // template void A::f(T){} //problem on f - public void _testClassTemplateMemberFunctionTemplate_Bug104262() throws Exception { + public void testClassTemplateMemberFunctionTemplate_Bug104262() throws Exception { final String code = getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); BindingAssertionHelper bh= new BindingAssertionHelper(code, true); @@ -3367,4 +3367,22 @@ public class AST2TemplateTests extends AST2BaseTest { method= bh.assertNonProblem("A::f", 11); assertSame(method.getOwner(), special); } + + // template class XT { + // class Nested { + // template void Nested::m(V); + // }; + // }; + // template template void XT::Nested::m(V) { + // } + public void testQualifiedMethodTemplate() throws Exception { + final String code = getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + + ICPPMethod mt1= bh.assertNonProblem("m(V);", 1); + ICPPMethod mt2= bh.assertNonProblem("m(V) ", 1); + assertSame(mt1, mt2); + assertInstance(mt1, ICPPFunctionTemplate.class); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateDeclaration.java index ce0a74b43ff..c2a277670b3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateDeclaration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateDeclaration.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * John Camelon (IBM) - Initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -14,20 +14,22 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTNode; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; /** - * @author jcamelon + * Represents a template declaration. */ public class CPPASTTemplateDeclaration extends ASTNode implements - ICPPASTTemplateDeclaration, IASTAmbiguityParent { + ICPPASTInternalTemplateDeclaration, IASTAmbiguityParent { private boolean exported; + private byte isAssociatedWithLastName= -1; + private short nestingLevel= -1; private IASTDeclaration declaration; private ICPPTemplateScope templateScope; @@ -116,4 +118,29 @@ public class CPPASTTemplateDeclaration extends ASTNode implements declaration = (IASTDeclaration) other; } } + + public short getNestingLevel() { + if (nestingLevel == -1) { + CPPTemplates.associateTemplateDeclarations(this); + } + assert nestingLevel != -1; + return nestingLevel; + } + + public boolean isAssociatedWithLastName() { + if (isAssociatedWithLastName == -1) + CPPTemplates.associateTemplateDeclarations(this); + + assert isAssociatedWithLastName != -1; + return isAssociatedWithLastName != 0; + } + + public void setAssociatedWithLastName(boolean value) { + isAssociatedWithLastName= value ? (byte) 1 : (byte) 0; + } + + public void setNestingLevel(short level) { + assert level >= 0; + nestingLevel= level; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateSpecialization.java index 22a9852efe8..379fbdff3ca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateSpecialization.java @@ -6,28 +6,31 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * John Camelon (IBM) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTNode; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; /** - * @author jcamelon + * Node for template specialization syntax. */ public class CPPASTTemplateSpecialization extends ASTNode implements - ICPPASTTemplateSpecialization, ICPPASTTemplateDeclaration, IASTAmbiguityParent { + ICPPASTTemplateSpecialization, ICPPASTInternalTemplateDeclaration, IASTAmbiguityParent { private IASTDeclaration declaration; private ICPPTemplateScope templateScope; + private short nestingLevel= -1; + private byte isAssociatedWithLastName= -1; public CPPASTTemplateSpecialization() { @@ -98,4 +101,29 @@ public class CPPASTTemplateSpecialization extends ASTNode implements declaration = (IASTDeclaration) other; } } + + public short getNestingLevel() { + if (nestingLevel == -1) { + CPPTemplates.associateTemplateDeclarations(this); + } + assert nestingLevel != -1; + return nestingLevel; + } + + public boolean isAssociatedWithLastName() { + if (isAssociatedWithLastName == -1) + CPPTemplates.associateTemplateDeclarations(this); + + assert isAssociatedWithLastName != -1; + return isAssociatedWithLastName != 0; + } + + public void setAssociatedWithLastName(boolean value) { + isAssociatedWithLastName= value ? (byte) 1 : (byte) 0; + } + + public void setNestingLevel(short level) { + assert level >= 0; + nestingLevel= level; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameter.java index 6463d051d71..5307eb7f3b8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameter.java @@ -19,7 +19,6 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; @@ -42,42 +41,40 @@ public abstract class CPPTemplateParameter extends PlatformObject public CPPTemplateParameter(IASTName name) { declarations = new IASTName[] {name}; - fParameterID= computeParameterPosition(name); + fParameterID= computeParameterID(name); } - private int computeParameterPosition(IASTName name) { - int pos= -1; - int nesting= -1; + private int computeParameterID(IASTName name) { + int nesting= 0; ICPPASTTemplateParameter tp= null; + ICPPASTTemplateParameter[] tps= null; for (IASTNode node= name.getParent(); node != null; node= node.getParent()) { - ICPPASTTemplateParameter[] tps= null; - if (node instanceof ICPPASTTemplateParameter) { + if (tp == null && node instanceof ICPPASTTemplateParameter) { tp= (ICPPASTTemplateParameter) node; - } else if (node instanceof ICPPASTTemplateDeclaration) { - if (++nesting == 0) { - tps= ((ICPPASTTemplateDeclaration) node).getTemplateParameters(); + } else if (node instanceof ICPPASTInternalTemplateDeclaration) { + final ICPPASTInternalTemplateDeclaration tdecl= (ICPPASTInternalTemplateDeclaration) node; + nesting+= tdecl.getNestingLevel(); + if (tps == null) { + tps= tdecl.getTemplateParameters(); } } else if (node instanceof ICPPASTTemplatedTypeTemplateParameter) { - if (++nesting == 0) { + nesting++; + if (tps == null) { tps= ((ICPPASTTemplatedTypeTemplateParameter) node).getTemplateParameters(); } } - - if (pos == -1 && tps != null && tp != null) { - for (int i = 0; i < tps.length; i++) { - if (tps[i] == tp) { - pos= i; - break; - } + } + int pos= 0; + if (tps != null && tp != null) { + for (int i = 0; i < tps.length; i++) { + if (tps[i] == tp) { + pos= i; + break; } } } - if (nesting < 0) - nesting= 0; - if (pos < 0) - pos= 0; - - return (nesting << 16) + pos; + + return (nesting << 16) + (pos & 0xffff); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPASTInternalTemplateDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPASTInternalTemplateDeclaration.java new file mode 100644 index 00000000000..0b82f64d81b --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPASTInternalTemplateDeclaration.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; + +/** + * Adds method that assist in finding the relation-ship between a template declaration + * and the names of the nested declaration. + */ +public interface ICPPASTInternalTemplateDeclaration extends ICPPASTTemplateDeclaration { + + /** + * Returns whether this template declaration is associated with the last name of + * the possibly qualified name of the enclosing declaration. If this template declaration + * encloses another one, false is returned. + */ + boolean isAssociatedWithLastName(); + + /** + * Returns the nesting level of this template declaration. + * @see ICPPTemplateParameter#getTemplateNestingLevel() + */ + short getNestingLevel(); + + /** + * Sets the nesting level, once it is determined + */ + void setNestingLevel(short level); + + /** + * Sets whether the template declaration is associated with the last name. + */ + void setAssociatedWithLastName(boolean value); +} 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 2cc01be9ed2..12cf86cb37a 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 @@ -18,6 +18,7 @@ import java.util.Collections; import java.util.List; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; @@ -26,6 +27,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; @@ -79,6 +81,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.core.parser.util.CharArraySet; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectMap; import org.eclipse.cdt.core.parser.util.ObjectSet; @@ -118,6 +121,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeParameter; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTypedefSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClass; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClassInstance; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalTemplateDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; @@ -483,9 +488,9 @@ public class CPPTemplates { final ICPPClassTemplate classTemplate = (ICPPClassTemplate) template; ICPPTemplateArgument[] args= createTemplateArgumentArray(id); - ICPPASTTemplateDeclaration tdecl= getTemplateDeclaration(id); - if (tdecl != null) { - if (hasDependentArgument(args)) { + if (hasDependentArgument(args)) { + ICPPASTTemplateDeclaration tdecl= getTemplateDeclaration(id); + if (tdecl != null) { if (argsAreTrivial(classTemplate.getTemplateParameters(), args)) { result= classTemplate; } else { @@ -830,10 +835,248 @@ public class CPPTemplates { * correspond to a template declaration. */ public static ICPPASTTemplateDeclaration getTemplateDeclaration(IASTName name) { - if (name == null) { + if (name == null) return null; - } + // first look for a related sequence of template declarations + ICPPASTInternalTemplateDeclaration tdecl= getInnerTemplateDeclaration(name); + if (tdecl == null) + return null; + + name= name.getLastName(); + IASTNode parent= name.getParent(); + if (!(parent instanceof ICPPASTQualifiedName)) { + if (parent instanceof ICPPASTTemplateId) { + return null; + } + // one name: use innermost template declaration + return tdecl; + } + + // last name can be associated even if it is not a template-id + final ICPPASTQualifiedName qname= (ICPPASTQualifiedName) parent; + final IASTName lastName = qname.getLastName(); + final boolean lastIsTemplate= lastName instanceof ICPPASTTemplateId || + tdecl.isAssociatedWithLastName(); + if (name == lastName) { + if (lastIsTemplate) { + return tdecl; + } + return null; + } + + // not the last name, search for the matching template declaration + if (!(name instanceof ICPPASTTemplateId)) + return null; + + if (lastIsTemplate) { + // skip one + tdecl= getDirectlyEnclosingTemplateDeclaration(tdecl); + } + final IASTName[] ns= qname.getNames(); + for (int i = ns.length-2; tdecl != null && i >= 0; i--) { + final IASTName n = ns[i]; + if (n == name) { + return tdecl; + } + if (n instanceof ICPPASTTemplateId) { + tdecl= getDirectlyEnclosingTemplateDeclaration(tdecl); + } + } + // not enough template declartaions + return null; + } + + public static void associateTemplateDeclarations(ICPPASTInternalTemplateDeclaration tdecl) { + // find innermost template decl + IASTDeclaration decl= tdecl.getDeclaration(); + while (decl instanceof ICPPASTInternalTemplateDeclaration) { + tdecl= (ICPPASTInternalTemplateDeclaration) decl; + decl= tdecl.getDeclaration(); + } + final ICPPASTInternalTemplateDeclaration innerMostTDecl= tdecl; + + // find name declared in nested declaration + IASTName name= getNameForDeclarationInTemplateDeclaration(decl); + + // count template declarations + int tdeclcount= 1; + IASTNode node= tdecl.getParent(); + while (node instanceof ICPPASTInternalTemplateDeclaration) { + tdeclcount++; + tdecl = (ICPPASTInternalTemplateDeclaration) node; + node= node.getParent(); + } + final ICPPASTInternalTemplateDeclaration outerMostTDecl= tdecl; + + // determine association of names with template declarations + boolean lastIsTemplate= true; + int additionalLevels= 0; + if (name instanceof ICPPASTQualifiedName) { + ICPPASTQualifiedName qname= (ICPPASTQualifiedName) name; + final boolean lastIsID = qname.getLastName() instanceof ICPPASTTemplateId; + + // count template-ids + int idcount= 0; + final IASTName[] ns= qname.getNames(); + for (int j = 0; j < ns.length; j++) { + final IASTName n = ns[j]; + if (n instanceof ICPPASTTemplateId) { + idcount++; + } + } + + if (lastIsID) { + additionalLevels= idcount-tdeclcount; + } else { + additionalLevels= idcount+1-tdeclcount; + if (additionalLevels > 0) { + // last name is probably not a template + additionalLevels--; + lastIsTemplate= false; + CharArraySet tparnames= collectTemplateParameterNames(outerMostTDecl); + int j= 0; + IASTName n; + for (int i = 0; i < ns.length; i++) { + n = ns[j]; + if (n instanceof ICPPASTTemplateId) { + // if we find a dependent id, there can be no explicit specialization. + ICPPASTTemplateId id= (ICPPASTTemplateId) n; + if (usesTemplateParameter(id, tparnames)) + break; + + if (j++ == additionalLevels) { + IBinding b= n.resolveBinding(); + if (b instanceof ICPPTemplateInstance && b instanceof ICPPClassType) { + try { + IScope s= ((ICPPClassType) b).getCompositeScope(); + if (!(s instanceof ICPPClassSpecializationScope)) { + // template-id of an explicit specialization. + // here we don't have a template declaration. (see 14.7.3.5) + additionalLevels++; + lastIsTemplate= true; + } + } catch (DOMException e) { + // assume that it is not an explicit instance + } + } + break; + } + } + } + } + } + } + + if (additionalLevels < 0) { + additionalLevels= 0; // too many template declarations + } + + // determine nesting level of parent + int level= 0; + node= outerMostTDecl.getParent(); + while (node != null) { + if (node instanceof ICPPASTInternalTemplateDeclaration) { + level= ((ICPPASTInternalTemplateDeclaration) node).getNestingLevel() + 1; + break; + } + node= node.getParent(); + } + + level += additionalLevels; + + tdecl= outerMostTDecl; + while(true) { + tdecl.setNestingLevel((short) level++); + node= tdecl.getDeclaration(); + if (node instanceof ICPPASTInternalTemplateDeclaration) { + tdecl= (ICPPASTInternalTemplateDeclaration) node; + } else { + break; + } + } + innerMostTDecl.setAssociatedWithLastName(lastIsTemplate); + } + + private static CharArraySet collectTemplateParameterNames(ICPPASTTemplateDeclaration tdecl) { + CharArraySet set= new CharArraySet(4); + while(true) { + ICPPASTTemplateParameter[] pars = tdecl.getTemplateParameters(); + for (ICPPASTTemplateParameter par : pars) { + IASTName name= CPPTemplates.getTemplateParameterName(par); + if (name != null) + set.put(name.toCharArray()); + } + final IASTNode next= tdecl.getDeclaration(); + if (next instanceof ICPPASTTemplateDeclaration) { + tdecl= (ICPPASTTemplateDeclaration) next; + } else { + break; + } + } + return set; + } + + private static boolean usesTemplateParameter(final ICPPASTTemplateId id, final CharArraySet names) { + final boolean[] result= {false}; + ASTVisitor v= new ASTVisitor(false) { + { shouldVisitNames= true;} + @Override + public int visit(IASTName name) { + if (name instanceof ICPPASTTemplateId) + return PROCESS_CONTINUE; + if (name instanceof ICPPASTQualifiedName) { + ICPPASTQualifiedName qname= (ICPPASTQualifiedName) name; + if (qname.isFullyQualified()) + return PROCESS_SKIP; + return PROCESS_CONTINUE; + } + + if (names.containsKey(name.toCharArray())) { + IASTNode parent= name.getParent(); + if (parent instanceof ICPPASTQualifiedName) { + if (((ICPPASTQualifiedName) parent).getNames()[0] != name) { + return PROCESS_CONTINUE; + } + result[0]= true; + return PROCESS_ABORT; + } else if (parent instanceof IASTIdExpression || + parent instanceof ICPPASTNamedTypeSpecifier) { + result[0]= true; + return PROCESS_ABORT; + } + } + return PROCESS_CONTINUE; + } + }; + id.accept(v); + return result[0]; + } + + private static IASTName getNameForDeclarationInTemplateDeclaration(IASTDeclaration decl) { + IASTName name= null; + if (decl instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) decl; + IASTDeclarator[] dtors = sdecl.getDeclarators(); + if (dtors != null && dtors.length > 0) { + name= CPPVisitor.findInnermostDeclarator(dtors[0]).getName(); + } else { + IASTDeclSpecifier declspec = sdecl.getDeclSpecifier(); + if (declspec instanceof IASTCompositeTypeSpecifier) { + name= ((IASTCompositeTypeSpecifier) declspec).getName(); + } else if (declspec instanceof IASTElaboratedTypeSpecifier) { + name= ((IASTElaboratedTypeSpecifier) declspec).getName(); + } + } + } else if (decl instanceof IASTFunctionDefinition) { + IASTFunctionDefinition fdef= (IASTFunctionDefinition) decl; + name= CPPVisitor.findInnermostDeclarator(fdef.getDeclarator()).getName(); + } + return name; + } + + + private static ICPPASTInternalTemplateDeclaration getInnerTemplateDeclaration(final IASTName name) { IASTNode parent = name.getParent(); while (parent instanceof IASTName) { parent = parent.getParent(); @@ -849,47 +1092,22 @@ public class CPPTemplates { parent = parent.getParent(); } } - if (!(parent instanceof IASTDeclaration)) { + if (!(parent instanceof IASTDeclaration)) return null; - } parent = parent.getParent(); - if (parent instanceof ICPPASTTemplateDeclaration) { - ICPPASTTemplateDeclaration templateDecl = (ICPPASTTemplateDeclaration) parent; + if (parent instanceof ICPPASTInternalTemplateDeclaration) + return (ICPPASTInternalTemplateDeclaration) parent; - 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(); - } else { - // 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; + } + + private static ICPPASTInternalTemplateDeclaration getDirectlyEnclosingTemplateDeclaration( + ICPPASTInternalTemplateDeclaration tdecl ) { + final IASTNode parent= tdecl.getParent(); + if (parent instanceof ICPPASTInternalTemplateDeclaration) + return (ICPPASTInternalTemplateDeclaration) parent; + return null; } 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 827d8fcd1bf..dfcb7d04a86 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 @@ -215,12 +215,23 @@ public class CPPVisitor extends ASTQueries { if (((IProblemBinding)binding).getID() == IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND) { IASTNode node = getContainingBlockItem(name.getParent()); ASTNodeProperty prop= node.getPropertyInParent(); + while (prop == ICPPASTTemplateDeclaration.OWNED_DECLARATION) { + node= node.getParent(); + prop= node.getPropertyInParent(); + } if (prop != IASTCompositeTypeSpecifier.MEMBER_DECLARATION && prop != ICPPASTNamespaceDefinition.OWNED_DECLARATION) { return binding; } - - if (getContainingScope(qname) != getContainingScope(name)) + IScope scope= getContainingScope(qname); + while (scope instanceof ICPPTemplateScope) { + try { + scope= scope.getParent(); + } catch (DOMException e) { + return binding; + } + } + if (scope != getContainingScope(name)) return binding; } } else { @@ -535,13 +546,19 @@ public class CPPVisitor extends ASTQueries { if (parent instanceof IASTTypeId) return CPPSemantics.resolveBinding(name); - // explicit instantiations + // function type for non-type template parameter ASTNodeProperty prop = parent.getPropertyInParent(); + if (prop == ICPPASTTemplateDeclaration.PARAMETER) { + return CPPTemplates.createBinding((ICPPASTTemplateParameter) parent); + } + + // explicit instantiations if (prop == ICPPASTExplicitTemplateInstantiation.OWNED_DECLARATION) return CPPSemantics.resolveBinding(name); // explicit specializations - if (prop == ICPPASTTemplateSpecialization.OWNED_DECLARATION) { + ICPPASTTemplateDeclaration tmplDecl= CPPTemplates.getTemplateDeclaration(name); + if (tmplDecl instanceof ICPPASTTemplateSpecialization) { IBinding b= CPPSemantics.resolveBinding(name); if (b instanceof ICPPInternalBinding) { if (parent instanceof ICPPASTFunctionDefinition) @@ -551,19 +568,14 @@ public class CPPVisitor extends ASTQueries { } return b; } - // function type for non-type template parameter - if (prop == ICPPASTTemplateDeclaration.PARAMETER) { - return CPPTemplates.createBinding((ICPPASTTemplateParameter) parent); - } - - // function declaration/defintion + + // function declaration/definition IBinding binding; - ICPPScope scope = (ICPPScope) getContainingScope((IASTNode) name); - boolean template= false; + final boolean template= tmplDecl != null; boolean isFriendDecl= false; + ICPPScope scope = (ICPPScope) getContainingScope((IASTNode) name); try { while (scope instanceof ICPPTemplateScope) { - template = true; scope= (ICPPScope) scope.getParent(); } if (parent instanceof IASTSimpleDeclaration && scope instanceof ICPPClassScope) { @@ -650,20 +662,7 @@ public class CPPVisitor extends ASTQueries { return function; } } - - if (binding instanceof IIndexBinding) { - ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name); - if (templateDecl != null) { - ICPPASTTemplateParameter[] params = templateDecl.getTemplateParameters(); - for (ICPPASTTemplateParameter param : params) { - IASTName paramName = CPPTemplates.getTemplateParameterName(param); - paramName.setBinding(null); - //unsetting the index bindings so that they - //can be re-resolved with normal bindings - } - } - } - + if (scope instanceof ICPPClassScope) { if (isConstructor(scope, funcDeclarator)) { binding = template ? (ICPPConstructor) new CPPConstructorTemplate(name) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index 208943df4da..7aafa326c8c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -208,7 +208,8 @@ class LookupData { if (p1 instanceof IASTDeclarator) { IASTNode p2= CPPVisitor.findOutermostDeclarator((IASTDeclarator) p1).getParent(); if (p2 instanceof IASTSimpleDeclaration || p2 instanceof IASTFunctionDefinition) { - return p2.getParent() instanceof ICPPASTTemplateSpecialization; + ICPPASTTemplateDeclaration tmplDecl = CPPTemplates.getTemplateDeclaration(n); + return tmplDecl instanceof ICPPASTTemplateSpecialization; } } return false;