[clang] 2bed2a7 - [clang][Interp] Emit dummy values for unknown C variables (#66749)

via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 7 07:00:23 PDT 2023


Author: Timm Baeder
Date: 2023-10-07T16:00:19+02:00
New Revision: 2bed2a7a5cc133cf2405cdea14bc52c16bb697dd

URL: https://github.com/llvm/llvm-project/commit/2bed2a7a5cc133cf2405cdea14bc52c16bb697dd
DIFF: https://github.com/llvm/llvm-project/commit/2bed2a7a5cc133cf2405cdea14bc52c16bb697dd.diff

LOG: [clang][Interp] Emit dummy values for unknown C variables (#66749)

We can't load anything from them, but we can still take their address or
return them as lvalues.

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/Interp.cpp
    clang/lib/AST/Interp/Program.cpp
    clang/lib/AST/Interp/Program.h
    clang/test/AST/Interp/c.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 3cf8bf874b1d210..02b35583636bf13 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2547,6 +2547,9 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
       // Retry.
       return this->VisitDeclRefExpr(E);
     }
+
+    if (std::optional<unsigned> I = P.getOrCreateDummy(D))
+      return this->emitGetPtrGlobal(*I, E);
   }
 
   return this->emitInvalidDeclRef(E, E);

diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 8e851595963184c..a4d6844ebe61722 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -139,7 +139,7 @@ bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
   if (!Ptr.isExtern())
     return true;
 
-  if (!S.checkingPotentialConstantExpression()) {
+  if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
     const auto *VD = Ptr.getDeclDesc()->asValueDecl();
     const SourceInfo &Loc = S.Current->getSource(OpPC);
     S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;

diff  --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp
index 63901d90703dc46..65e170881e313d7 100644
--- a/clang/lib/AST/Interp/Program.cpp
+++ b/clang/lib/AST/Interp/Program.cpp
@@ -138,17 +138,16 @@ std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
   return std::nullopt;
 }
 
-std::optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) {
-
+std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *PD) {
   // Dedup blocks since they are immutable and pointers cannot be compared.
   if (auto It = DummyParams.find(PD);
       It != DummyParams.end())
     return It->second;
 
-  auto &ASTCtx = Ctx.getASTContext();
   // Create a pointer to an incomplete array of the specified elements.
-  QualType ElemTy = PD->getType()->castAs<PointerType>()->getPointeeType();
-  QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
+  QualType ElemTy = PD->getType();
+  QualType Ty =
+      Ctx.getASTContext().getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
 
   if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) {
     DummyParams[PD] = *Idx;

diff  --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/Interp/Program.h
index d880a738e733e31..d843fa06538f514 100644
--- a/clang/lib/AST/Interp/Program.h
+++ b/clang/lib/AST/Interp/Program.h
@@ -82,8 +82,8 @@ class Program final {
   std::optional<unsigned> getOrCreateGlobal(const ValueDecl *VD,
                                             const Expr *Init = nullptr);
 
-  /// Returns or creates a dummy value for parameters.
-  std::optional<unsigned> getOrCreateDummy(const ParmVarDecl *PD);
+  /// Returns or creates a dummy value for unknown declarations.
+  std::optional<unsigned> getOrCreateDummy(const ValueDecl *PD);
 
   /// Creates a global and returns its index.
   std::optional<unsigned> createGlobal(const ValueDecl *VD, const Expr *E);
@@ -208,7 +208,7 @@ class Program final {
   llvm::DenseMap<const RecordDecl *, Record *> Records;
 
   /// Dummy parameter to generate pointers from.
-  llvm::DenseMap<const ParmVarDecl *, unsigned> DummyParams;
+  llvm::DenseMap<const ValueDecl *, unsigned> DummyParams;
 
   /// Creates a new descriptor.
   template <typename... Ts>

diff  --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 47058b8a93203b6..384912f7bcab17c 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -28,15 +28,25 @@ const int b = 3;
 _Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \
                             // pedantic-expected-warning {{not an integer constant expression}}
 
+/// FIXME: The new interpreter is missing the "initializer of 'c' unknown" diagnostics.
 const int c; // ref-note {{declared here}} \
-             // pedantic-ref-note {{declared here}} \
-             // expected-note {{declared here}} \
-             // pedantic-expected-note {{declared here}}
+             // pedantic-ref-note {{declared here}}
 _Static_assert(c == 0, ""); // ref-error {{not an integral constant expression}} \
                             // ref-note {{initializer of 'c' is unknown}} \
                             // pedantic-ref-error {{not an integral constant expression}} \
                             // pedantic-ref-note {{initializer of 'c' is unknown}} \
                             // expected-error {{not an integral constant expression}} \
-                            // expected-note {{initializer of 'c' is unknown}} \
-                            // pedantic-expected-error {{not an integral constant expression}} \
-                            // pedantic-expected-note {{initializer of 'c' is unknown}}
+                            // pedantic-expected-error {{not an integral constant expression}}
+
+_Static_assert(&c != 0, ""); // ref-warning {{always true}} \
+                             // pedantic-ref-warning {{always true}} \
+                             // pedantic-ref-warning {{is a GNU extension}} \
+                             // expected-warning {{always true}} \
+                             // pedantic-expected-warning {{always true}} \
+                             // pedantic-expected-warning {{is a GNU extension}}
+_Static_assert(&a != 0, ""); // ref-warning {{always true}} \
+                             // pedantic-ref-warning {{always true}} \
+                             // pedantic-ref-warning {{is a GNU extension}} \
+                             // expected-warning {{always true}} \
+                             // pedantic-expected-warning {{always true}} \
+                             // pedantic-expected-warning {{is a GNU extension}}


        


More information about the cfe-commits mailing list