Serialize `#pragma comment`.
authorNico Weber <nicolasweber@gmx.de>
Wed, 2 Mar 2016 17:28:48 +0000 (17:28 +0000)
committerNico Weber <nicolasweber@gmx.de>
Wed, 2 Mar 2016 17:28:48 +0000 (17:28 +0000)
`#pragma comment` was handled by Sema calling a function on ASTConsumer, and
CodeGen then implementing this function and writing things to its output.

Instead, introduce a PragmaCommentDecl AST node and hang one off the
TranslationUnitDecl for every `#pragma comment` line, and then use the regular
serialization machinery. (Since PragmaCommentDecl has codegen relevance, it's
eagerly deserialized.)

http://reviews.llvm.org/D17799

llvm-svn: 262493

25 files changed:
clang/include/clang/AST/ASTConsumer.h
clang/include/clang/AST/Decl.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/Basic/DeclNodes.td
clang/include/clang/Basic/PragmaKinds.h [new file with mode: 0644]
clang/include/clang/Frontend/MultiplexConsumer.h
clang/include/clang/Sema/Sema.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTDumper.cpp
clang/lib/AST/Decl.cpp
clang/lib/AST/DeclBase.cpp
clang/lib/CodeGen/CGDecl.cpp
clang/lib/CodeGen/CodeGenAction.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/ModuleBuilder.cpp
clang/lib/Frontend/MultiplexConsumer.cpp
clang/lib/Parse/ParsePragma.cpp
clang/lib/Sema/SemaAttr.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/lib/Serialization/ASTCommon.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/test/PCH/pragma-comment.c [new file with mode: 0644]
clang/tools/libclang/CIndex.cpp

index 7c0acbc..7aea66b 100644 (file)
@@ -94,22 +94,12 @@ public:
   /// The default implementation passes it to HandleTopLevelDecl.
   virtual void HandleImplicitImportDecl(ImportDecl *D);
 
-  /// \brief Handle a pragma or command line flag that appends to Linker
-  /// Options.  This exists to support Microsoft's
-  /// #pragma comment(linker, "/foo") and the frontend flag --linker-option=.
-  virtual void HandleLinkerOption(llvm::StringRef Opts) {}
-
   /// \brief Handle a pragma that emits a mismatch identifier and value to the
   /// object file for the linker to work with.  Currently, this only exists to
   /// support Microsoft's #pragma detect_mismatch.
   virtual void HandleDetectMismatch(llvm::StringRef Name,
                                     llvm::StringRef Value) {}
 
-  /// \brief Handle a dependent library created by a pragma in the source.
-  /// Currently this only exists to support Microsoft's
-  /// #pragma comment(lib, "/foo").
-  virtual void HandleDependentLibrary(llvm::StringRef Lib) {}
-
   /// CompleteTentativeDefinition - Callback invoked at the end of a translation
   /// unit to notify the consumer that the given tentative definition should be
   /// completed.
index a545e21..569c23a 100644 (file)
@@ -23,6 +23,7 @@
 #include "clang/Basic/Linkage.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/PragmaKinds.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/Compiler.h"
@@ -103,6 +104,40 @@ public:
   }
 };
 
+/// \brief Represents a `#pragma comment` line. Always a child of
+/// TranslationUnitDecl.
+class PragmaCommentDecl final
+    : public Decl,
+      private llvm::TrailingObjects<PragmaCommentDecl, char> {
+  virtual void anchor();
+
+  PragmaMSCommentKind CommentKind;
+
+  friend TrailingObjects;
+  friend class ASTDeclReader;
+  friend class ASTDeclWriter;
+
+  PragmaCommentDecl(TranslationUnitDecl *TU, SourceLocation CommentLoc,
+                    PragmaMSCommentKind CommentKind)
+      : Decl(PragmaComment, TU, CommentLoc), CommentKind(CommentKind) {}
+
+public:
+  static PragmaCommentDecl *Create(const ASTContext &C, TranslationUnitDecl *DC,
+                                   SourceLocation CommentLoc,
+                                   PragmaMSCommentKind CommentKind,
+                                   StringRef Arg);
+  static PragmaCommentDecl *CreateDeserialized(ASTContext &C, unsigned ID,
+                                               unsigned ArgSize);
+
+  PragmaMSCommentKind getCommentKind() const { return CommentKind; }
+
+  StringRef getArg() const { return getTrailingObjects<char>(); }
+
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+  static bool classofKind(Kind K) { return K == PragmaComment; }
+};
+
 /// \brief Declaration context for names declared as extern "C" in C++. This
 /// is neither the semantic nor lexical context for such declarations, but is
 /// used to check for conflicts with other extern "C" declarations. Example:
