Recognize gcc's ms_struct pragma (and ignore for now).
This is wip.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130138 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 6e1e1e4..ccd48da 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -485,6 +485,8 @@
   "missing ')' after '#pragma %0' - ignoring">;
 def warn_pragma_expected_identifier : Warning<
   "expected identifier in '#pragma %0' - ignored">;  
+def warn_pragma_ms_struct : Warning<
+  "incorrect use of '#pragma ms_struct on|off' - ignored">;  
 def warn_pragma_extra_tokens_at_eol : Warning<
   "extra tokens at end of '#pragma %0' - ignored">; 
 // - #pragma options
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index de4904a..0311c06 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -131,6 +131,7 @@
   llvm::OwningPtr<PragmaHandler> GCCVisibilityHandler;
   llvm::OwningPtr<PragmaHandler> OptionsHandler;
   llvm::OwningPtr<PragmaHandler> PackHandler;
+  llvm::OwningPtr<PragmaHandler> MSStructHandler;
   llvm::OwningPtr<PragmaHandler> UnusedHandler;
   llvm::OwningPtr<PragmaHandler> WeakHandler;
   llvm::OwningPtr<PragmaHandler> FPContractHandler;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 6c08712..e635526 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -240,6 +240,8 @@
   /// PackContext - Manages the stack for #pragma pack. An alignment
   /// of 0 indicates default alignment.
   void *PackContext; // Really a "PragmaPackStack*"
+    
+  bool MSStructPragmaOn; // True when #pragma ms_struct on
 
   /// VisContext - Manages the stack for #pragma GCC visibility.
   void *VisContext; // Really a "PragmaVisStack*"
@@ -4855,6 +4857,11 @@
     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,
@@ -4862,6 +4869,9 @@
                        SourceLocation PragmaLoc,
                        SourceLocation LParenLoc,
                        SourceLocation RParenLoc);
+    
+  /// ActOnPragmaMSStruct - Called on well formed #pragms ms_struct [on|off].
+  void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
 
   /// ActOnPragmaUnused - Called on well-formed '#pragma unused'.
   void ActOnPragmaUnused(const Token &Identifier,
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index beb1af6..46225c8 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -177,6 +177,38 @@
                           LParenLoc, RParenLoc);
 }
 
+// #pragma ms_struct on
+// #pragma ms_struct off
+void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, 
+                                         PragmaIntroducerKind Introducer,
+                                         Token &MSStructTok) {
+  Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
+  
+  Token Tok;
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::identifier)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
+    return;
+  }
+  const IdentifierInfo *II = Tok.getIdentifierInfo();
+  if (II->isStr("on")) {
+    Kind = Sema::PMSST_ON;
+    PP.Lex(Tok);
+  }
+  else if (II->isStr("off") || II->isStr("reset"))
+    PP.Lex(Tok);
+  else {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
+    return;
+  }
+  
+  if (Tok.isNot(tok::eod)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "ms_struct";
+    return;
+  }
+  Actions.ActOnPragmaMSStruct(Kind);
+}
+
 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
 static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h
index bee6af3..1d3138f 100644
--- a/lib/Parse/ParsePragma.h
+++ b/lib/Parse/ParsePragma.h
@@ -58,6 +58,16 @@
   virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
                             Token &FirstToken);
 };
+  
+class PragmaMSStructHandler : public PragmaHandler {
+  Sema &Actions;
+public:
+  explicit PragmaMSStructHandler(Sema &A) : PragmaHandler("ms_struct"),
+  Actions(A) {}
+    
+  virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+                            Token &FirstToken);
+};
 
 class PragmaUnusedHandler : public PragmaHandler {
   Sema &Actions;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 9244b99..debc740 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -45,6 +45,9 @@
 
   PackHandler.reset(new PragmaPackHandler(actions));
   PP.AddPragmaHandler(PackHandler.get());
+    
+  MSStructHandler.reset(new PragmaMSStructHandler(actions));
+  PP.AddPragmaHandler(MSStructHandler.get());
 
   UnusedHandler.reset(new PragmaUnusedHandler(actions, *this));
   PP.AddPragmaHandler(UnusedHandler.get());
@@ -377,6 +380,8 @@
   OptionsHandler.reset();
   PP.RemovePragmaHandler(PackHandler.get());
   PackHandler.reset();
+  PP.RemovePragmaHandler(MSStructHandler.get());
+  MSStructHandler.reset();
   PP.RemovePragmaHandler(UnusedHandler.get());
   UnusedHandler.reset();
   PP.RemovePragmaHandler(WeakHandler.get());
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 3ce1d82..7707fb1 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -141,7 +141,7 @@
     LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
     Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
     ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), 
-    PackContext(0), VisContext(0),
+    PackContext(0), MSStructPragmaOn(false), VisContext(0),
     LateTemplateParser(0), OpaqueParser(0),
     IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     GlobalNewDeleteDeclared(false), 
@@ -184,7 +184,7 @@
   if (PackContext) FreePackedContext();
   if (VisContext) FreeVisContext();
   delete TheTargetAttributesSema;
-
+  MSStructPragmaOn = false;
   // Kill all the active scopes.
   for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
     delete FunctionScopes[I];
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 4fad173..7a50356 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -263,6 +263,10 @@
   }
 }
 
+void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { 
+  MSStructPragmaOn = (Kind == PMSST_ON);
+}
+
 void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
                              SourceLocation PragmaLoc) {
 
diff --git a/test/Sema/pragma-ms_struct.c b/test/Sema/pragma-ms_struct.c
new file mode 100644
index 0000000..61047c0
--- /dev/null
+++ b/test/Sema/pragma-ms_struct.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-apple-darwin9 %s
+
+#pragma ms_struct on
+
+#pragma ms_struct off
+
+#pragma ms_struct reset
+
+#pragma ms_struct // expected-warning {{incorrect use of '#pragma ms_struct on|off' - ignored}}
+
+#pragma ms_struct on top of spaghetti  // expected-warning {{extra tokens at end of '#pragma ms_struct' - ignored}}
+
+struct foo
+{
+  int a;
+  int b;
+  char c;
+};
+