1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-04 14:55:41 +02:00

Create implicit name wrapping a problem binding for an invalid

constructor call.
This commit is contained in:
Sergey Prigogin 2013-04-02 21:04:50 -07:00
parent 30081f07d5
commit f987bfe27c
6 changed files with 44 additions and 43 deletions

View file

@ -1561,6 +1561,18 @@ public class AST2CPPTests extends AST2TestBase {
assertSame(ctor, ctor2); assertSame(ctor, ctor2);
} }
// struct A {
// A(int x, int y);
// };
//
// void test() {
// A a("hi", 5, 10);
// }
public void testInvalidImplicitConstructorCall() throws Exception {
BindingAssertionHelper bh = getAssertionHelper();
bh.assertImplicitName("a", 1, IProblemBinding.class);
}
// struct A { // struct A {
// A(int x); // A(int x);
// }; // };
@ -8391,9 +8403,7 @@ public class AST2CPPTests extends AST2TestBase {
// fH({1}); // H(G(1)) // fH({1}); // H(G(1))
// } // }
public void testListInitialization_302412f() throws Exception { public void testListInitialization_302412f() throws Exception {
IProblemBinding problem; BindingAssertionHelper bh= getAssertionHelper();
String code= getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
bh.assertProblem("f({1,1})", 1); bh.assertProblem("f({1,1})", 1);
bh.assertImplicitName("F({1,1})", 1, ICPPConstructor.class); bh.assertImplicitName("F({1,1})", 1, ICPPConstructor.class);
bh.assertNonProblem("fF({1,1})", 2); bh.assertNonProblem("fF({1,1})", 2);
@ -8402,13 +8412,9 @@ public class AST2CPPTests extends AST2TestBase {
bh.assertNonProblem("fG({1})", 2); bh.assertNonProblem("fG({1})", 2);
bh.assertImplicitName("H(1)", 1, ICPPConstructor.class); bh.assertImplicitName("H(1)", 1, ICPPConstructor.class);
bh.assertNoImplicitName("H({1})", 1); IASTImplicitName n= bh.assertImplicitName("H({1})", 1, IProblemBinding.class);
// TODO(nathanridge): Perhaps we should store implicit names even if they IProblemBinding problem= (IProblemBinding) n.resolveBinding();
// resolve to ProblemBindings. Then we can do the stronger check in the assertEquals(IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, problem.getID());
// 3 commented lines below.
//IASTImplicitName n= bh.assertImplicitName("H({1})", 1, IProblemBinding.class);
//problem= (IProblemBinding) n.resolveBinding();
//assertEquals(IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, problem.getID());
bh.assertProblem("fH(1)", 2); bh.assertProblem("fH(1)", 2);
bh.assertNonProblem("fH({1})", 2); bh.assertNonProblem("fH({1})", 2);
} }

View file

@ -27,34 +27,32 @@ public interface IASTImplicitName extends IASTName {
* {@inheritDoc} * {@inheritDoc}
* Redeclared with strengthened postcondition. * Redeclared with strengthened postcondition.
* *
* Will not return null or a problem binding. * Will not return {@code null}, but may return a problem binding, for example for an implicit
* Implicit names are not generated unless they resolve to something. * constructor call.
*/ */
@Override @Override
public IBinding resolveBinding(); public IBinding resolveBinding();
/** /**
* Returns true if this node is an alternate. * Returns {@code true} if this node is an alternate.
* *
* Sometimes more than one implicit name is generated for the same binding * Sometimes more than one implicit name is generated for the same binding but with different
* but with different offsets, when this happens the additional names * offsets, when this happens the additional names generated are considered alternates.
* generated are considered alternates.
* *
* @see ASTVisitor#shouldVisitImplicitNameAlternates * @see ASTVisitor#shouldVisitImplicitNameAlternates
*/ */
public boolean isAlternate(); public boolean isAlternate();
/** /**
* Convenience method that returns true if this * Convenience method that returns true if this name represents an overloaded operator.
* name represents an overloaded operator.
*/ */
public boolean isOperator(); public boolean isOperator();
/** /**
* This method is not supported on implicit names. * This method is not supported on implicit names.
* *
* Implicit names are not copied when an AST is copied, * Implicit names are not copied when an AST is copied, instead the implicit names are
* instead the implicit names are regenerated when needed. * regenerated when needed.
* *
* @throws UnsupportedOperationException always * @throws UnsupportedOperationException always
*/ */

View file

@ -241,7 +241,7 @@ public class CPPASTConstructorChainInitializer extends ASTNode implements
@Override @Override
public IASTImplicitName[] getImplicitNames() { public IASTImplicitName[] getImplicitNames() {
if (implicitNames == null) { if (implicitNames == null) {
ICPPConstructor ctor = CPPSemantics.findImplicitlyCalledConstructor(this); IBinding ctor = CPPSemantics.findImplicitlyCalledConstructor(this);
if (ctor == null) { if (ctor == null) {
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
} else { } else {

View file

@ -28,11 +28,11 @@ import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.parser.util.ArrayUtil; 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.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
@ -305,7 +305,7 @@ public class CPPASTDeclarator extends ASTNode implements ICPPASTDeclarator, IAST
@Override @Override
public IASTImplicitName[] getImplicitNames() { public IASTImplicitName[] getImplicitNames() {
if (implicitNames == null) { if (implicitNames == null) {
ICPPConstructor ctor = CPPSemantics.findImplicitlyCalledConstructor(this); IBinding ctor = CPPSemantics.findImplicitlyCalledConstructor(this);
if (ctor == null) { if (ctor == null) {
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
} else { } else {

View file

@ -28,10 +28,10 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
@ -175,7 +175,7 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression
} }
CPPASTImplicitName constructorName = null; CPPASTImplicitName constructorName = null;
ICPPConstructor constructor = CPPSemantics.findImplicitlyCalledConstructor(this); IBinding constructor = CPPSemantics.findImplicitlyCalledConstructor(this);
if (constructor != null) { if (constructor != null) {
constructorName = new CPPASTImplicitName(constructor.getNameCharArray(), this); constructorName = new CPPASTImplicitName(constructor.getNameCharArray(), this);
constructorName.setBinding(constructor); constructorName.setBinding(constructor);

View file

@ -3074,9 +3074,9 @@ public class CPPSemantics {
} }
/** /**
* Returns constructor called by a declarator, or <code>null</code> if no constructor is called. * Returns constructor called by a declarator, or {@code null} if no constructor is called.
*/ */
public static ICPPConstructor findImplicitlyCalledConstructor(final ICPPASTDeclarator declarator) { public static IBinding findImplicitlyCalledConstructor(final ICPPASTDeclarator declarator) {
if (declarator.getNestedDeclarator() != null) if (declarator.getNestedDeclarator() != null)
return null; return null;
IASTDeclarator dtor= ASTQueries.findOutermostDeclarator(declarator); IASTDeclarator dtor= ASTQueries.findOutermostDeclarator(declarator);
@ -3100,17 +3100,17 @@ public class CPPSemantics {
/** /**
* Returns constructor called by a class member initializer in a constructor initializer chain. * Returns constructor called by a class member initializer in a constructor initializer chain.
* Returns <code>null</code> if no constructor is called. * Returns {@code null} if no constructor is called.
*/ */
public static ICPPConstructor findImplicitlyCalledConstructor(ICPPASTConstructorChainInitializer initializer) { public static IBinding findImplicitlyCalledConstructor(ICPPASTConstructorChainInitializer initializer) {
return findImplicitlyCalledConstructor(initializer.getMemberInitializerId(), initializer.getInitializer()); return findImplicitlyCalledConstructor(initializer.getMemberInitializerId(), initializer.getInitializer());
} }
/** /**
* Returns constructor called by a variable declarator or an initializer in a constructor initializer * Returns constructor called by a variable declarator or an initializer in a constructor
* chain. Returns <code>null</code> if no constructor is called. * initializer chain. Returns {@code null} if no constructor is called.
*/ */
private static ICPPConstructor findImplicitlyCalledConstructor(IASTName name, IASTInitializer initializer) { private static IBinding findImplicitlyCalledConstructor(IASTName name, IASTInitializer initializer) {
IBinding binding = name.resolveBinding(); IBinding binding = name.resolveBinding();
if (!(binding instanceof ICPPVariable)) if (!(binding instanceof ICPPVariable))
return null; return null;
@ -3125,7 +3125,7 @@ public class CPPSemantics {
return findImplicitlyCalledConstructor((ICPPClassType) type, initializer, name); return findImplicitlyCalledConstructor((ICPPClassType) type, initializer, name);
} }
public static ICPPConstructor findImplicitlyCalledConstructor(ICPPASTNewExpression expr) { public static IBinding findImplicitlyCalledConstructor(ICPPASTNewExpression expr) {
IType type = getNestedType(expr.getExpressionType(), TDEF | REF | CVTYPE); IType type = getNestedType(expr.getExpressionType(), TDEF | REF | CVTYPE);
if (!(type instanceof IPointerType)) if (!(type instanceof IPointerType))
return null; return null;
@ -3137,7 +3137,7 @@ public class CPPSemantics {
return null; return null;
} }
private static ICPPConstructor findImplicitlyCalledConstructor(ICPPClassType type, IASTInitializer initializer, private static IBinding findImplicitlyCalledConstructor(ICPPClassType type, IASTInitializer initializer,
IASTNode typeId) { IASTNode typeId) {
try { try {
if (initializer instanceof IASTEqualsInitializer) { if (initializer instanceof IASTEqualsInitializer) {
@ -3157,7 +3157,7 @@ public class CPPSemantics {
if (c.converts()) { if (c.converts()) {
ICPPFunction f = c.getUserDefinedConversion(); ICPPFunction f = c.getUserDefinedConversion();
if (f instanceof ICPPConstructor) if (f instanceof ICPPConstructor)
return (ICPPConstructor) f; return f;
// If a conversion is used, the constructor is elided. // If a conversion is used, the constructor is elided.
} }
} }
@ -3169,7 +3169,7 @@ public class CPPSemantics {
if (c.converts()) { if (c.converts()) {
ICPPFunction f = c.getUserDefinedConversion(); ICPPFunction f = c.getUserDefinedConversion();
if (f instanceof ICPPConstructor) if (f instanceof ICPPConstructor)
return (ICPPConstructor) f; return f;
} }
} }
} else if (initializer instanceof ICPPASTConstructorInitializer) { } else if (initializer instanceof ICPPASTConstructorInitializer) {
@ -3190,7 +3190,7 @@ public class CPPSemantics {
return null; return null;
} }
private static ICPPConstructor findImplicitlyCalledConstructor(ICPPClassType classType, private static IBinding findImplicitlyCalledConstructor(ICPPClassType classType,
ICPPASTConstructorInitializer initializer, IASTNode typeId) { ICPPASTConstructorInitializer initializer, IASTNode typeId) {
final IASTInitializerClause[] arguments = initializer.getArguments(); final IASTInitializerClause[] arguments = initializer.getArguments();
CPPASTName astName = new CPPASTName(); CPPASTName astName = new CPPASTName();
@ -3204,15 +3204,12 @@ public class CPPSemantics {
data.setFunctionArguments(false, arguments); data.setFunctionArguments(false, arguments);
data.qualified = true; data.qualified = true;
data.foundItems = ClassTypeHelper.getConstructors(classType, typeId); data.foundItems = ClassTypeHelper.getConstructors(classType, typeId);
IBinding binding;
try { try {
binding = resolveAmbiguities(data); return resolveAmbiguities(data);
if (binding instanceof ICPPConstructor)
return (ICPPConstructor) binding;
} catch (DOMException e) { } catch (DOMException e) {
}
return null; return null;
} }
}
public static ICPPFunction findImplicitlyCalledDestructor(ICPPASTDeleteExpression expr) { public static ICPPFunction findImplicitlyCalledDestructor(ICPPASTDeleteExpression expr) {
IType t = getTypeOfPointer(expr.getOperand().getExpressionType()); IType t = getTypeOfPointer(expr.getOperand().getExpressionType());