1
0
Fork 0
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:
Markus Schorn 2010-03-11 13:05:12 +00:00
parent dc68630fb6
commit 53b6af27b0
7 changed files with 150 additions and 102 deletions

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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()};