Skip to content

Commit

Permalink
Serialize #pragma comment.
Browse files Browse the repository at this point in the history
`#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
  • Loading branch information
nico committed Mar 2, 2016
1 parent 3ca9ee0 commit 6622029
Show file tree
Hide file tree
Showing 25 changed files with 211 additions and 80 deletions.
10 changes: 0 additions & 10 deletions clang/include/clang/AST/ASTConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,12 @@ class ASTConsumer {
/// 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.
Expand Down
35 changes: 35 additions & 0 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -103,6 +104,40 @@ class TranslationUnitDecl : public Decl, public DeclContext {
}
};

/// \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:
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1359,6 +1359,8 @@ DEF_TRAVERSE_DECL(
// D->getAnonymousNamespace().
})

DEF_TRAVERSE_DECL(PragmaCommentDecl, {})

DEF_TRAVERSE_DECL(ExternCContextDecl, {})

DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DeclNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
26 changes: 26 additions & 0 deletions clang/include/clang/Basic/PragmaKinds.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 0 additions & 2 deletions clang/include/clang/Frontend/MultiplexConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,8 @@ class MultiplexConsumer : public SemaConsumer {
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;
Expand Down
13 changes: 3 additions & 10 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -7615,15 +7616,6 @@ class Sema {
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,
Expand All @@ -7637,7 +7629,8 @@ class Sema {

/// 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
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions clang/lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down
23 changes: 23 additions & 0 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case FileScopeAsm:
case StaticAssert:
case ObjCPropertyImpl:
case PragmaComment:
case Block:
case Captured:
case TranslationUnit:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 0 additions & 8 deletions clang/lib/CodeGen/CodeGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 2 additions & 10 deletions clang/lib/CodeGen/ModuleBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
};
}

Expand Down
10 changes: 0 additions & 10 deletions clang/lib/Frontend/MultiplexConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 6622029

Please sign in to comment.