mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 302412: Change resolution of constructors for initializations.
This commit is contained in:
parent
dc68630fb6
commit
53b6af27b0
7 changed files with 150 additions and 102 deletions
|
@ -4863,4 +4863,17 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
assertTrue(inst.isExplicitSpecialization());
|
||||
}
|
||||
|
||||
// template <typename T> struct CT {
|
||||
// CT ();
|
||||
// };
|
||||
// template<> struct CT<int> {
|
||||
// CT ();
|
||||
// int value_;
|
||||
// };
|
||||
// CT<int>::CT() : value_(0) {
|
||||
// }
|
||||
public void testConstructorOfExplicitSpecialization() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()};
|
||||
|
|
Loading…
Add table
Reference in a new issue