llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Arendelle (SekaiArendelle)

<details>
<summary>Changes</summary>

When HandleDestructionImpl destroys a class object during constant evaluation, 
it attempts to look up the class's destructor via getDestructor() before 
checking whether the record is an anonymous union. Anonymous unions should not 
have their destructors invoked directly during constant evaluation — their 
lifetime is managed by the enclosing class's destructor. Move the 
anonymous-union short-circuit before the getDestructor() call so anonymous 
unions are handled early, regardless of whether getDestructor() returns null or 
not.

This fixes cases where an object with an implicitly-defined constexpr 
destructor stored inside an anonymous union member was incorrectly rejected 
during constant evaluation.

---
Full diff: https://github.com/llvm/llvm-project/pull/197416.diff


2 Files Affected:

- (modified) clang/lib/AST/ExprConstant.cpp (+9-6) 
- (modified) clang/test/SemaCXX/constant-expression-cxx2a.cpp (+20) 


``````````diff
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 5f09c9ea4a7b8..efe9d793d2fb2 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -7370,23 +7370,26 @@ static bool HandleDestructionImpl(EvalInfo &Info, 
SourceRange CallRange,
     return false;
   }
 
+  // If an anonymous union would be destroyed, some enclosing destructor must
+  // have been explicitly defined, and the anonymous union destruction should
+  // have no effect.
+  if (RD->isAnonymousStructOrUnion() && RD->isUnion()) {
+    Value = APValue();
+    return true;
+  }
+
   const CXXDestructorDecl *DD = RD->getDestructor();
   if (!DD && !RD->hasTrivialDestructor()) {
     Info.FFDiag(CallRange.getBegin());
     return false;
   }
 
-  if (!DD || DD->isTrivial() ||
-      (RD->isAnonymousStructOrUnion() && RD->isUnion())) {
+  if (!DD || DD->isTrivial()) {
     // A trivial destructor just ends the lifetime of the object. Check for
     // this case before checking for a body, because we might not bother
     // building a body for a trivial destructor. Note that it doesn't matter
     // whether the destructor is constexpr in this case; all trivial
     // destructors are constexpr.
-    //
-    // If an anonymous union would be destroyed, some enclosing destructor must
-    // have been explicitly defined, and the anonymous union destruction should
-    // have no effect.
     Value = APValue();
     return true;
   }
diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp 
b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index 396a8df21a3e3..0748c6be0179f 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1518,3 +1518,23 @@ namespace GH150705 {
   constexpr const A& a = b;
   constexpr auto x = (a.*q)(); // expected-error {{constant expression}}
 }
+
+namespace GH197403 {
+  struct Inner {
+    constexpr ~Inner() noexcept {}
+  };
+  struct Outer {
+    Inner inner;
+  };
+  template<typename T>
+  struct BugTrigger {
+    union { T value; int dummy; };
+    constexpr BugTrigger() : value{} {}
+    constexpr ~BugTrigger() noexcept { value.~T(); }
+  };
+  consteval int test() {
+    BugTrigger<Outer> bt;
+    return 0;
+  }
+  static_assert(test() == 0);
+}

``````````

</details>


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

Reply via email to