summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTConsumer.h10
-rw-r--r--clang/include/clang/AST/Decl.h35
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h2
-rw-r--r--clang/include/clang/Basic/DeclNodes.td1
-rw-r--r--clang/include/clang/Basic/PragmaKinds.h26
-rw-r--r--clang/include/clang/Frontend/MultiplexConsumer.h2
-rw-r--r--clang/include/clang/Sema/Sema.h13
-rw-r--r--clang/include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--clang/lib/AST/ASTContext.cpp4
-rw-r--r--clang/lib/AST/ASTDumper.cpp16
-rw-r--r--clang/lib/AST/Decl.cpp23
-rw-r--r--clang/lib/AST/DeclBase.cpp1
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp1
-rw-r--r--clang/lib/CodeGen/CodeGenAction.cpp8
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp19
-rw-r--r--clang/lib/CodeGen/ModuleBuilder.cpp12
-rw-r--r--clang/lib/Frontend/MultiplexConsumer.cpp10
-rw-r--r--clang/lib/Parse/ParsePragma.cpp23
-rw-r--r--clang/lib/Sema/SemaAttr.cpp23
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp5
-rw-r--r--clang/lib/Serialization/ASTCommon.cpp1
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp18
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp11
-rw-r--r--clang/test/PCH/pragma-comment.c22
-rw-r--r--clang/tools/libclang/CIndex.cpp1
25 files changed, 211 insertions, 80 deletions
diff --git a/clang/include/clang/AST/ASTConsumer.h b/clang/include/clang/AST/ASTConsumer.h
index 7c0acbc6b36..7aea66bd06f 100644
--- a/clang/include/clang/AST/ASTConsumer.h
+++ b/clang/include/clang/AST/ASTConsumer.h
@@ -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.
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index a545e218143..569c23a6784 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -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:
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 58850f55944..76e870a4eec 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1359,6 +1359,8 @@ DEF_TRAVERSE_DECL(
// D->getAnonymousNamespace().
})
+DEF_TRAVERSE_DECL(PragmaCommentDecl, {})
+
DEF_TRAVERSE_DECL(ExternCContextDecl, {})
DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td
index a8d4520e062..9f4296132d6 100644
--- a/clang/include/clang/Basic/DeclNodes.td
+++ b/clang/include/clang/Basic/DeclNodes.td
@@ -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
index 00000000000..be3eabb0011
--- /dev/null
+++ b/clang/include/clang/Basic/PragmaKinds.h
@@ -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
diff --git a/clang/include/clang/Frontend/MultiplexConsumer.h b/clang/include/clang/Frontend/MultiplexConsumer.h
index 3e8c52438de..2021a7676c0 100644
--- a/clang/include/clang/Frontend/MultiplexConsumer.h
+++ b/clang/include/clang/Frontend/MultiplexConsumer.h
@@ -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;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ec1ade4926a..10fd4850965 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -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
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 09df5379973..b58f4157bdc 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -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.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index dad6d1a9d4f..0579bca3fe7 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -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;
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index 809b1dd6bd4..e0ef80d475f 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 7378c44178b..e22f1bcf0f2 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -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,
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index d41d25f7a44..91bc809cf48 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -641,6 +641,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case FileScopeAsm:
case StaticAssert:
case ObjCPropertyImpl:
+ case PragmaComment:
case Block:
case Captured:
case TranslationUnit:
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 5b88ef1830f..f9a6b06a4a9 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -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:
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 3d333c88f99..8d081144902 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -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);
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index b98094f6656..887c53331f6 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -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;
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp
index 234a7736065..968cc46f7e7 100644
--- a/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -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);
- }
};
}
diff --git a/clang/lib/Frontend/MultiplexConsumer.cpp b/clang/lib/Frontend/MultiplexConsumer.cpp
index 12cd86af83c..95e9bec6a4e 100644
--- a/clang/lib/Frontend/MultiplexConsumer.cpp
+++ b/clang/lib/Frontend/MultiplexConsumer.cpp
@@ -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);
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 42f8b518b17..06c1a17bdd4 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -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
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index f3145713d58..1900d80b217 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -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) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index fdf1c73bfc6..844bdd1fa07 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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");
}
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index 0b4772a5353..067653dfbf2 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -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:
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index f484345dfc5..a7eded1a2fd 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -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;
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 6ff3f954168..bf36af6bd5a 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -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
index 00000000000..14cbf6a2b51
--- /dev/null
+++ b/clang/test/PCH/pragma-comment.c
@@ -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
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index db1849bba2d..f4fa07c7fa8 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -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
OpenPOWER on IntegriCloud