[clang] d27fb5e - [Serialization] Add support for (de)serializing #pragma pack
Mike Rice via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 7 11:41:16 PST 2023
Author: Dustin Howett
Date: 2023-02-07T11:37:02-08:00
New Revision: d27fb5efc5f2086fa157e7d836b61bae4d5f3734
URL: https://github.com/llvm/llvm-project/commit/d27fb5efc5f2086fa157e7d836b61bae4d5f3734
DIFF: https://github.com/llvm/llvm-project/commit/d27fb5efc5f2086fa157e7d836b61bae4d5f3734.diff
LOG: [Serialization] Add support for (de)serializing #pragma pack
Serialization of tokens is required when PCH is used with late parsed
templates, including annotation tokens used for pragmas.
This patch implements the serialization for annot_pragma_pack.
Fixes https://github.com/llvm/llvm-project/issues/60543
Differential Revision: https://reviews.llvm.org/D143410
Added:
clang/test/PCH/delayed-template-with-pragma-pack.cpp
Modified:
clang/include/clang/Sema/Sema.h
clang/include/clang/Serialization/ASTReader.h
clang/lib/Parse/ParsePragma.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 6247d4a5f6a53..223190602d921 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -483,6 +483,12 @@ class Sema final {
PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value)
};
+ struct PragmaPackInfo {
+ PragmaMsStackAction Action;
+ StringRef SlotLabel;
+ Token Alignment;
+ };
+
// #pragma pack and align.
class AlignPackInfo {
public:
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index 5cdbdfe4e38d4..007872b10e242 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -2236,7 +2236,7 @@ class ASTReader
unsigned &Idx, LocSeq *Seq = nullptr);
// Read a string
- static std::string ReadString(const RecordData &Record, unsigned &Idx);
+ static std::string ReadString(const RecordDataImpl &Record, unsigned &Idx);
// Skip a string
static void SkipString(const RecordData &Record, unsigned &Idx) {
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 658853d42b746..ff7273eddb1a0 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -665,18 +665,10 @@ void Parser::HandlePragmaVisibility() {
Actions.ActOnPragmaVisibility(VisType, VisLoc);
}
-namespace {
-struct PragmaPackInfo {
- Sema::PragmaMsStackAction Action;
- StringRef SlotLabel;
- Token Alignment;
-};
-} // end anonymous namespace
-
void Parser::HandlePragmaPack() {
assert(Tok.is(tok::annot_pragma_pack));
- PragmaPackInfo *Info =
- static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
+ Sema::PragmaPackInfo *Info =
+ static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());
SourceLocation PragmaLoc = Tok.getLocation();
ExprResult Alignment;
if (Info->Alignment.is(tok::numeric_constant)) {
@@ -2110,8 +2102,8 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
return;
}
- PragmaPackInfo *Info =
- PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
+ Sema::PragmaPackInfo *Info =
+ PP.getPreprocessorAllocator().Allocate<Sema::PragmaPackInfo>(1);
Info->Action = Action;
Info->SlotLabel = SlotLabel;
Info->Alignment = Alignment;
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index eb1eda98abc79..fb723d4e46d6b 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -1687,6 +1687,16 @@ Token ASTReader::ReadToken(ModuleFile &F, const RecordDataImpl &Record,
Tok.setAnnotationValue(static_cast<void *>(Info));
break;
}
+ case tok::annot_pragma_pack: {
+ auto *Info = new (PP.getPreprocessorAllocator()) Sema::PragmaPackInfo;
+ Info->Action = static_cast<Sema::PragmaMsStackAction>(Record[Idx++]);
+ auto SlotLabel = ReadString(Record, Idx);
+ Info->SlotLabel =
+ llvm::StringRef(SlotLabel).copy(PP.getPreprocessorAllocator());
+ Info->Alignment = ReadToken(F, Record, Idx);
+ Tok.setAnnotationValue(static_cast<void *>(Info));
+ break;
+ }
// Some annotation tokens do not use the PtrData field.
case tok::annot_pragma_openmp:
case tok::annot_pragma_openmp_end:
@@ -9084,7 +9094,7 @@ llvm::APFloat ASTRecordReader::readAPFloat(const llvm::fltSemantics &Sem) {
}
// Read a string
-std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
+std::string ASTReader::ReadString(const RecordDataImpl &Record, unsigned &Idx) {
unsigned Len = Record[Idx++];
std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
Idx += Len;
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index bdf11001473e2..c1afdeb6007db 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4412,6 +4412,14 @@ void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) {
AddToken(T, Record);
break;
}
+ case tok::annot_pragma_pack: {
+ auto *Info =
+ static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());
+ Record.push_back(static_cast<unsigned>(Info->Action));
+ AddString(Info->SlotLabel, Record);
+ AddToken(Info->Alignment, Record);
+ break;
+ }
// Some annotation tokens do not use the PtrData field.
case tok::annot_pragma_openmp:
case tok::annot_pragma_openmp_end:
diff --git a/clang/test/PCH/delayed-template-with-pragma-pack.cpp b/clang/test/PCH/delayed-template-with-pragma-pack.cpp
new file mode 100644
index 0000000000000..cee33685bd8d5
--- /dev/null
+++ b/clang/test/PCH/delayed-template-with-pragma-pack.cpp
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -emit-pch -o %t.pch %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fdelayed-template-parsing -emit-pch -o %t.delayed.pch %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -DMAIN_FILE \
+// RUN: -include-pch %t.pch \
+// RUN: -emit-llvm -verify -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -DMAIN_FILE -fdelayed-template-parsing \
+// RUN: -include-pch %t.delayed.pch \
+// RUN: -emit-llvm -verify -o - %s | FileCheck %s
+
+#ifndef MAIN_FILE
+
+extern "C" void consume(int b);
+
+template <int I>
+void function() {
+#pragma pack(push, 1)
+ struct packedAt1 {
+ char a;
+ unsigned long long b;
+ char c;
+ unsigned long long d;
+ // 18 bytes total
+ };
+#pragma pack(push, slot1, 2)
+ struct packedAt2 {
+ char a; // +1 byte of padding
+ unsigned long long b;
+ char c; // +1 byte of padding
+ unsigned long long d;
+ // 20 bytes total
+ };
+#pragma pack(push, 4)
+ struct packedAt4 {
+ char a; // +3 bytes of padding
+ unsigned long long b;
+ char c; // +3 bytes of padding
+ unsigned long long d;
+ // 24 bytes total
+ };
+#pragma pack(push, 16)
+ struct packedAt16 {
+ char a; // +7 bytes of padding
+ unsigned long long b;
+ char c; // +7 bytes of padding
+ unsigned long long d;
+ // 32 bytes total
+ };
+#pragma pack(pop, slot1) // This should return packing to 1 (established before push(slot1))
+ struct packedAfterPopBackTo1 {
+ char a;
+ unsigned long long b;
+ char c;
+ unsigned long long d;
+ };
+#pragma pack(pop)
+
+ consume(sizeof(packedAt1)); // 18
+ consume(sizeof(packedAt2)); // 20
+ consume(sizeof(packedAt4)); // 24
+ consume(sizeof(packedAt16)); // 32
+ consume(sizeof(packedAfterPopBackTo1)); // 18 again
+}
+
+#else
+
+// CHECK-LABEL: define linkonce_odr dso_local void @"??$function@$0A@@@YAXXZ"(
+// CHECK: call void @consume(i32 noundef 18)
+// CHECK-NEXT: call void @consume(i32 noundef 20)
+// CHECK-NEXT: call void @consume(i32 noundef 24)
+// CHECK-NEXT: call void @consume(i32 noundef 32)
+// CHECK-NEXT: call void @consume(i32 noundef 18)
+void foo() {
+ function<0>();
+}
+
+// expected-no-diagnostics
+
+#endif
More information about the cfe-commits
mailing list