mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-25 18:05:33 +02:00
Create implicit name wrapping a problem binding for an invalid
constructor call.
This commit is contained in:
parent
30081f07d5
commit
f987bfe27c
6 changed files with 44 additions and 43 deletions
|
@ -1276,7 +1276,7 @@ public class AST2CPPTests extends AST2TestBase {
|
|||
assertInstances(collector, x2, 1);
|
||||
}
|
||||
|
||||
// class A { };
|
||||
// class A {};
|
||||
public void testImplicitConstructors() throws Exception {
|
||||
IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP);
|
||||
|
||||
|
@ -1561,6 +1561,18 @@ public class AST2CPPTests extends AST2TestBase {
|
|||
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 {
|
||||
// A(int x);
|
||||
// };
|
||||
|
@ -8391,9 +8403,7 @@ public class AST2CPPTests extends AST2TestBase {
|
|||
// fH({1}); // H(G(1))
|
||||
// }
|
||||
public void testListInitialization_302412f() throws Exception {
|
||||
IProblemBinding problem;
|
||||
String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
BindingAssertionHelper bh= getAssertionHelper();
|
||||
bh.assertProblem("f({1,1})", 1);
|
||||
bh.assertImplicitName("F({1,1})", 1, ICPPConstructor.class);
|
||||
bh.assertNonProblem("fF({1,1})", 2);
|
||||
|
@ -8402,13 +8412,9 @@ public class AST2CPPTests extends AST2TestBase {
|
|||
bh.assertNonProblem("fG({1})", 2);
|
||||
|
||||
bh.assertImplicitName("H(1)", 1, ICPPConstructor.class);
|
||||
bh.assertNoImplicitName("H({1})", 1);
|
||||
// TODO(nathanridge): Perhaps we should store implicit names even if they
|
||||
// resolve to ProblemBindings. Then we can do the stronger check in the
|
||||
// 3 commented lines below.
|
||||
//IASTImplicitName n= bh.assertImplicitName("H({1})", 1, IProblemBinding.class);
|
||||
//problem= (IProblemBinding) n.resolveBinding();
|
||||
//assertEquals(IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, problem.getID());
|
||||
IASTImplicitName n= bh.assertImplicitName("H({1})", 1, IProblemBinding.class);
|
||||
IProblemBinding problem= (IProblemBinding) n.resolveBinding();
|
||||
assertEquals(IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, problem.getID());
|
||||
bh.assertProblem("fH(1)", 2);
|
||||
bh.assertNonProblem("fH({1})", 2);
|
||||
}
|
||||
|
|
|
@ -27,34 +27,32 @@ public interface IASTImplicitName extends IASTName {
|
|||
* {@inheritDoc}
|
||||
* Redeclared with strengthened postcondition.
|
||||
*
|
||||
* Will not return null or a problem binding.
|
||||
* Implicit names are not generated unless they resolve to something.
|
||||
* Will not return {@code null}, but may return a problem binding, for example for an implicit
|
||||
* constructor call.
|
||||
*/
|
||||
@Override
|
||||
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
|
||||
* but with different offsets, when this happens the additional names
|
||||
* generated are considered alternates.
|
||||
* Sometimes more than one implicit name is generated for the same binding but with different
|
||||
* offsets, when this happens the additional names generated are considered alternates.
|
||||
*
|
||||
* @see ASTVisitor#shouldVisitImplicitNameAlternates
|
||||
*/
|
||||
public boolean isAlternate();
|
||||
|
||||
/**
|
||||
* Convenience method that returns true if this
|
||||
* name represents an overloaded operator.
|
||||
* Convenience method that returns true if this name represents an overloaded operator.
|
||||
*/
|
||||
public boolean isOperator();
|
||||
|
||||
/**
|
||||
* This method is not supported on implicit names.
|
||||
*
|
||||
* Implicit names are not copied when an AST is copied,
|
||||
* instead the implicit names are regenerated when needed.
|
||||
* Implicit names are not copied when an AST is copied, instead the implicit names are
|
||||
* regenerated when needed.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
|
|
|
@ -241,7 +241,7 @@ public class CPPASTConstructorChainInitializer extends ASTNode implements
|
|||
@Override
|
||||
public IASTImplicitName[] getImplicitNames() {
|
||||
if (implicitNames == null) {
|
||||
ICPPConstructor ctor = CPPSemantics.findImplicitlyCalledConstructor(this);
|
||||
IBinding ctor = CPPSemantics.findImplicitlyCalledConstructor(this);
|
||||
if (ctor == null) {
|
||||
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||
} else {
|
||||
|
|
|
@ -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.IASTSimpleDeclaration;
|
||||
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.ICPPASTLinkageSpecification;
|
||||
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.ICPPConstructor;
|
||||
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.ASTQueries;
|
||||
|
@ -305,7 +305,7 @@ public class CPPASTDeclarator extends ASTNode implements ICPPASTDeclarator, IAST
|
|||
@Override
|
||||
public IASTImplicitName[] getImplicitNames() {
|
||||
if (implicitNames == null) {
|
||||
ICPPConstructor ctor = CPPSemantics.findImplicitlyCalledConstructor(this);
|
||||
IBinding ctor = CPPSemantics.findImplicitlyCalledConstructor(this);
|
||||
if (ctor == null) {
|
||||
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||
} else {
|
||||
|
|
|
@ -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.IASTTypeId;
|
||||
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.cpp.ICPPASTConstructorInitializer;
|
||||
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.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||
|
@ -175,7 +175,7 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression
|
|||
}
|
||||
|
||||
CPPASTImplicitName constructorName = null;
|
||||
ICPPConstructor constructor = CPPSemantics.findImplicitlyCalledConstructor(this);
|
||||
IBinding constructor = CPPSemantics.findImplicitlyCalledConstructor(this);
|
||||
if (constructor != null) {
|
||||
constructorName = new CPPASTImplicitName(constructor.getNameCharArray(), this);
|
||||
constructorName.setBinding(constructor);
|
||||
|
|
|
@ -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)
|
||||
return null;
|
||||
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 <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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns constructor called by a variable declarator or an initializer in a constructor initializer
|
||||
* chain. Returns <code>null</code> if no constructor is called.
|
||||
* Returns constructor called by a variable declarator or an initializer in a constructor
|
||||
* 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();
|
||||
if (!(binding instanceof ICPPVariable))
|
||||
return null;
|
||||
|
@ -3125,7 +3125,7 @@ public class CPPSemantics {
|
|||
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);
|
||||
if (!(type instanceof IPointerType))
|
||||
return null;
|
||||
|
@ -3137,7 +3137,7 @@ public class CPPSemantics {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static ICPPConstructor findImplicitlyCalledConstructor(ICPPClassType type, IASTInitializer initializer,
|
||||
private static IBinding findImplicitlyCalledConstructor(ICPPClassType type, IASTInitializer initializer,
|
||||
IASTNode typeId) {
|
||||
try {
|
||||
if (initializer instanceof IASTEqualsInitializer) {
|
||||
|
@ -3157,7 +3157,7 @@ public class CPPSemantics {
|
|||
if (c.converts()) {
|
||||
ICPPFunction f = c.getUserDefinedConversion();
|
||||
if (f instanceof ICPPConstructor)
|
||||
return (ICPPConstructor) f;
|
||||
return f;
|
||||
// If a conversion is used, the constructor is elided.
|
||||
}
|
||||
}
|
||||
|
@ -3169,7 +3169,7 @@ public class CPPSemantics {
|
|||
if (c.converts()) {
|
||||
ICPPFunction f = c.getUserDefinedConversion();
|
||||
if (f instanceof ICPPConstructor)
|
||||
return (ICPPConstructor) f;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
} else if (initializer instanceof ICPPASTConstructorInitializer) {
|
||||
|
@ -3190,7 +3190,7 @@ public class CPPSemantics {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static ICPPConstructor findImplicitlyCalledConstructor(ICPPClassType classType,
|
||||
private static IBinding findImplicitlyCalledConstructor(ICPPClassType classType,
|
||||
ICPPASTConstructorInitializer initializer, IASTNode typeId) {
|
||||
final IASTInitializerClause[] arguments = initializer.getArguments();
|
||||
CPPASTName astName = new CPPASTName();
|
||||
|
@ -3204,14 +3204,11 @@ public class CPPSemantics {
|
|||
data.setFunctionArguments(false, arguments);
|
||||
data.qualified = true;
|
||||
data.foundItems = ClassTypeHelper.getConstructors(classType, typeId);
|
||||
IBinding binding;
|
||||
try {
|
||||
binding = resolveAmbiguities(data);
|
||||
if (binding instanceof ICPPConstructor)
|
||||
return (ICPPConstructor) binding;
|
||||
return resolveAmbiguities(data);
|
||||
} catch (DOMException e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ICPPFunction findImplicitlyCalledDestructor(ICPPASTDeleteExpression expr) {
|
||||
|
|
Loading…
Add table
Reference in a new issue