index 58850f5..76e870a 100644 (file)
@@ -1359,6 +1359,8 @@ DEF_TRAVERSE_DECL(
      // D->getAnonymousNamespace().
     })
 
+DEF_TRAVERSE_DECL(PragmaCommentDecl, {})
+
 DEF_TRAVERSE_DECL(ExternCContextDecl, {})
 
 DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
index a8d4520..9f42961 100644 (file)
@@ -11,6 +11,7 @@ class DDecl<Decl base, bit abstract = 0> : Decl<abstract> {
 class DeclContext { }
 
 def TranslationUnit : Decl, DeclContext;
+def PragmaComment : Decl;
 def ExternCContext : Decl, DeclContext;
 def Named : Decl<1>;
   def Namespace : DDecl<Named>, DeclContext;
diff --git a/clang/include/clang/Basic/PragmaKinds.h b/clang/include/clang/Basic/PragmaKinds.h
new file mode 100644 (file)
index 0000000..be3eabb
--- /dev/null
@@ -0,0 +1,26 @@
+//===--- PragmaKinds.h - #pragma comment() kinds  ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_PRAGMA_KINDS_H
+#define LLVM_CLANG_BASIC_PRAGMA_KINDS_H
+
+namespace clang {
+
+enum PragmaMSCommentKind {
+  PCK_Unknown,
+  PCK_Linker,   // #pragma comment(linker, ...)
+  PCK_Lib,      // #pragma comment(lib, ...)
+  PCK_Compiler, // #pragma comment(compiler, ...)
+  PCK_ExeStr,   // #pragma comment(exestr, ...)
+  PCK_User      // #pragma comment(user, ...)
+};
+
+}
+
+#endif
index 3e8c524..2021a76 100644 (file)
@@ -44,10 +44,8 @@ public:
   void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override;
   void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
   void HandleImplicitImportDecl(ImportDecl *D) override;
-  void HandleLinkerOption(llvm::StringRef Opts) override;
   void HandleDetectMismatch(llvm::StringRef Name,
                             llvm::StringRef Value) override;
-  void HandleDependentLibrary(llvm::StringRef Lib) override;
   void CompleteTentativeDefinition(VarDecl *D) override;
   void AssignInheritanceModel(CXXRecordDecl *RD) override;
   void HandleVTable(CXXRecordDecl *RD) override;
index ec1ade4..10fd485 100644 (file)
@@ -29,6 +29,7 @@
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/PragmaKinds.h"
 #include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TemplateKinds.h"
 #include "clang/Basic/TypeTraits.h"
@@ -7615,15 +7616,6 @@ public:
     PMSST_ON    // #pragms ms_struct on
   };
 
-  enum PragmaMSCommentKind {
-    PCK_Unknown,
-    PCK_Linker,   // #pragma comment(linker, ...)
-    PCK_Lib,      // #pragma comment(lib, ...)
-    PCK_Compiler, // #pragma comment(compiler, ...)
-    PCK_ExeStr,   // #pragma comment(exestr, ...)
-    PCK_User      // #pragma comment(user, ...)
-  };
-
   /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
   void ActOnPragmaPack(PragmaPackKind Kind,
                        IdentifierInfo *Name,
@@ -7637,7 +7629,8 @@ public:
 
   /// ActOnPragmaMSComment - Called on well formed
   /// \#pragma comment(kind, "arg").
-  void ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg);
+  void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind,
+                            StringRef Arg);
 
   /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
   /// pointers_to_members(representation method[, general purpose
