]> granicus.if.org Git - clang/commitdiff
Serialize `pragma ms_struct` state.
authorNico Weber <nicolasweber@gmx.de>
Wed, 2 Mar 2016 23:22:00 +0000 (23:22 +0000)
committerNico Weber <nicolasweber@gmx.de>
Wed, 2 Mar 2016 23:22:00 +0000 (23:22 +0000)
pragma ms_struct has an effect on struct decls, and the effect is serialized
correctly already.  But the "is ms_struct currently on" state wasn't before
this change.

This uses the same approach as `pragma clang optimize`: When writing a module,
the state isn't serialized, only when writing a pch file.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@262539 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/PragmaKinds.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
include/clang/Serialization/ASTReader.h
include/clang/Serialization/ASTWriter.h
lib/Parse/ParsePragma.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/PCH/pragma-ms_struct.cpp [new file with mode: 0644]

index be3eabb0011d99135251c741d05c4d59162d3cf5..b373a9e4e29e8b02fd5fd4dc7173049404342f67 100644 (file)
@@ -21,6 +21,11 @@ enum PragmaMSCommentKind {
   PCK_User      // #pragma comment(user, ...)
 };
 
+enum PragmaMSStructKind {
+  PMSST_OFF, // #pragms ms_struct off
+  PMSST_ON   // #pragms ms_struct on
+};
+
 }
 
 #endif
index fc6e56174a489d5621ab34d03e261da0f86d8044..22879d3b1c0bff56cde16a5ac1405339ac602484 100644 (file)
@@ -7611,11 +7611,6 @@ public:
     PPK_Pop      // #pragma pack(pop, [identifier], [n])
   };
 
