https://github.com/Fznamznon created 
https://github.com/llvm/llvm-project/pull/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

>From f5e5d21ff6d2b4b4dc36f3d07046fd0a14c6016a Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <[email protected]>
Date: Wed, 13 May 2026 06:07:05 -0700
Subject: [PATCH] [clang] Fix #embed with C++20 modules

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
---
 clang/docs/ReleaseNotes.rst               |  1 +
 clang/include/clang/AST/Expr.h            |  2 +-
 clang/lib/Serialization/ASTReaderStmt.cpp | 10 ++++++--
 clang/lib/Serialization/ASTWriterStmt.cpp |  1 -
 clang/test/Modules/embed-directive.cppm   | 28 +++++++++++++++++++++++
 5 files changed, 38 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/Modules/embed-directive.cppm

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bd91b8723a5c6..991cd35239926 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -546,6 +546,7 @@ Bug Fixes in This Version
 - Fixed a crash when parsing invalid ``static_assert`` declarations with 
string-literal messages (#GH187690).
 - 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 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 393fe275c6269..caaa10c1bf0ee 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 4ada1dc58042d..903c52632cab3 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1388,8 +1388,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 47cbef06c3cc4..9130e88227519 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1339,7 +1339,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

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

Reply via email to