1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 17:56:01 +02:00

Bug 430230 - Invalid constructor call is ignored by SFINAE template

resolution.
This commit is contained in:
Sergey Prigogin 2014-03-13 16:28:20 -07:00
parent d5db93891d
commit aa2ae49463
3 changed files with 110 additions and 10 deletions

View file

@ -7404,6 +7404,53 @@ public class AST2TemplateTests extends AST2TestBase {
parseAndCheckBindings(); parseAndCheckBindings();
} }
// template<typename T, typename = decltype(T(0))>
// static void test(int);
//
// template<typename>
// static int test(...);
//
// struct A {};
//
// int waldo(int p);
//
// int x = waldo(test<A>(0));
public void testSfinaeInConstructorCall_430230() throws Exception {
parseAndCheckBindings();
}
// template<typename T, typename = decltype(new T(0))>
// static void test(int);
//
// template<typename>
// static int test(...);
//
// struct A {};
//
// int waldo(int p);
//
// int x = waldo(test<A>(0));
public void testSfinaeInNewExpression_430230() throws Exception {
parseAndCheckBindings();
}
// template<typename T, typename = decltype(new T)>
// static void test(int);
//
// template<typename>
// static int test(...);
//
// struct A {
// A() = delete;
// };
//
// int waldo(int p);
//
// int x = waldo(test<A>(0));
public void testSfinaeInNewExpressionWithDeletedConstructor_430230() throws Exception {
parseAndCheckBindings();
}
// template <typename> // template <typename>
// struct M { // struct M {
// template <typename... Args> // template <typename... Args>

View file

@ -31,16 +31,16 @@ import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBinding; 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.ICPPASTInitializerClause;
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.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;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.c.CASTExpressionList; import org.eclipse.cdt.internal.core.dom.parser.c.CASTExpressionList;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId;
import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.Assert;
@ -267,11 +267,19 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression
@Override @Override
public ICPPEvaluation getEvaluation() { public ICPPEvaluation getEvaluation() {
if (fEvaluation == null) { if (fEvaluation == null) {
IType t= CPPVisitor.createType(getTypeId()); IType t = CPPVisitor.createType(getTypeId());
if (t instanceof IArrayType) { if (t instanceof IArrayType) {
t= ((IArrayType) t).getType(); t = ((IArrayType) t).getType();
} }
fEvaluation= new EvalFixed(new CPPPointerType(t), PRVALUE, Value.UNKNOWN); ICPPEvaluation[] arguments = ICPPEvaluation.EMPTY_ARRAY;
if (initializer instanceof ICPPASTConstructorInitializer) {
IASTInitializerClause[] args = ((ICPPASTConstructorInitializer) initializer).getArguments();
arguments= new ICPPEvaluation[args.length];
for (int i = 0; i < arguments.length; i++) {
arguments[i] = ((ICPPASTInitializerClause) args[i]).getEvaluation();
}
}
fEvaluation = EvalTypeId.createForNewExpression(t, this, arguments);
} }
return fEvaluation; return fEvaluation;
} }

View file