-  enum PragmaMSStructKind {
-    PMSST_OFF,  // #pragms ms_struct off
-    PMSST_ON    // #pragms ms_struct on
-  };
-
   /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
   void ActOnPragmaPack(PragmaPackKind Kind,
                        IdentifierInfo *Name,
index 82f0cbf9388ca464cbf9c7cc1972b366cf9899d9..a47888ab06d23c0466574858c679601d71a498eb 100644 (file)
@@ -575,7 +575,10 @@ namespace clang {
       CXX_CTOR_INITIALIZERS_OFFSETS = 53,
 
       /// \brief Delete expressions that will be analyzed later.
-      DELETE_EXPRS_TO_ANALYZE = 54
+      DELETE_EXPRS_TO_ANALYZE = 54,
+
+      /// \brief Record code for \#pragma ms_struct options.
+      MSSTRUCT_PRAGMA_OPTIONS = 55
     };
 
     /// \brief Record types used within a source manager block.
index ca54d8f2c33d051d9a98bfd598818f19217d1199..cb092344bbdf4dc777212df5e05c01420cd5e44a 100644 (file)
@@ -785,6 +785,9 @@ private:
   /// \brief The pragma clang optimize location (if the pragma state is "off").
   SourceLocation OptimizeOffPragmaLocation;
 
+  /// \brief The PragmaMSStructKind pragma ms_struct state if set, or -1.
+  int PragmaMSStructState;
+
   /// \brief The OpenCL extension settings.
   SmallVector<uint64_t, 1> OpenCLExtensions;
 
index ef8c653413882dcd41376df26f9849d639e307f1..e31f6e98370266a404ed35c93e708247f5711af4 100644 (file)
@@ -551,6 +551,7 @@ private:
   void WriteObjCCategories();
   void WriteLateParsedTemplates(Sema &SemaRef);
   void WriteOptimizePragmaOptions(Sema &SemaRef);
+  void WriteMSStructPragmaOptions(Sema &SemaRef);
   void WriteModuleFileExtension(Sema &SemaRef,
                                 ModuleFileExtensionWriter &Writer);
 
index a7ea206d09b0b17b8da66b2d1499442fbccbd9f7..09c5d49a6ae74973e81bdcb1349ff0ce7b80bdb1 100644 (file)
@@ -362,9 +362,8 @@ void Parser::HandlePragmaPack() {
 
 void Parser::HandlePragmaMSStruct() {
   assert(Tok.is(tok::annot_pragma_msstruct));
-  Sema::PragmaMSStructKind Kind =
-    static_cast<Sema::PragmaMSStructKind>(
-    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
+  PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
+      reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
   Actions.ActOnPragmaMSStruct(Kind);
   ConsumeToken(); // The annotation token.
 }
@@ -1063,8 +1062,8 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP,
 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, 
                                          PragmaIntroducerKind Introducer,
                                          Token &MSStructTok) {
-  Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
-  
+  PragmaMSStructKind Kind = PMSST_OFF;
+
   Token Tok;
   PP.Lex(Tok);
   if (Tok.isNot(tok::identifier)) {
@@ -1074,7 +1073,7 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
   SourceLocation EndLoc = Tok.getLocation();
   const IdentifierInfo *II = Tok.getIdentifierInfo();
   if (II->isStr("on")) {
-    Kind = Sema::PMSST_ON;
+    Kind = PMSST_ON;
     PP.Lex(Tok);
   }
   else if (II->isStr("off") || II->isStr("reset"))
index 4eef6cfbff408bb8c263ad2e4eaee2ba3daf1ffb..57dc611c7e00dab73afd88dc03ccab6054354388 100644 (file)
@@ -3217,6 +3217,14 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
       OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]);
       break;
 
+    case MSSTRUCT_PRAGMA_OPTIONS:
+      if (Record.size() != 1) {
+        Error("invalid pragma ms_struct record");
+        return Failure;
+      }
+      PragmaMSStructState = Record[0];
+      break;
+
     case UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES:
       for (unsigned I = 0, N = Record.size(); I != N; ++I)
         UnusedLocalTypedefNameCandidates.push_back(
@@ -6998,10 +7006,12 @@ void ASTReader::UpdateSema() {
     SemaDeclRefs.clear();
   }
 
-  // Update the state of 'pragma clang optimize'. Use the same API as if we had
-  // encountered the pragma in the source.
+  // Update the state of pragmas. Use the same API as if we had encountered the
+  // pragma in the source.
   if(OptimizeOffPragmaLocation.isValid())
     SemaObj->ActOnPragmaOptimize(/* IsOn = */ false, OptimizeOffPragmaLocation);
+  if (PragmaMSStructState != -1)
+    SemaObj->ActOnPragmaMSStruct((PragmaMSStructKind)PragmaMSStructState);
 }
 
 IdentifierInfo *ASTReader::get(StringRef Name) {
@@ -8696,6 +8706,7 @@ ASTReader::ASTReader(
       Diags(PP.getDiagnostics()), SemaObj(nullptr), PP(PP), Context(Context),
       Consumer(nullptr), ModuleMgr(PP.getFileManager(), PCHContainerRdr),
       ReadTimer(std::move(ReadTimer)),
+      PragmaMSStructState(-1),
       isysroot(isysroot), DisableValidation(DisableValidation),
       AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
       AllowConfigurationMismatch(AllowConfigurationMismatch),
index 98ed1488d50544936761f5956a725c1d065b2767..bef7fc267ebf27144f730c19a1c062ff7d8aefe7 100644 (file)
@@ -960,6 +960,7 @@ void ASTWriter::WriteBlockInfoBlock() {
   RECORD(UNDEFINED_BUT_USED);
   RECORD(LATE_PARSED_TEMPLATE);
   RECORD(OPTIMIZE_PRAGMA_OPTIONS);
+  RECORD(MSSTRUCT_PRAGMA_OPTIONS);
   RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);
   RECORD(CXX_CTOR_INITIALIZERS_OFFSETS);
   RECORD(DELETE_EXPRS_TO_ANALYZE);
@@ -3928,6 +3929,13 @@ void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {
   Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record);
 }
 
+/// \brief Write the state of 'pragma ms_struct' at the end of the module.
+void ASTWriter::WriteMSStructPragmaOptions(Sema &SemaRef) {
+  RecordData Record;
+  Record.push_back(SemaRef.MSStructPragmaOn ? PMSST_ON : PMSST_OFF);
+  Stream.EmitRecord(MSSTRUCT_PRAGMA_OPTIONS, Record);
+}
+
 void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
                                          ModuleFileExtensionWriter &Writer) {
   // Enter the extension block.
@@ -4605,8 +4613,10 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
 
   WriteDeclReplacementsBlock();
   WriteObjCCategories();
-  if(!WritingModule)
+  if(!WritingModule) {
     WriteOptimizePragmaOptions(SemaRef);
+    WriteMSStructPragmaOptions(SemaRef);
+  }
 
   // Some simple statistics
   RecordData::value_type Record[] = {
diff --git a/test/PCH/pragma-ms_struct.cpp b/test/PCH/pragma-ms_struct.cpp
new file mode 100644 (file)
index 0000000..ac2a1e8
--- /dev/null
@@ -0,0 +1,41 @@
+// Test this without pch.
+// RUN: %clang_cc1 %s -Wunknown-pragmas -Werror -triple i386-apple-darwin9 -fsyntax-only -include %s -verify -std=c++11
+
+// Test with pch.
+// RUN: %clang_cc1 %s -Wunknown-pragmas -Werror -triple i386-apple-darwin9 -emit-pch -o %t -std=c++11
+// RUN: %clang_cc1 %s -Wunknown-pragmas -Werror -triple i386-apple-darwin9 -fsyntax-only -include-pch %t -verify -std=c++11
+
+// The first run line creates a pch, and since at that point HEADER is not
+// defined, the only thing contained in the pch is the pragma. The second line
+// then includes that pch, so HEADER is defined and the actual code is compiled.
+// The check then makes sure that the pragma is in effect in the file that
+// includes the pch.
+
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+struct SOffH {
+  short m : 9;
+  int q : 12;
+};
+
+#pragma ms_struct on
+
+struct SOnH {
+  short m : 9;
+  int q : 12;
+};
+
+#else
+
+struct SOnC {
+  short m : 9;
+  int q : 12;
+};
+
+static_assert(sizeof(SOffH) == 4, "");
+static_assert(sizeof(SOnH) == 8, "");
+static_assert(sizeof(SOnC) == 8, "");
+
+#endif