diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index f93e2a4bf87..d09424f3ced 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -7404,6 +7404,53 @@ public class AST2TemplateTests extends AST2TestBase { parseAndCheckBindings(); } + // template + // static void test(int); + // + // template + // static int test(...); + // + // struct A {}; + // + // int waldo(int p); + // + // int x = waldo(test(0)); + public void testSfinaeInConstructorCall_430230() throws Exception { + parseAndCheckBindings(); + } + + // template + // static void test(int); + // + // template + // static int test(...); + // + // struct A {}; + // + // int waldo(int p); + // + // int x = waldo(test(0)); + public void testSfinaeInNewExpression_430230() throws Exception { + parseAndCheckBindings(); + } + + // template + // static void test(int); + // + // template + // static int test(...); + // + // struct A { + // A() = delete; + // }; + // + // int waldo(int p); + // + // int x = waldo(test(0)); + public void testSfinaeInNewExpressionWithDeletedConstructor_430230() throws Exception { + parseAndCheckBindings(); + } + // template // struct M { // template diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java index aebbb8ca50d..919b9c777f9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java index 05120e9fc19..26c6ccba41c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java @@ -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