Author: Timm Bäder
Date: 2024-06-29T19:55:29+02:00
New Revision: d957da83791930a3c23f4f936ca7c7644c4b07a4

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

LOG: [clang][Interp] Allow taking the address of a non-const global reference

This is not a read, but the GetGlobal op before failed if the reference
we were taking a pointer of was non-const. Use GetGlobalUnchecked
instead.

Added: 
    

Modified: 
    clang/lib/AST/Interp/Compiler.cpp
    clang/lib/AST/Interp/Interp.h
    clang/test/AST/Interp/references.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index e21e2c0eb8b6a..8b6f7f644a778 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -4906,8 +4906,11 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, 
const Expr *E) {
       return this->emitGetLocal(PT_Ptr, Offset, E);
     return this->emitGetPtrLocal(Offset, E);
   } else if (auto GlobalIndex = P.getGlobal(D)) {
-    if (IsReference)
-      return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);
+    if (IsReference) {
+      if (!Ctx.getLangOpts().CPlusPlus11)
+        return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);
+      return this->emitGetGlobalUnchecked(classifyPrim(E), *GlobalIndex, E);
+    }
 
     return this->emitGetPtrGlobal(*GlobalIndex, E);
   } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 916d268aa4f09..6c9246f692204 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1255,7 +1255,10 @@ bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) 
{
 /// Same as GetGlobal, but without the checks.
 template <PrimType Name, class T = typename PrimConv<Name>::T>
 bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) {
-  auto *B = S.P.getGlobal(I);
+  const Pointer &Ptr = S.P.getPtrGlobal(I);
+  if (!Ptr.isInitialized())
+    return false;
+  const Block *B = S.P.getGlobal(I);
   S.Stk.push<T>(B->deref<T>());
   return true;
 }

diff  --git a/clang/test/AST/Interp/references.cpp 
b/clang/test/AST/Interp/references.cpp
index efb756545b4aa..9a790dc75d730 100644
--- a/clang/test/AST/Interp/references.cpp
+++ b/clang/test/AST/Interp/references.cpp
@@ -130,3 +130,8 @@ const char (&nonextended_string_ref)[3] = {"hi"};
 static_assert(nonextended_string_ref[0] == 'h', "");
 static_assert(nonextended_string_ref[1] == 'i', "");
 static_assert(nonextended_string_ref[2] == '\0', "");
+
+/// This isa non-constant context. Reading A is not allowed,
+/// but taking its address is.
+int &&A = 12;
+int arr[!&A];


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to