index 09df537..b58f415 100644 (file)
@@ -1164,7 +1164,9 @@ namespace clang {
       /// \brief An ObjCTypeParamDecl record.
       DECL_OBJC_TYPE_PARAM,
       /// \brief An OMPCapturedExprDecl record.
-      DECL_OMP_CAPTUREDEXPR
+      DECL_OMP_CAPTUREDEXPR,
+      /// \brief A PragmaCommentDecl record.
+      DECL_PRAGMA_COMMENT
     };
 
     /// \brief Record codes for each kind of statement or expression.
index dad6d1a..0579bca 100644 (file)
@@ -8503,7 +8503,9 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
     // We never need to emit an uninstantiated function template.
     if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
       return false;
-  } else if (isa<OMPThreadPrivateDecl>(D))
+  } else if (isa<PragmaCommentDecl>(D))
+    return true;
+  else if (isa<OMPThreadPrivateDecl>(D))
     return true;
   else
     return false;
index 809b1dd..e0ef80d 100644 (file)
@@ -426,6 +426,7 @@ namespace  {
     void VisitVarDecl(const VarDecl *D);
     void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D);
     void VisitImportDecl(const ImportDecl *D);
+    void VisitPragmaCommentDecl(const PragmaCommentDecl *D);
 
     // C++ Decls
     void VisitNamespaceDecl(const NamespaceDecl *D);
@@ -1200,6 +1201,21 @@ void ASTDumper::VisitImportDecl(const ImportDecl *D) {
   OS << ' ' << D->getImportedModule()->getFullModuleName();
 }
 
+void ASTDumper::VisitPragmaCommentDecl(const PragmaCommentDecl *D) {
+  OS << ' ';
+  switch (D->getCommentKind()) {
+  case PCK_Unknown:  llvm_unreachable("unexpected pragma comment kind");
+  case PCK_Compiler: OS << "compiler"; break;
+  case PCK_ExeStr:   OS << "exestr"; break;
+  case PCK_Lib:      OS << "lib"; break;
+  case PCK_Linker:   OS << "linker"; break;
+  case PCK_User:     OS << "user"; break;
+  }
+  StringRef Arg = D->getArg();
+  if (!Arg.empty())
+    OS << " \"" << Arg << "\"";
+}
+
 //===----------------------------------------------------------------------===//
 // C++ Declarations
 //===----------------------------------------------------------------------===//
index 7378c44..e22f1bc 100644 (file)
@@ -3905,6 +3905,29 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
   return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
 }
 
+void PragmaCommentDecl::anchor() { }
+
+PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C,
+                                             TranslationUnitDecl *DC,
+                                             SourceLocation CommentLoc,
+                                             PragmaMSCommentKind CommentKind,
+                                             StringRef Arg) {
+  PragmaCommentDecl *PCD =
+      new (C, DC, additionalSizeToAlloc<char>(Arg.size() + 1))
+          PragmaCommentDecl(DC, CommentLoc, CommentKind);
+  memcpy(PCD->getTrailingObjects<char>(), Arg.data(), Arg.size());
+  PCD->getTrailingObjects<char>()[Arg.size()] = '\0';
+  return PCD;
+}
+
+PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C,
+                                                         unsigned ID,
+                                                         unsigned ArgSize) {
+  return new (C, ID, additionalSizeToAlloc<char>(ArgSize + 1))
+      PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown);
+}
+
+
 void ExternCContextDecl::anchor() { }
 
 ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C,
index d41d25f..91bc809 100644 (file)
@@ -641,6 +641,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
     case FileScopeAsm:
     case StaticAssert:
     case ObjCPropertyImpl:
+    case PragmaComment:
     case Block:
     case Captured:
     case TranslationUnit:
index 5b88ef1..f9a6b06 100644 (file)
@@ -71,6 +71,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
   case Decl::ObjCImplementation:
   case Decl::ObjCProperty:
   case Decl::ObjCCompatibleAlias:
+  case Decl::PragmaComment:
   case Decl::AccessSpec:
   case Decl::LinkageSpec:
   case Decl::ObjCPropertyImpl:
