[clang] 844f833 - Fix crash with modules and constexpr destructor (#69076)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jan 14 23:40:30 PST 2024
Author: Jonas Hahnfeld
Date: 2024-01-15T08:40:26+01:00
New Revision: 844f8335f211da19ae4b375761013909a3394d9a
URL: https://github.com/llvm/llvm-project/commit/844f8335f211da19ae4b375761013909a3394d9a
DIFF: https://github.com/llvm/llvm-project/commit/844f8335f211da19ae4b375761013909a3394d9a.diff
LOG: Fix crash with modules and constexpr destructor (#69076)
With modules, serialization might omit the outer ExprWithCleanups
as it calls ParmVarDecl::getDefaultArg(). Complementary to fixing
this in a separate change, make the code more robust by adding a
FullExpressionRAII and avoid the llvm_unreachable in the added test
clang/test/Modules/pr68702.cpp.
Closes https://github.com/llvm/llvm-project/issues/68702
Added:
clang/test/Modules/pr68702.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/AST/ExprConstant.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index dc8a6fe506bce6..7e130304c5c08f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -958,6 +958,8 @@ Miscellaneous Clang Crashes Fixed
- Fixed a crash when a lambda marked as ``static`` referenced a captured
variable in an expression.
`Issue 74608 <https://github.com/llvm/llvm-project/issues/74608>`_
+- Fixed a crash with modules and a ``constexpr`` destructor.
+ `Issue 68702 <https://github.com/llvm/llvm-project/issues/68702>`_
OpenACC Specific Changes
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f6aeee1a4e935d..f20850d14c0c86 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -15754,10 +15754,22 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
LValue LVal;
LVal.set(VD);
- if (!EvaluateInPlace(Value, Info, LVal, this,
- /*AllowNonLiteralTypes=*/true) ||
- EStatus.HasSideEffects)
- return false;
+ {
+ // C++23 [intro.execution]/p5
+ // A full-expression is ... an init-declarator ([dcl.decl]) or a
+ // mem-initializer.
+ // So we need to make sure temporary objects are destroyed after having
+ // evaluated the expression (per C++23 [class.temporary]/p4).
+ //
+ // FIXME: Otherwise this may break test/Modules/pr68702.cpp because the
+ // serialization code calls ParmVarDecl::getDefaultArg() which strips the
+ // outermost FullExpr, such as ExprWithCleanups.
+ FullExpressionRAII Scope(Info);
+ if (!EvaluateInPlace(Value, Info, LVal, this,
+ /*AllowNonLiteralTypes=*/true) ||
+ EStatus.HasSideEffects)
+ return false;
+ }
// At this point, any lifetime-extended temporaries are completely
// initialized.
diff --git a/clang/test/Modules/pr68702.cpp b/clang/test/Modules/pr68702.cpp
new file mode 100644
index 00000000000000..d32f946910f4fb
--- /dev/null
+++ b/clang/test/Modules/pr68702.cpp
@@ -0,0 +1,65 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %t/main.cpp -o %t/main.o
+
+//--- V.h
+#ifndef V_H
+#define V_H
+
+class A {
+public:
+ constexpr A() { }
+ constexpr ~A() { }
+};
+
+template <typename T>
+class V {
+public:
+ V() = default;
+
+ constexpr V(int n, const A& a = A()) {}
+};
+
+#endif
+
+//--- inst1.h
+#include "V.h"
+
+static void inst1() {
+ V<int> v;
+}
+
+//--- inst2.h
+#include "V.h"
+
+static void inst2() {
+ V<int> v(100);
+}
+
+//--- module.modulemap
+module "M" {
+ export *
+ module "V.h" {
+ export *
+ header "V.h"
+ }
+ module "inst1.h" {
+ export *
+ header "inst1.h"
+ }
+}
+
+module "inst2.h" {
+ export *
+ header "inst2.h"
+}
+
+//--- main.cpp
+#include "V.h"
+#include "inst2.h"
+
+static void m() {
+ static V<int> v(100);
+}
More information about the cfe-commits
mailing list