[clang] 858f734 - [clang] Fix #embed with C++20 modules (#197434)
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 18 04:37:40 PDT 2026
Author: Mariya Podchishchaeva
Date: 2026-05-18T11:37:35Z
New Revision: 858f734d2d2ae74306e12ee726cc51e098c687d4
URL: https://github.com/llvm/llvm-project/commit/858f734d2d2ae74306e12ee726cc51e098c687d4
DIFF: https://github.com/llvm/llvm-project/commit/858f734d2d2ae74306e12ee726cc51e098c687d4.diff
LOG: [clang] Fix #embed with C++20 modules (#197434)
Fix a bug in EmbedExpr's constructor, correct serialization to make sure
to initialize all required fields and add a test.
Fixes https://github.com/llvm/llvm-project/issues/195350
Added:
clang/test/Modules/embed-directive.cppm
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/Expr.h
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b0c2179a3aec1..3aea1c28c3cae 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -562,6 +562,7 @@ Bug Fixes in This Version
- Fixed a potential stack-use-after-return issue in Clang when copy-initializing
an array via an element-at-a-time copy loop (#GH192026)
- Fixed an issue where certain designated initializers would be rejected for constexpr variables. (#GH193373)
+- Fixed a crash when ``#embed`` is used with C++ modules (#GH195350)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 885c8ceea71c1..b91bf4a5375fb 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -5137,7 +5137,7 @@ class EmbedExpr final : public Expr {
public:
EmbedExpr(const ASTContext &Ctx, SourceLocation Loc, EmbedDataStorage *Data,
unsigned Begin, unsigned NumOfElements);
- explicit EmbedExpr(EmptyShell Empty) : Expr(SourceLocExprClass, Empty) {}
+ explicit EmbedExpr(EmptyShell Empty) : Expr(EmbedExprClass, Empty) {}
SourceLocation getLocation() const { return EmbedKeywordLoc; }
SourceLocation getBeginLoc() const { return EmbedKeywordLoc; }
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 39a37c6dacb2a..7e51ce8c0aca2 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1389,8 +1389,14 @@ void ASTStmtReader::VisitEmbedExpr(EmbedExpr *E) {
EmbedDataStorage *Data = new (Record.getContext()) EmbedDataStorage;
Data->BinaryData = cast<StringLiteral>(Record.readSubStmt());
E->Data = Data;
- E->Begin = Record.readInt();
- E->NumOfElements = Record.readInt();
+ E->Begin = Record.readUInt32();
+ E->NumOfElements = Record.readUInt32();
+ ASTContext &Ctx = Record.getContext();
+ E->Ctx = &Ctx;
+ E->setType(Ctx.IntTy);
+ E->FakeChildNode = IntegerLiteral::Create(
+ Ctx, llvm::APInt::getZero(Ctx.getTypeSize(E->getType())), E->getType(),
+ E->EmbedKeywordLoc);
}
void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index e1613b777b95a..a7e815a1ef438 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1340,7 +1340,6 @@ void ASTStmtWriter::VisitSourceLocExpr(SourceLocExpr *E) {
void ASTStmtWriter::VisitEmbedExpr(EmbedExpr *E) {
VisitExpr(E);
Record.AddSourceLocation(E->getBeginLoc());
- Record.AddSourceLocation(E->getEndLoc());
Record.AddStmt(E->getDataStringLiteral());
Record.writeUInt32(E->getStartingElementPos());
Record.writeUInt32(E->getDataElementCount());
diff --git a/clang/test/Modules/embed-directive.cppm b/clang/test/Modules/embed-directive.cppm
new file mode 100644
index 0000000000000..1d2448c685870
--- /dev/null
+++ b/clang/test/Modules/embed-directive.cppm
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %t/foo.cppm -emit-module-interface \
+// RUN: -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %t/user.cc -fmodule-file=foo=%t/foo.pcm \
+// RUN: -emit-llvm -o - -disable-llvm-passes | FileCheck %t/user.cc
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %t/user.cc -fmodule-file=foo=%t/foo.pcm \
+// RUN: -fexperimental-new-constant-interpreter -emit-llvm -o - -disable-llvm-passes | FileCheck %t/user.cc
+
+//--- foo.cppm
+// embed content
+
+export module foo;
+
+export constexpr const char data[] = {
+#embed __FILE__ limit(16)
+ , 0};
+
+//--- user.cc
+export module importer;
+import foo;
+
+constexpr auto d = data;
+static_assert(d[0] == '/');
+
+// CHECK: @{{.*}}data{{.*}} = {{.*}} constant [17 x i8] c"// embed content\00", align 16
More information about the cfe-commits
mailing list