index 3d333c8..8d08114 100644 (file)
@@ -205,19 +205,11 @@ namespace clang {
       Gen->HandleVTable(RD);
     }
 
-    void HandleLinkerOption(llvm::StringRef Opts) override {
-      Gen->HandleLinkerOption(Opts);
-    }
-
     void HandleDetectMismatch(llvm::StringRef Name,
                                       llvm::StringRef Value) override {
       Gen->HandleDetectMismatch(Name, Value);
     }
 
-    void HandleDependentLibrary(llvm::StringRef Opts) override {
-      Gen->HandleDependentLibrary(Opts);
-    }
-
     static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
                                      unsigned LocCookie) {
       SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
index b98094f..887c533 100644 (file)
@@ -3689,6 +3689,25 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
     ObjCRuntime->RegisterAlias(cast<ObjCCompatibleAliasDecl>(D));
     break;
 
+  case Decl::PragmaComment: {
+    const auto *PCD = cast<PragmaCommentDecl>(D);
+    switch (PCD->getCommentKind()) {
+    case PCK_Unknown:
+      llvm_unreachable("unexpected pragma comment kind");
+    case PCK_Linker:
+      AppendLinkerOptions(PCD->getArg());
+      break;
+    case PCK_Lib:
+      AddDependentLib(PCD->getArg());
+      break;
+    case PCK_Compiler:
+    case PCK_ExeStr:
+    case PCK_User:
+      break; // We ignore all of these.
+    }
+    break;
+  }
+
   case Decl::LinkageSpec:
     EmitLinkageSpec(cast<LinkageSpecDecl>(D));
     break;
index 234a773..968cc46 100644 (file)
@@ -104,9 +104,9 @@ namespace {
                                                *M, Diags, CoverageInfo));
 
       for (auto &&Lib : CodeGenOpts.DependentLibraries)
-        HandleDependentLibrary(Lib);
+        Builder->AddDependentLib(Lib);
       for (auto &&Opt : CodeGenOpts.LinkerOptions)
-        HandleLinkerOption(Opt);
+        Builder->AppendLinkerOptions(Opt);
     }
 
     void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override {
@@ -234,18 +234,10 @@ namespace {
       Builder->EmitVTable(RD);
     }
 
-    void HandleLinkerOption(llvm::StringRef Opts) override {
-      Builder->AppendLinkerOptions(Opts);
-    }
-
     void HandleDetectMismatch(llvm::StringRef Name,
                               llvm::StringRef Value) override {
       Builder->AddDetectMismatch(Name, Value);
     }
-
-    void HandleDependentLibrary(llvm::StringRef Lib) override {
-      Builder->AddDependentLib(Lib);
-    }
   };
 }
 
index 12cd86a..95e9bec 100644 (file)
@@ -317,21 +317,11 @@ void MultiplexConsumer::HandleImplicitImportDecl(ImportDecl *D) {
     Consumer->HandleImplicitImportDecl(D);
 }
 
-void MultiplexConsumer::HandleLinkerOption(llvm::StringRef Opts) {
-  for (auto &Consumer : Consumers)
-    Consumer->HandleLinkerOption(Opts);
-}
-
 void MultiplexConsumer::HandleDetectMismatch(llvm::StringRef Name, llvm::StringRef Value) {
   for (auto &Consumer : Consumers)
     Consumer->HandleDetectMismatch(Name, Value);
 }
 
