Author: Timm Bäder
Date: 2024-05-22T17:57:00+02:00
New Revision: 4fbc95d1360147e9c4aceeadd1bda17d68364b85

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

LOG: [clang][Interp] Skip union members in default initializers

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/EvaluationResult.cpp
    clang/test/AST/Interp/unions.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 859a3fabea32b..50c85bf7d35f5 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1061,6 +1061,10 @@ bool 
ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
              R->getField(InitIndex)->Decl->isUnnamedBitField())
         ++InitIndex;
 
+      // Potentially skip ahead. This is especially relevant in unions.
+      if (const auto *D = dyn_cast<CXXDefaultInitExpr>(Init))
+        InitIndex = D->getField()->getFieldIndex();
+
       if (!this->emitDupPtr(E))
         return false;
 

diff  --git a/clang/lib/AST/Interp/EvaluationResult.cpp 
b/clang/lib/AST/Interp/EvaluationResult.cpp
index 79f222ce2b30c..150a793da881d 100644
--- a/clang/lib/AST/Interp/EvaluationResult.cpp
+++ b/clang/lib/AST/Interp/EvaluationResult.cpp
@@ -101,6 +101,10 @@ static bool CheckFieldsInitialized(InterpState &S, 
SourceLocation Loc,
     Pointer FieldPtr = BasePtr.atField(F.Offset);
     QualType FieldType = F.Decl->getType();
 
+    // Don't check inactive union members.
+    if (R->isUnion() && !FieldPtr.isActive())
+      continue;
+
     if (FieldType->isRecordType()) {
       Result &= CheckFieldsInitialized(S, Loc, FieldPtr, FieldPtr.getRecord());
     } else if (FieldType->isIncompleteArrayType()) {
@@ -115,10 +119,6 @@ static bool CheckFieldsInitialized(InterpState &S, 
SourceLocation Loc,
       DiagnoseUninitializedSubobject(S, Loc, F.Decl);
       Result = false;
     }
-
-    // Only the first member of a union needs to be initialized.
-    if (R->isUnion())
-      break;
   }
 
   // Check Fields in all bases

diff  --git a/clang/test/AST/Interp/unions.cpp 
b/clang/test/AST/Interp/unions.cpp
index 004e500de064f..46ba514b47b98 100644
--- a/clang/test/AST/Interp/unions.cpp
+++ b/clang/test/AST/Interp/unions.cpp
@@ -10,3 +10,11 @@ constexpr U a = {12};
 static_assert(a.a == 12, "");
 static_assert(a.b == 0, ""); // both-error {{not an integral constant 
expression}} \
                              // both-note {{read of member 'b' of union with 
active member 'a'}}
+union U1 {
+  int i;
+  float f = 3.0f;
+};
+constexpr U1 u1{};
+static_assert(u1.f == 3.0, "");
+static_assert(u1.i == 1, ""); // both-error {{not an integral constant 
expression}} \
+                              // both-note {{read of member 'i' of union with 
active member 'f'}}


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

Reply via email to