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 810ef3a3a18..a4997194576 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 @@ -4863,4 +4863,17 @@ public class AST2TemplateTests extends AST2BaseTest { assertTrue(inst.isExplicitSpecialization()); } + // template struct CT { + // CT (); + // }; + // template<> struct CT { + // CT (); + // int value_; + // }; + // CT::CT() : value_(0) { + // } + public void testConstructorOfExplicitSpecialization() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java index 7f549f48bdd..815c7a67c60 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 IBM Corporation and others. + * Copyright (c) 2005, 2010 IBM Corporation 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 @@ -65,9 +65,10 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat public IBinding getBinding(IASTName name, boolean forceResolve, IIndexFileSet fileSet) throws DOMException { char[] c = name.getLookupKey(); - if (CharArrayUtils.equals(c, specialClass.getNameCharArray()) && !CPPClassScope.isConstructorReference(name)) { - return specialClass; - } + if (CharArrayUtils.equals(c, specialClass.getNameCharArray()) + && !CPPClassScope.shallReturnConstructors(name, false)) { + return specialClass; + } ICPPClassType specialized = specialClass.getSpecializedBinding(); IScope classScope = specialized.getCompositeScope(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java index 9cc8414232a..0e8f0e6a363 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation 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 @@ -222,9 +222,6 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { compName= ((ICPPASTTemplateId) compName).getTemplateName(); } if (CharArrayUtils.equals(c, compName.getLookupKey())) { - if (isConstructorReference(name)) { - return CPPSemantics.resolveAmbiguities(name, getConstructors(name, resolve)); - } //9.2 ... The class-name is also inserted into the scope of the class itself return compName.resolveBinding(); } @@ -244,7 +241,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { IBinding[] result = null; if ((!prefixLookup && CharArrayUtils.equals(c, compName.getLookupKey())) || (prefixLookup && CharArrayUtils.equals(compName.getLookupKey(), 0, c.length, c, true))) { - if (isConstructorReference(name)) { + if (shallReturnConstructors(name, prefixLookup)) { result = (IBinding[]) ArrayUtil.addAll(IBinding.class, result, getConstructors(name, resolve)); } //9.2 ... The class-name is also inserted into the scope of the class itself @@ -332,26 +329,31 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { return super.find(name); } - public static boolean isConstructorReference(IASTName name) { - if (name.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; - IASTNode node = name.getParent(); - if (node instanceof ICPPASTTemplateId) - return false; - if (node instanceof ICPPASTQualifiedName) { - if (((ICPPASTQualifiedName) node).getLastName() == name) - node = node.getParent(); - else - return false; - } - if (node instanceof IASTDeclSpecifier) { - IASTNode parent = node.getParent(); - if (parent instanceof IASTTypeId && parent.getParent() instanceof ICPPASTNewExpression) - return true; - return false; - } else if (node instanceof IASTFieldReference) { - return false; - } - return true; + public static boolean shallReturnConstructors(IASTName name, boolean isPrefixLookup) { + if (!isPrefixLookup) + return CPPVisitor.isConstructorDeclaration(name); + + if (name.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) + return false; + + IASTNode node = name.getParent(); + if (node instanceof ICPPASTTemplateId) + return false; + if (node instanceof ICPPASTQualifiedName) { + if (((ICPPASTQualifiedName) node).getLastName() == name) + node = node.getParent(); + else + return false; + } + if (node instanceof IASTDeclSpecifier) { + IASTNode parent = node.getParent(); + if (parent instanceof IASTTypeId && parent.getParent() instanceof ICPPASTNewExpression) + return true; + return false; + } else if (node instanceof IASTFieldReference) { + return false; + } + return true; } /* (non-Javadoc) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 8a4e9386b34..522ad073065 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -342,11 +342,11 @@ public class CPPSemantics { } } - if (data.considerConstructors) { - if (binding instanceof ICPPClassType) { - if (binding instanceof IIndexBinding) { - binding= data.tu.mapToAST((ICPPClassType) binding); - } + if (binding instanceof ICPPClassType) { + if (convertClassToConstructor(data.astName)) { + if (binding instanceof IIndexBinding) { + binding= data.tu.mapToAST((ICPPClassType) binding); + } ICPPClassType cls= (ICPPClassType) binding; try { @@ -363,14 +363,10 @@ public class CPPSemantics { if (cls instanceof ICPPDeferredClassInstance) { binding= new CPPUnknownConstructor(cls); } else { - // Force resolution of constructor bindings - final ICPPConstructor[] constructors = cls.getConstructors(); - if (constructors.length > 0) { - binding= CPPSemantics.resolveAmbiguities(data.astName, constructors); - } + binding= selectConstructor(cls, data); } } catch (DOMException e) { - binding = e.getProblem(); + return e.getProblem(); } } } @@ -432,10 +428,10 @@ public class CPPSemantics { } else if (parent instanceof ICPPASTUnaryExpression && ((ICPPASTUnaryExpression) parent).getOperator() == IASTUnaryExpression.op_sizeofParameterPack) { // argument of sizeof... can be a type - } else if (data.considerConstructors && - (binding instanceof ICPPUnknownType || binding instanceof ITypedef || binding instanceof IEnumeration)) { - // constructor or simple-type constructor - } else { + } else if ((binding instanceof ICPPUnknownType || binding instanceof ITypedef || binding instanceof IEnumeration) + && convertClassToConstructor(data.astName)) { + // constructor or simple-type constructor + } else { binding= new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings()); } @@ -488,6 +484,58 @@ public class CPPSemantics { return binding; } + private static boolean convertClassToConstructor(IASTName name) { + if (name == null) + return false; + final ASTNodeProperty propertyInParent = name.getPropertyInParent(); + if (propertyInParent == CPPSemantics.STRING_LOOKUP_PROPERTY || propertyInParent == null) + return false; + + if (propertyInParent == ICPPASTTemplateId.TEMPLATE_NAME) + return false; + + IASTNode parent= name.getParent(); + if (parent instanceof ICPPASTQualifiedName) { + if (((ICPPASTQualifiedName) parent).getLastName() != name) + return false; + parent= parent.getParent(); + } + if (parent instanceof ICPPASTConstructorChainInitializer) { + return true; + } + if (parent instanceof IASTExpression) { + ASTNodeProperty propInParent= parent.getPropertyInParent(); + if (parent instanceof IASTIdExpression) { + parent= parent.getParent(); + } + while (parent instanceof IASTUnaryExpression + && ((IASTUnaryExpression) parent).getOperator() == IASTUnaryExpression.op_bracketedPrimary) { + propInParent = parent.getPropertyInParent(); + parent= parent.getParent(); + } + if (parent instanceof IASTFunctionCallExpression && propInParent == IASTFunctionCallExpression.FUNCTION_NAME) { + return true; + } + } else if (parent instanceof ICPPASTNamedTypeSpecifier) { + parent= parent.getParent(); + if (parent instanceof IASTTypeId && parent.getParent() instanceof ICPPASTNewExpression) { + IASTDeclarator dtor = ((IASTTypeId) parent).getAbstractDeclarator(); + if (dtor != null && dtor.getPointerOperators().length == 0) + return true; + } + } + return false; + } + + private static IBinding selectConstructor(ICPPClassType cls, LookupData data) throws DOMException { + // Force resolution of constructor bindings + final ICPPConstructor[] constructors= cls.getConstructors(); + if (constructors.length > 0) { + return CPPSemantics.resolveAmbiguities(data.astName, constructors); + } + return cls; + } + private static void doKoenigLookup(LookupData data) throws DOMException { data.ignoreUsingDirectives = true; data.forceQualified = true; @@ -1707,7 +1755,7 @@ public class CPPSemantics { if (type == null) { type = temp; - } else if (type != temp) { + } else if (!type.equals(temp)) { int c = compareByRelevance(data, type, temp); if (c < 0) { type= temp; 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 42324e7a76e..99e8812dc6d 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 @@ -726,6 +726,45 @@ public class CPPVisitor extends ASTQueries { return isConstructor(clsName, declarator); } + public static boolean isConstructorDeclaration(IASTName name) { + if (name == null) + return false; + final ASTNodeProperty propertyInParent = name.getPropertyInParent(); + if (propertyInParent == CPPSemantics.STRING_LOOKUP_PROPERTY || propertyInParent == null) + return false; + IASTNode parent = name.getParent(); + if (parent instanceof ICPPASTTemplateId) { + name= (IASTName) parent; + parent= name.getParent(); + } + if (parent instanceof ICPPASTQualifiedName) { + if (((ICPPASTQualifiedName) parent).getLastName() != name) + return false; + name= (IASTName) parent; + parent= name.getParent(); + } + if (parent instanceof IASTDeclarator) { + IASTDeclarator dtor= findTypeRelevantDeclarator((IASTDeclarator) parent); + if (dtor instanceof ICPPASTFunctionDeclarator) { + if (name instanceof ICPPASTQualifiedName) { + IASTName[] names = ((ICPPASTQualifiedName)name).getNames(); + if (names.length >= 2) { + return CPPVisitor.isConstructor(names[names.length - 2], dtor); + } + } else { + while(parent != null && !(parent instanceof ICPPASTCompositeTypeSpecifier)) { + parent= parent.getParent(); + } + if (parent instanceof ICPPASTCompositeTypeSpecifier) { + IASTName compName= ((ICPPASTCompositeTypeSpecifier) parent).getName().getLastName(); + return CPPVisitor.isConstructor(compName, dtor); + } + } + } + } + return false; + } + public static boolean isConstructor(IASTName parentName, IASTDeclarator declarator) { if (declarator == null || !(declarator instanceof IASTFunctionDeclarator)) return false; 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 a6739ee5254..dda37a4790c 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 @@ -37,8 +37,6 @@ import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTTypeId; -import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IScope; @@ -51,10 +49,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; @@ -98,7 +93,6 @@ public class LookupData { public boolean contentAssist = false; public boolean prefixLookup = false; public boolean typesOnly = false; - public boolean considerConstructors = false; /** For lookup of unknown bindings the point of declaration can be reversed. */ public boolean checkPointOfDecl= true; /** For field references or qualified names, enclosing template declarations are ignored. */ @@ -118,7 +112,6 @@ public class LookupData { astName = n; tu= (CPPASTTranslationUnit) astName.getTranslationUnit(); typesOnly = typesOnly(astName); - considerConstructors = considerConstructors(); checkWholeClassScope = checkWholeClassScope(n); } @@ -251,51 +244,6 @@ public class LookupData { return false; } - private boolean considerConstructors() { - if (astName == null) return false; - final ASTNodeProperty propertyInParent = astName.getPropertyInParent(); - if (propertyInParent == CPPSemantics.STRING_LOOKUP_PROPERTY || propertyInParent == null) return false; - IASTNode p1 = astName.getParent(); - IASTNode p2 = p1.getParent(); - - if (p1 instanceof ICPPASTQualifiedName) { - if (((ICPPASTQualifiedName) p1).getLastName() != astName) - return false; - if (p2 instanceof ICPPASTFunctionDeclarator) { - IASTName[] names = ((ICPPASTQualifiedName)p1).getNames(); - if (names.length >= 2 && names[names.length - 1] == astName) - return CPPVisitor.isConstructor(names[names.length - 2], (IASTDeclarator) p2); - } - if (p2 != null) { - p1= p2; - p2= p1.getParent(); - } - } - if (p1 instanceof ICPPASTConstructorChainInitializer) { - return true; - } - if (p1 instanceof IASTExpression) { - ASTNodeProperty prop = p1.getPropertyInParent(); - if (p1 instanceof IASTIdExpression) { - p1= p1.getParent(); - } - while (p1 instanceof IASTUnaryExpression && ((IASTUnaryExpression) p1).getOperator() == IASTUnaryExpression.op_bracketedPrimary) { - prop = p1.getPropertyInParent(); - p1= p1.getParent(); - } - if (p1 instanceof IASTFunctionCallExpression && prop == IASTFunctionCallExpression.FUNCTION_NAME) { - return true; - } - } else if (p1 instanceof ICPPASTNamedTypeSpecifier && p2 instanceof IASTTypeId) { - if (p2.getParent() instanceof ICPPASTNewExpression) { - IASTDeclarator dtor = ((IASTTypeId) p2).getAbstractDeclarator(); - if (dtor != null && dtor.getPointerOperators().length == 0) - return true; - } - } - return false; - } - public boolean qualified() { if (forceQualified) return true; if (astName == null) return false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java index 60500cfb063..ee5f3443d55 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassScope.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 QNX Software Systems and others. + * Copyright (c) 2005, 2010 QNX Software Systems 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 @@ -121,9 +121,6 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { try { final char[] nameChars = name.getSimpleID(); if (CharArrayUtils.equals(fBinding.getNameCharArray(), nameChars)) { - if (CPPClassScope.isConstructorReference(name)){ - return CPPSemantics.resolveAmbiguities(name, fBinding.getConstructors()); - } //9.2 ... The class-name is also inserted into the scope of the class itself return getClassNameBinding(); } @@ -155,7 +152,7 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { final char[] nameChars = name.getSimpleID(); if (!prefixLookup) { if (CharArrayUtils.equals(fBinding.getNameCharArray(), nameChars)) { - if (CPPClassScope.isConstructorReference(name)){ + if (CPPClassScope.shallReturnConstructors(name, prefixLookup)){ return fBinding.getConstructors(); } return new IBinding[] {getClassNameBinding()};