-void MultiplexConsumer::HandleDependentLibrary(llvm::StringRef Lib) {
-  for (auto &Consumer : Consumers)
-    Consumer->HandleDependentLibrary(Lib);
-}
-
 void MultiplexConsumer::CompleteTentativeDefinition(VarDecl *D) {
   for (auto &Consumer : Consumers)
     Consumer->CompleteTentativeDefinition(D);
index 42f8b51..06c1a17 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "RAIIObjectsForParser.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/Basic/PragmaKinds.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Parse/ParseDiagnostic.h"
@@ -1793,22 +1794,22 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
 
   // Verify that this is one of the 5 whitelisted options.
   IdentifierInfo *II = Tok.getIdentifierInfo();
-  Sema::PragmaMSCommentKind Kind =
-    llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
-    .Case("linker",   Sema::PCK_Linker)
-    .Case("lib",      Sema::PCK_Lib)
-    .Case("compiler", Sema::PCK_Compiler)
-    .Case("exestr",   Sema::PCK_ExeStr)
-    .Case("user",     Sema::PCK_User)
-    .Default(Sema::PCK_Unknown);
-  if (Kind == Sema::PCK_Unknown) {
+  PragmaMSCommentKind Kind =
+    llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
+    .Case("linker",   PCK_Linker)
+    .Case("lib",      PCK_Lib)
+    .Case("compiler", PCK_Compiler)
+    .Case("exestr",   PCK_ExeStr)
+    .Case("user",     PCK_User)
+    .Default(PCK_Unknown);
+  if (Kind == PCK_Unknown) {
     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
     return;
   }
 
   // On PS4, issue a warning about any pragma comments other than
   // #pragma comment lib.
-  if (PP.getTargetInfo().getTriple().isPS4() && Kind != Sema::PCK_Lib) {
+  if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
     PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
       << II->getName();
     return;
@@ -1844,7 +1845,7 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
   if (PP.getPPCallbacks())
     PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
 
-  Actions.ActOnPragmaMSComment(Kind, ArgumentString);
+  Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
 }
 
 // #pragma clang optimize off
index f314571..1900d80 100644 (file)
@@ -269,23 +269,12 @@ void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
   MSStructPragmaOn = (Kind == PMSST_ON);
 }
 
-void Sema::ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg) {
-  // FIXME: Serialize this.
-  switch (Kind) {
-  case PCK_Unknown:
-    llvm_unreachable("unexpected pragma comment kind");
-  case PCK_Linker:
-    Consumer.HandleLinkerOption(Arg);
-    return;
-  case PCK_Lib:
-    Consumer.HandleDependentLibrary(Arg);
-    return;
-  case PCK_Compiler:
-  case PCK_ExeStr:
-  case PCK_User:
-    return;  // We ignore all of these.
-  }
-  llvm_unreachable("invalid pragma comment kind");
+void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc,
+                                PragmaMSCommentKind Kind, StringRef Arg) {
+  auto *PCD = PragmaCommentDecl::Create(
+      Context, Context.getTranslationUnitDecl(), CommentLoc, Kind, Arg);
+  Context.getTranslationUnitDecl()->addDecl(PCD);
+  Consumer.HandleTopLevelDecl(DeclGroupRef(PCD));
 }
 
 void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) {
index fdf1c73..844bdd1 100644 (file)
@@ -334,6 +334,11 @@ TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
 }
 
 Decl *
+TemplateDeclInstantiator::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
+  llvm_unreachable("pragma comment cannot be instantiated");
+}
+
+Decl *
 TemplateDeclInstantiator::VisitExternCContextDecl(ExternCContextDecl *D) {
   llvm_unreachable("extern \"C\" context cannot be instantiated");
 }
index 0b4772a..067653d 100644 (file)
@@ -319,6 +319,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
   case Decl::ObjCCompatibleAlias:
   case Decl::LinkageSpec:
   case Decl::ObjCPropertyImpl:
+  case Decl::PragmaComment:
   case Decl::FileScopeAsm:
   case Decl::AccessSpec:
   case Decl::Friend:
index f484345..a7eded1 100644 (file)
@@ -68,6 +68,10 @@ namespace clang {
       return Reader.ReadDeclID(F, R, I);
     }
 
+    std::string ReadString(const RecordData &R, unsigned &I) {
+      return Reader.ReadString(R, I);
+    }
+
     void ReadDeclIDList(SmallVectorImpl<DeclID> &IDs) {
       for (unsigned I = 0, Size = Record[Idx++]; I != Size; ++I)
         IDs.push_back(ReadDeclID(Record, Idx));
@@ -238,6 +242,7 @@ namespace clang {
     }
 
     void VisitDecl(Decl *D);
+    void VisitPragmaCommentDecl(PragmaCommentDecl *D);
     void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
     void VisitNamedDecl(NamedDecl *ND);
     void VisitLabelDecl(LabelDecl *LD);
@@ -538,6 +543,15 @@ void ASTDeclReader::VisitDecl(Decl *D) {
   }
 }
 
