Author: Timm Baeder
Date: 2026-10-30T12:56:48+01:00
New Revision: 3950f2b61b82cf1d75c4b6c6d76cc72eda793167

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

LOG: [clang][bytecode] Fix bitcast from nullptr_t to array (#237165)

First, we need to make sure that initialize() on an arrayroot pointer
does not initialize the first element of the array; second, it is
possible for such an array to not have an associated FieldDecl, as is
the case in the materialized temporary array in the attached reproducer.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Compiler.cpp
    clang/lib/AST/ByteCode/EvaluationResult.cpp
    clang/lib/AST/ByteCode/Pointer.cpp
    clang/lib/AST/ByteCode/Pointer.h
    clang/test/AST/ByteCode/builtin-bit-cast.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 079c24344f21a..71f761f58aed2 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1310,7 +1310,9 @@ bool Compiler<Emitter>::VisitImaginaryLiteral(const 
ImaginaryLiteral *E) {
     return false;
   if (!this->emitInitElem(SubExprT, 0, SubExpr))
     return false;
-  return this->visitArrayElemInit(1, SubExpr, SubExprT);
+  if (!this->visitArrayElemInit(1, SubExpr, SubExprT))
+    return false;
+  return this->emitFinishInit(E);
 }
 
 template <class Emitter>
@@ -1884,7 +1886,7 @@ bool Compiler<Emitter>::VisitComplexBinOp(const 
BinaryOperator *E) {
         return this->emitPopPtr(E);
     }
   }
-  return true;
+  return this->emitFinishInit(E);
 }
 
 template <class Emitter>

diff  --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp 
b/clang/lib/AST/ByteCode/EvaluationResult.cpp
index 70f64568483fd..d6dbd8c80f32f 100644
--- a/clang/lib/AST/ByteCode/EvaluationResult.cpp
+++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp
@@ -62,7 +62,8 @@ static bool CheckArrayInitialized(InterpState &S, 
SourceLocation Loc,
   if (BaseDesc->isPrimitiveArray()) {
     if (BasePtr.allElementsInitialized())
       return true;
-    DiagnoseUninitializedSubobject(S, Loc, BasePtr.getField());
+    if (const FieldDecl *F = BasePtr.getField())
+      DiagnoseUninitializedSubobject(S, Loc, F);
     return false;
   }
   const Descriptor *ElemDesc = BaseDesc->ElemDesc;

diff  --git a/clang/lib/AST/ByteCode/Pointer.cpp 
b/clang/lib/AST/ByteCode/Pointer.cpp
index 3890f2ed2f91d..35ffa4e68373a 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -814,7 +814,7 @@ void PtrView::initialize() const {
 
   const Descriptor *Desc = getFieldDesc();
   assert(Desc);
-  if (Desc->isPrimitiveArray()) {
+  if (Offset != Base && Desc->isPrimitiveArray()) {
     if (Desc->getNumElems() != 0)
       initializeElement(getIndex());
     return;

diff  --git a/clang/lib/AST/ByteCode/Pointer.h 
b/clang/lib/AST/ByteCode/Pointer.h
index 0fc540cdd8858..8cedb529b73a0 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -315,7 +315,7 @@ struct PtrView {
     assert(Pointee && "Cannot check if null pointer was initialized");
     const Descriptor *Desc = getFieldDesc();
     assert(Desc);
-    if (Desc->isPrimitiveArray())
+    if (Offset != Base && Desc->isPrimitiveArray())
       return isElementInitialized(getIndex());
 
     if (Base == 0)

diff  --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp 
b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
index 2aaf84f9130c7..8588b4217a4d9 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
@@ -616,3 +616,11 @@ namespace StringInDoBitCast {
   static_assert(foo<b32>(0x42), ""); // both-error {{not an integral constant 
expression}} \
                                      // both-note {{in call to}}
 }
+
+namespace nullptrToArray {
+  typedef decltype(__builtin_bit_cast(unsigned char[sizeof(nullptr)], 
nullptr)) footype;
+  static_assert(__builtin_bit_cast(footype, nullptr) == nullptr); // 
both-error {{failed due to requirement}}
+  static_assert(__builtin_bit_cast(footype, nullptr)[0] == 0); // both-error 
{{not an integral constant expression}} \
+                                                               // both-note 
{{read of uninitialized object}} \
+                                                               // both-note 
{{temporary created here}}
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to