From 40954074fbb4958a2891dccfbf8f8392a0482fff Mon Sep 17 00:00:00 2001 From: "Igor V. Kovalenko" Date: Mon, 27 Mar 2023 02:36:22 +0300 Subject: [PATCH] Do not error out failing to resolve function in dependend context Detect if function set failed to resolve while instantiating for template-id which still has dependend arguments. Since resolution still can succeed later via ADL when template-id is fully instantiated, do not error out immediately and return original evaluation to allow trying to instantiate later. --- .../parser/tests/ast2/AST2TemplateTests.java | 28 +++++++++++++++++++ .../cpp/semantics/EvalFunctionCall.java | 17 ++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) 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 36503540caa..70682f4527c 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 @@ -8052,6 +8052,34 @@ public void testSfinaeInDefaultArgument() throws Exception { parseAndCheckBindings(); } + // namespace std { + // template _Up __declval(int); + // template _Tp __declval(long); + // template auto declval() noexcept -> decltype(__declval<_Tp>(0)); + // } + // + // template + // using is_augmented_t = decltype (is_augmented (std::declval ())); + // + // template > + // constexpr T f(T x) { return x; } + // + // template > + // constexpr T g(T x) { return x; } + // + // enum E { E1 = 42 }; + // void is_augmented(E *); + // + // void is_augmented(int *); + // + // constexpr int value_via_adl = f(E1); // ADL via enumeration argument finds is_augmented(E*) + // constexpr int value_no_adl = g(int(E1)); // Error: no ADL performed, is_augmented(int*) is not found + public void testSfinaeInDependentContext() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(); + bh.assertVariableValue("value_via_adl", 42); + bh.assertProblem("g(int(E1))", 1); + } + // typedef char (&no_tag)[1]; // typedef char (&yes_tag)[2]; // diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java index 5c30a9bd92e..da5165efdf0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java @@ -25,12 +25,14 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IVariable; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; @@ -39,6 +41,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.CompositeValue; import org.eclipse.cdt.internal.core.dom.parser.DependentValue; @@ -242,8 +245,20 @@ public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { EvalFunctionSet functionSet = (EvalFunctionSet) args[0]; args[0] = functionSet.resolveFunction(Arrays.copyOfRange(args, 1, args.length)); - // Propagate instantiation errors for SFINAE purposes. if (args[0] == EvalFixed.INCOMPLETE) { + // Do not error if instantiation context is still a dependent template-id, + // as function set can still be resolved later via ADL. + if (CPPSemantics.getCurrentLookupPoint() instanceof ICPPASTTemplateId templateId) { + for (IASTNode argument : templateId.getTemplateArguments()) { + if (argument instanceof IASTTypeId typeId) { + if (CPPVisitor.createType(typeId) instanceof ICPPTemplateParameter) { + return this; + } + } + } + } + + // Propagate instantiation errors for SFINAE purposes. return args[0]; }