+void ASTDeclReader::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
+  VisitDecl(D);
+  D->setLocation(ReadSourceLocation(Record, Idx));
+  D->CommentKind = (PragmaMSCommentKind)Record[Idx++];
+  std::string Arg = ReadString(Record, Idx);
+  memcpy(D->getTrailingObjects<char>(), Arg.data(), Arg.size());
+  D->getTrailingObjects<char>()[Arg.size()] = '\0';
+}
+
 void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
   llvm_unreachable("Translation units are not serialized");
 }
@@ -2418,6 +2432,7 @@ static bool isConsumerInterestedIn(Decl *D, bool HasBody) {
       isa<ObjCProtocolDecl>(D) || 
       isa<ObjCImplDecl>(D) ||
       isa<ImportDecl>(D) ||
+      isa<PragmaCommentDecl>(D) ||
       isa<OMPThreadPrivateDecl>(D))
     return true;
   if (VarDecl *Var = dyn_cast<VarDecl>(D))
@@ -3335,6 +3350,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
   case DECL_OMP_CAPTUREDEXPR:
     D = OMPCapturedExprDecl::CreateDeserialized(Context, ID);
     break;
+  case DECL_PRAGMA_COMMENT:
+    D = PragmaCommentDecl::CreateDeserialized(Context, ID, Record[Idx++]);
+    break;
   case DECL_EMPTY:
     D = EmptyDecl::CreateDeserialized(Context, ID);
     break;
index 6ff3f95..bf36af6 100644 (file)
@@ -49,6 +49,7 @@ namespace clang {
     void Visit(Decl *D);
 
     void VisitDecl(Decl *D);
+    void VisitPragmaCommentDecl(PragmaCommentDecl *D);
     void VisitTranslationUnitDecl(TranslationUnitDecl *D);
     void VisitNamedDecl(NamedDecl *D);
     void VisitLabelDecl(LabelDecl *LD);
@@ -315,6 +316,16 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
   }
 }
 
+void ASTDeclWriter::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
+  StringRef Arg = D->getArg();
+  Record.push_back(Arg.size());
+  VisitDecl(D);
+  Writer.AddSourceLocation(D->getLocStart(), Record);
+  Record.push_back(D->getCommentKind());
+  Writer.AddString(Arg, Record);
+  Code = serialization::DECL_PRAGMA_COMMENT;
+}
+
 void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
   llvm_unreachable("Translation units aren't directly serialized");
 }
diff --git a/clang/test/PCH/pragma-comment.c b/clang/test/PCH/pragma-comment.c
new file mode 100644 (file)
index 0000000..14cbf6a
--- /dev/null
@@ -0,0 +1,22 @@
+// Test this without pch.
+// RUN: %clang_cc1 %s -Wunknown-pragmas -Werror -triple x86_64-pc-win32 -fms-extensions -emit-llvm -include %s -o - | FileCheck %s
+
+// Test with pch.
+// RUN: %clang_cc1 %s -Wunknown-pragmas -Werror -triple x86_64-pc-win32 -fms-extensions -emit-pch -o %t
+// RUN: %clang_cc1 %s -Wunknown-pragmas -Werror -triple x86_64-pc-win32 -fms-extensions -emit-llvm -include-pch %t -o - | FileCheck %s
+
+// 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.
+
+#ifndef HEADER
+#define HEADER
+#pragma comment(lib, "foo.lib")
+
+#else
+
+// CHECK: "/DEFAULTLIB:foo.lib"
+
+#endif
index db1849b..f4fa07c 100644 (file)
@@ -5586,6 +5586,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
   case Decl::OMPThreadPrivate:
   case Decl::ObjCTypeParam:
   case Decl::BuiltinTemplate:
+  case Decl::PragmaComment:
     return C;
 
   // Declaration kinds that don't make any sense here, but are