[PATCH] D113859: [Sema] Fix consteval function calls with value-dependent args

Léo Lam via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 14 12:20:24 PST 2021

leoetlino created this revision.
leoetlino added a reviewer: rsmith.
Herald added a subscriber: kristof.beyls.
leoetlino requested review of this revision.
Herald added a project: clang.

If any arguments of a consteval function call are value-dependent,
the call cannot be evaluated until instantiation.

This patch fixes Sema::CheckForImmediateInvocation so we don't attempt
to evaluate consteval function calls too early (before instantiation).

This fixes things like:

  consteval int f(int n) { return n; }
  template <int M>
  constexpr int broken() {
    return f(M);

Without the value-dependency checks, what happens is that the constant
expression evaluation engine is called on the following expression:

  ConstantExpr 'int'
  `-CallExpr 'int'
    |-ImplicitCastExpr 'int (*)(int)' <FunctionToPointerDecay>
    | `-DeclRefExpr 'int (int)' lvalue Function 'f' 'int (int)'
    `-DeclRefExpr 'int' NonTypeTemplateParm 'M' 'int'

which obviously fails when it tries to evaluate M.

  rG LLVM Github Monorepo



Index: clang/test/SemaCXX/cxx2a-consteval.cpp
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -61,6 +61,20 @@
 struct E : C {
   consteval ~E() {} // expected-error {{cannot be declared consteval}}
+template <int X>
+constexpr int callConstevalWithNameDependentArg() {
+  return f1(X);
+template <int X>
+constexpr int callConstevalWithNameDependentArgAsVariable() {
+  constexpr int x = X;
+  return f1(x);
+auto foo = callConstevalWithNameDependentArg<42>();
 consteval int main() { // expected-error {{'main' is not allowed to be declared consteval}}
Index: clang/lib/Sema/SemaExpr.cpp
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -16654,11 +16654,22 @@
   /// It's OK if this fails; we'll also remove this in
   /// HandleImmediateInvocations, but catching it here allows us to avoid
   /// walking the AST looking for it in simple cases.
-  if (auto *Call = dyn_cast<CallExpr>(E.get()->IgnoreImplicit()))
+  if (auto *Call = dyn_cast<CallExpr>(E.get()->IgnoreImplicit())) {
     if (auto *DeclRef =
+    // If any arguments are value-dependent, we will not be able to evaluate
+    // the function call until instantiation.
+    if (Call->isValueDependent())
+      return E;
+    for (Expr *Arg : Call->arguments()) {
+      if (Arg->isValueDependent())
+        return E;
+    }
+  }
   E = MaybeCreateExprWithCleanups(E);
   ConstantExpr *Res = ConstantExpr::Create(

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D113859.387123.patch
Type: text/x-patch
Size: 1746 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20211114/16c2a619/attachment.bin>

More information about the cfe-commits mailing list