From 4ec1115e9c37c82c51968481b18ced86f010b427 Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Sat, 8 Jul 2023 16:34:14 +1000 Subject: [PATCH] [#455] If constructor arguments fail to resolve, propagate failure This change prevents invalid partial specialisations from being chosen when instantiating a template in cases where the expression for the type/value of a template parameter involves a constructor call. --- .../parser/tests/ast2/AST2TemplateTests.java | 38 +++++++++++++++++++ .../parser/cpp/semantics/CPPSemantics.java | 3 ++ .../dom/parser/cpp/semantics/EvalTypeId.java | 11 ++++++ 3 files changed, 52 insertions(+) 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 05e61ccd100..e2a6fbaf2f7 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 @@ -6865,6 +6865,44 @@ public void testSfinae_b() throws Exception { parseAndCheckBindings(); } + // template + // struct A + // { + // using type = int *; + // }; + // + // template + // struct A + // { + // using type = typename T::p; + // }; + // + // class d { }; + // + // class B { + // public: + // using p = typename A::type; + // + // public: + // explicit B(p) {} + // }; + // + // int *ip = nullptr; + // B b1 { ip }; + // B::p jp = nullptr; + public void testSfinae_c() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(); + + IVariable varB1 = bh.assertNonProblem("b1"); + IType bcls = bh.assertNonProblem("B"); + IVariable varJp = bh.assertNonProblem("jp"); + IVariable varIp = bh.assertNonProblem("ip"); + + assertFalse(varB1.getInitialValue() instanceof IProblemBinding); + assertTrue(varB1.getType().isSameType(bcls)); + assertTrue(varIp.getType().isSameType(varJp.getType())); + } + // template // struct is_pod { // static const bool value = __is_pod(T); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index e33e73f9a14..48e0de0e97d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -218,6 +218,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; +import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression; @@ -5067,6 +5068,8 @@ public static boolean isUsingPromiscuousBindingResolution() { */ public static IType getDeclTypeForEvaluation(ICPPEvaluation eval) { IType expressionType = eval.getType(); + if (expressionType instanceof ProblemType) + return expressionType; boolean namedEntity = eval instanceof EvalBinding || eval instanceof EvalMemberAccess; if (!namedEntity && !(expressionType instanceof ICPPReferenceType)) { switch (eval.getValueCategory()) { 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 8064200f971..09533b43e4a 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 @@ -26,6 +26,7 @@ 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.IProblemType; import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; @@ -42,6 +43,7 @@ import org.eclipse.cdt.internal.core.dom.parser.DependentValue; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; @@ -416,6 +418,15 @@ public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { if (args == fArguments && type == fInputType) return this; + // If type or arguments failed to resolve, return INCOMPLETE for SFINAE purposes + if (type instanceof ProblemBinding) + return EvalFixed.INCOMPLETE; + for (ICPPEvaluation arg : args) { + if (arg.getType() instanceof IProblemType) { + return EvalFixed.INCOMPLETE; + } + } + EvalTypeId result = new EvalTypeId(type, getTemplateDefinition(), fRepresentsNewExpression, fUsesBracedInitList, args);