Author: Yanzuo Liu
Date: 2026-02-05T16:37:58+01:00
New Revision: ddda8d7d259826e9a686469d531787ea223d727d

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

LOG: [clang][bytecode] Fix reading union template parameter object (#179899)

Before this patch, reading union template parameter object will trigger
diagnostics saying it's not initialized. This patch fixes this issue.

Reading union template parameter with no active fields, class type
fields, or bit-fields is handled as a drive-by.

AI usage: The implementation was generated by AI and modified by me
afterwards.

Assisted-by: GPT-5.2

---------

Co-authored-by: Timm Baeder <[email protected]>

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Compiler.cpp
    clang/test/AST/ByteCode/cxx20.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index eb52112f16b82..a0138c402e143 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -5069,14 +5069,29 @@ bool Compiler<Emitter>::visitAPValueInitializer(const 
APValue &Val,
   }
   if (Val.isUnion()) {
     const FieldDecl *UnionField = Val.getUnionField();
-    const Record *R = this->getRecord(UnionField->getParent());
+    if (!UnionField)
+      return true;
+    const Record *R = this->getRecord(T);
     assert(R);
     const APValue &F = Val.getUnionValue();
     const Record::Field *RF = R->getField(UnionField);
-    PrimType T = classifyPrim(RF->Decl->getType());
-    if (!this->visitAPValue(F, T, E))
+    QualType FieldType = RF->Decl->getType();
+
+    if (OptPrimType PT = classify(FieldType)) {
+      if (!this->visitAPValue(F, *PT, E))
+        return false;
+      if (RF->isBitField())
+        return this->emitInitBitFieldActivate(*PT, RF, E);
+      return this->emitInitFieldActivate(*PT, RF->Offset, E);
+    }
+
+    if (!this->emitGetPtrField(RF->Offset, E))
       return false;
-    return this->emitInitField(T, RF->Offset, E);
+    if (!this->emitActivate(E))
+      return false;
+    if (!this->visitAPValueInitializer(F, E, FieldType))
+      return false;
+    return this->emitPopPtr(E);
   }
   if (Val.isArray()) {
     const auto *ArrType = T->getAsArrayTypeUnsafe();
@@ -7126,8 +7141,9 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, 
const Expr *E) {
           return false;
         return this->emitInitGlobal(*T, *Index, E);
       }
-      return this->visitAPValueInitializer(TPOD->getValue(), E,
-                                           TPOD->getType());
+      if (!this->visitAPValueInitializer(TPOD->getValue(), E, TPOD->getType()))
+        return false;
+      return this->emitFinishInit(E);
     }
     return false;
   }

diff  --git a/clang/test/AST/ByteCode/cxx20.cpp 
b/clang/test/AST/ByteCode/cxx20.cpp
index 2abe8dd120e6f..139b6c873adce 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -785,6 +785,30 @@ namespace APValues {
   constexpr const A &w = get<A{1, &g, &A::n, "hello"}>;
 }
 
+namespace InitFromAPValues {
+  template <auto a> struct S {
+    static constexpr auto &ref = a;
+  };
+
+  union U1 { int x, y; };
+  static_assert(S<U1{1}>::ref.x == 1);
+  static_assert(S<U1{1}>::ref.y == 1); // both-error {{static assertion 
expression is not an integral constant expression}} \
+                                       // both-note {{read of member 'y' of 
union with active member 'x' is not allowed in a constant expression}}
+
+  union U2 {
+    bool x;
+    constexpr U2() {}
+  };
+  static_assert(S<U2{}>::ref.x); // both-error {{static assertion expression 
is not an integral constant expression}} \
+                                 // both-note {{read of member 'x' of union 
with no active member is not allowed in a constant expression}}
+
+  union U3 {
+    struct S { int x; };
+    S s;
+  };
+  static_assert(S<U3{2}>::ref.s.x == 2);
+}
+
 namespace self_referencing {
   struct S {
     S* ptr = nullptr;


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

Reply via email to