[clang] 6a8ab12 - [clang][Interp] Properly emit call ops to invalid functions

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 15 11:17:59 PST 2024


Author: Timm Bäder
Date: 2024-02-15T20:17:51+01:00
New Revision: 6a8ab129300bfdf7cc58e023b06e0aada4458205

URL: https://github.com/llvm/llvm-project/commit/6a8ab129300bfdf7cc58e023b06e0aada4458205
DIFF: https://github.com/llvm/llvm-project/commit/6a8ab129300bfdf7cc58e023b06e0aada4458205.diff

LOG: [clang][Interp] Properly emit call ops to invalid functions

Just like everywhere else, we can't just abort compilation because
a function is invalid. We need to emit the Call op and let later
interpretation handle the failure.

This fixes a long standing FIXME comment.

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/Interp.cpp
    clang/test/AST/Interp/cxx20.cpp
    clang/test/AST/Interp/records.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index db6d818eef334b..e4b48c4e946f13 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2835,14 +2835,6 @@ bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
     const Function *Func = getFunction(FuncDecl);
     if (!Func)
       return false;
-    // If the function is being compiled right now, this is a recursive call.
-    // In that case, the function can't be valid yet, even though it will be
-    // later.
-    // If the function is already fully compiled but not constexpr, it was
-    // found to be faulty earlier on, so bail out.
-    if (Func->isFullyCompiled() && !Func->isConstexpr())
-      return false;
-
     assert(HasRVO == Func->hasRVO());
 
     bool HasQualifier = false;

diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 2338f88569db8b..2a51f18adf02c5 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -477,6 +477,11 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
         if (!DiagDecl->isDefined() && S.checkingPotentialConstantExpression())
           return false;
 
+        // If the declaration is defined _and_ declared 'constexpr', the below
+        // diagnostic doesn't add anything useful.
+        if (DiagDecl->isDefined() && DiagDecl->isConstexpr())
+          return false;
+
         S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
           << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
         S.Note(DiagDecl->getLocation(), diag::note_declared_at);

diff  --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp
index 0af553a77892e6..0fc5d977b59f4c 100644
--- a/clang/test/AST/Interp/cxx20.cpp
+++ b/clang/test/AST/Interp/cxx20.cpp
@@ -230,15 +230,13 @@ namespace ConstThis {
                       // ref-note {{declared const here}}
     int a;
   public:
-    constexpr Foo() { // expected-note {{declared here}}
+    constexpr Foo() {
       this->a = 10;
       T = 13; // expected-error {{cannot assign to non-static data member 'T' with const-qualified type}} \
               // ref-error {{cannot assign to non-static data member 'T' with const-qualified type}}
     }
   };
   constexpr Foo F; // expected-error {{must be initialized by a constant expression}} \
-                   // FIXME: The following note is wrong. \
-                   // expected-note {{undefined constructor 'Foo' cannot be used in a constant expression}} \
                    // ref-error {{must be initialized by a constant expression}}
 
 

diff  --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp
index 93da831f3bda0a..62f1f1d6e426c3 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1232,10 +1232,9 @@ namespace InheritedConstructor {
 namespace InvalidCtorInitializer {
   struct X {
     int Y;
-    constexpr X() // expected-note {{declared here}}
+    constexpr X()
         : Y(fo_o_()) {} // both-error {{use of undeclared identifier 'fo_o_'}}
   };
   // no crash on evaluating the constexpr ctor.
-  constexpr int Z = X().Y; // both-error {{constexpr variable 'Z' must be initialized by a constant expression}} \
-                           // expected-note {{undefined constructor 'X'}}
+  constexpr int Z = X().Y; // both-error {{constexpr variable 'Z' must be initialized by a constant expression}}
 }


        


More information about the cfe-commits mailing list