@ -14,17 +14,23 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromReturnType; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromReturnType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
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.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -34,19 +40,29 @@ import org.eclipse.core.runtime.CoreException;
public class EvalTypeId extends CPPDependentEvaluation { public class EvalTypeId extends CPPDependentEvaluation {
private final IType fInputType; private final IType fInputType;
private final ICPPEvaluation[] fArguments; private final ICPPEvaluation[] fArguments;
private final boolean fRepresentsNewExpression;
private IType fOutputType; private IType fOutputType;
public EvalTypeId(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) { public EvalTypeId(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) {
this(type, findEnclosingTemplate(pointOfDefinition), arguments); this(type, findEnclosingTemplate(pointOfDefinition), false, arguments);
} }
public EvalTypeId(IType type, IBinding templateDefinition, ICPPEvaluation... arguments) { public EvalTypeId(IType type, IBinding templateDefinition, ICPPEvaluation... arguments) {
this(type, templateDefinition, false, arguments);
}
private EvalTypeId(IType type, IBinding templateDefinition, boolean forNewExpression, ICPPEvaluation... arguments) {
super(templateDefinition); super(templateDefinition);
if (arguments == null) if (arguments == null)
throw new NullPointerException("arguments"); //$NON-NLS-1$ throw new NullPointerException("arguments"); //$NON-NLS-1$
fInputType= type; fInputType= type;
fArguments= arguments; fArguments= arguments;
fRepresentsNewExpression = forNewExpression;
}
public static EvalTypeId createForNewExpression(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) {
return new EvalTypeId(type, findEnclosingTemplate(pointOfDefinition), true, arguments);
} }
public IType getInputType() { public IType getInputType() {
@ -78,7 +94,11 @@ public class EvalTypeId extends CPPDependentEvaluation {
private IType computeType() { private IType computeType() {
if (CPPTemplates.isDependentType(fInputType)) if (CPPTemplates.isDependentType(fInputType))
return new TypeOfDependentExpression(this); return new TypeOfDependentExpression(this);
return typeFromReturnType(fInputType);
IType type = typeFromReturnType(fInputType);
if (fRepresentsNewExpression)
return new CPPPointerType(type);
return type;
} }
@Override @Override
@ -87,6 +107,8 @@ public class EvalTypeId extends CPPDependentEvaluation {
return Value.create(this); return Value.create(this);
if (isTypeDependent()) if (isTypeDependent())
return Value.create(this); return Value.create(this);
if (fRepresentsNewExpression)
return Value.UNKNOWN;
if (fOutputType instanceof ICPPClassType) { if (fOutputType instanceof ICPPClassType) {
// TODO(sprigogin): Simulate execution of a ctor call. // TODO(sprigogin): Simulate execution of a ctor call.
return Value.UNKNOWN; return Value.UNKNOWN;
@ -123,6 +145,8 @@ public class EvalTypeId extends CPPDependentEvaluation {
short firstBytes = ITypeMarshalBuffer.EVAL_TYPE_ID; short firstBytes = ITypeMarshalBuffer.EVAL_TYPE_ID;
if (includeValue) if (includeValue)
firstBytes |= ITypeMarshalBuffer.FLAG1; firstBytes |= ITypeMarshalBuffer.FLAG1;
if (fRepresentsNewExpression)
firstBytes |= ITypeMarshalBuffer.FLAG2;
buffer.putShort(firstBytes); buffer.putShort(firstBytes);
buffer.marshalType(fInputType); buffer.marshalType(fInputType);
@ -149,7 +173,8 @@ public class EvalTypeId extends CPPDependentEvaluation {
args = ICPPEvaluation.EMPTY_ARRAY; // arguments must not be null args = ICPPEvaluation.EMPTY_ARRAY; // arguments must not be null
} }
IBinding templateDefinition= buffer.unmarshalBinding(); IBinding templateDefinition= buffer.unmarshalBinding();
return new EvalTypeId(type, templateDefinition, args); boolean forNewExpression = (firstBytes & ITypeMarshalBuffer.FLAG2) != 0;
return new EvalTypeId(type, templateDefinition, forNewExpression, args);
} }
@Override @Override
@ -159,7 +184,27 @@ public class EvalTypeId extends CPPDependentEvaluation {
IType type = CPPTemplates.instantiateType(fInputType, tpMap, packOffset, within, point); IType type = CPPTemplates.instantiateType(fInputType, tpMap, packOffset, within, point);
if (args == fArguments && type == fInputType) if (args == fArguments && type == fInputType)
return this; return this;
return new EvalTypeId(type, getTemplateDefinition(), args);
if (!CPPTemplates.isDependentType(type) && type instanceof ICPPClassType) {
// Check the constructor call and return EvalFixed.INCOMPLETE to indicate a substitution
// failure if the call cannot be resolved.
ICPPClassType classType = (ICPPClassType) type;
LookupData data = new LookupData(classType.getNameCharArray(), null, point);
ICPPConstructor[] constructors = classType.getConstructors();
data.foundItems = constructors;
data.setFunctionArguments(false, fArguments);
try {
IBinding binding = CPPSemantics.resolveFunction(data, constructors, true);
if (binding == null || binding instanceof IProblemBinding ||
binding instanceof ICPPFunction && ((ICPPFunction) binding).isDeleted()) {
return EvalFixed.INCOMPLETE;
}
} catch (DOMException e) {
CCorePlugin.log(e);
return EvalFixed.INCOMPLETE;
}
}
return new EvalTypeId(type, getTemplateDefinition(), fRepresentsNewExpression, args);
} }
@Override @Override
@ -178,7 +223,7 @@ public class EvalTypeId extends CPPDependentEvaluation {
} }
if (args == fArguments) if (args == fArguments)
return this; return this;
return new EvalTypeId(fInputType, getTemplateDefinition(), args); return new EvalTypeId(fInputType, getTemplateDefinition(), fRepresentsNewExpression, args);
} }
@Override @Override