mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 430230 - Invalid constructor call is ignored by SFINAE template
resolution.
This commit is contained in:
parent
d5db93891d
commit
aa2ae49463
3 changed files with 110 additions and 10 deletions
|
@ -7404,6 +7404,53 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
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>
|
||||
// struct M {
|
||||
// template <typename... Args>
|
||||
|
|
|
@ -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.IType;
|
||||
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.ICPPFunction;
|
||||
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.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.cpp.semantics.CPPSemantics;
|
||||
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;
|
||||
|
||||
|
||||
|
@ -267,11 +267,19 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression
|
|||
@Override
|
||||
public ICPPEvaluation getEvaluation() {
|
||||
if (fEvaluation == null) {
|
||||
IType t= CPPVisitor.createType(getTypeId());
|
||||
IType t = CPPVisitor.createType(getTypeId());
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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.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.IASTNode;
|
||||
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.IValue;
|
||||
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.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
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.ITypeMarshalBuffer;
|
||||
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.core.runtime.CoreException;
|
||||
|
||||
|
@ -34,19 +40,29 @@ import org.eclipse.core.runtime.CoreException;
|
|||
public class EvalTypeId extends CPPDependentEvaluation {
|
||||
private final IType fInputType;
|
||||
private final ICPPEvaluation[] fArguments;
|
||||
private final boolean fRepresentsNewExpression;
|
||||
private IType fOutputType;
|
||||
|
||||
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) {
|
||||
this(type, templateDefinition, false, arguments);
|
||||
}
|
||||
|
||||
private EvalTypeId(IType type, IBinding templateDefinition, boolean forNewExpression, ICPPEvaluation... arguments) {
|
||||
super(templateDefinition);
|
||||
if (arguments == null)
|
||||
throw new NullPointerException("arguments"); //$NON-NLS-1$
|
||||
|
||||
fInputType= type;
|
||||
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() {
|
||||
|
@ -78,7 +94,11 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
private IType computeType() {
|
||||
if (CPPTemplates.isDependentType(fInputType))
|
||||
return new TypeOfDependentExpression(this);
|
||||
return typeFromReturnType(fInputType);
|
||||
|
||||
IType type = typeFromReturnType(fInputType);
|
||||
if (fRepresentsNewExpression)
|
||||
return new CPPPointerType(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,6 +107,8 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
return Value.create(this);
|
||||
if (isTypeDependent())
|
||||
return Value.create(this);
|
||||
if (fRepresentsNewExpression)
|
||||
return Value.UNKNOWN;
|
||||
if (fOutputType instanceof ICPPClassType) {
|
||||
// TODO(sprigogin): Simulate execution of a ctor call.
|
||||
return Value.UNKNOWN;
|
||||
|
@ -123,6 +145,8 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
short firstBytes = ITypeMarshalBuffer.EVAL_TYPE_ID;
|
||||
if (includeValue)
|
||||
firstBytes |= ITypeMarshalBuffer.FLAG1;
|
||||
if (fRepresentsNewExpression)
|
||||
firstBytes |= ITypeMarshalBuffer.FLAG2;
|
||||
|
||||
buffer.putShort(firstBytes);
|
||||
buffer.marshalType(fInputType);
|
||||
|
@ -149,7 +173,8 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
args = ICPPEvaluation.EMPTY_ARRAY; // arguments must not be null
|
||||
}
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalTypeId(type, templateDefinition, args);
|
||||
boolean forNewExpression = (firstBytes & ITypeMarshalBuffer.FLAG2) != 0;
|
||||
return new EvalTypeId(type, templateDefinition, forNewExpression, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -159,7 +184,27 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
IType type = CPPTemplates.instantiateType(fInputType, tpMap, packOffset, within, point);
|
||||
if (args == fArguments && type == fInputType)
|
||||
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
|
||||
|
@ -178,7 +223,7 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
}
|
||||
if (args == fArguments)
|
||||
return this;
|
||||
return new EvalTypeId(fInputType, getTemplateDefinition(), args);
|
||||
return new EvalTypeId(fInputType, getTemplateDefinition(), fRepresentsNewExpression, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Add table
Reference in a new issue