summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/ASTConsumer.h11
-rw-r--r--clang/include/clang/Parse/Parser.h4
-rw-r--r--clang/include/clang/Sema/Sema.h13
-rw-r--r--clang/lib/CodeGen/CodeGenAction.cpp8
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp45
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h9
-rw-r--r--clang/lib/CodeGen/ModuleBuilder.cpp9
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp32
-rw-r--r--clang/lib/CodeGen/TargetInfo.h6
-rw-r--r--clang/lib/Parse/ParsePragma.cpp23
-rw-r--r--clang/lib/Parse/ParsePragma.h5
-rw-r--r--clang/lib/Parse/Parser.cpp2
-rw-r--r--clang/lib/Sema/SemaAttr.cpp21
-rw-r--r--clang/test/Modules/autolink.m2
14 files changed, 163 insertions, 27 deletions
diff --git a/clang/include/clang/AST/ASTConsumer.h b/clang/include/clang/AST/ASTConsumer.h
index ae779436a9d..33e9bd92a47 100644
--- a/clang/include/clang/AST/ASTConsumer.h
+++ b/clang/include/clang/AST/ASTConsumer.h
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
#define LLVM_CLANG_AST_ASTCONSUMER_H
+#include "llvm/ADT/StringRef.h"
+
namespace clang {
class ASTContext;
class CXXRecordDecl;
@@ -86,6 +88,15 @@ public:
/// The default implementation passes it to HandleTopLevelDecl.
virtual void HandleImplicitImportDecl(ImportDecl *D);
+ /// \brief Handle a pragma that appends to Linker Options. Currently this
+ /// only exists to support Microsoft's #pragma comment(linker, "/foo").
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {}
+
+ /// \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/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 1029a90c55c..72acacf5ae6 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -419,6 +419,10 @@ private:
void HandlePragmaMSStruct();
/// \brief Handle the annotation token produced for
+ /// #pragma comment...
+ void HandlePragmaMSComment();
+
+ /// \brief Handle the annotation token produced for
/// #pragma align...
void HandlePragmaAlign();
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d7c80f2e4f9..f75ac93a908 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -49,6 +49,7 @@
#include "llvm/MC/MCParser/MCAsmParser.h"
#include <deque>
#include <string>
+#include <vector>
namespace llvm {
class APSInt;
@@ -6584,6 +6585,15 @@ 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,
@@ -6595,6 +6605,9 @@ public:
/// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
+ /// ActOnPragmaMSStruct - Called on well formed \#pragma comment(kind, "arg").
+ void ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg);
+
/// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
void ActOnPragmaUnused(const Token &Identifier,
Scope *curScope,
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 679cfeb6ed3..9570076574c 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -179,6 +179,14 @@ namespace clang {
Gen->HandleVTable(RD, DefinitionRequired);
}
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {
+ Gen->HandleLinkerOptionPragma(Opts);
+ }
+
+ virtual void HandleDependentLibrary(llvm::StringRef Opts) {
+ 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 0b03a3c4b67..1da4e87c0a5 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -186,7 +186,8 @@ void CodeGenModule::Release() {
EmitStaticExternCAliases();
EmitLLVMUsed();
- if (CodeGenOpts.Autolink && Context.getLangOpts().Modules) {
+ if (CodeGenOpts.Autolink &&
+ (Context.getLangOpts().Modules || !LinkerOptionsMetadata.empty())) {
EmitModuleLinkOptions();
}
@@ -762,31 +763,41 @@ void CodeGenModule::EmitLLVMUsed() {
GV->setSection("llvm.metadata");
}
+void CodeGenModule::AppendLinkerOptions(StringRef Opts) {
+ llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opts);
+ LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
+}
+
+void CodeGenModule::AddDependentLib(StringRef Lib) {
+ llvm::SmallString<24> Opt;
+ getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt);
+ llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opt);
+ LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
+}
+
/// \brief Add link options implied by the given module, including modules
/// it depends on, using a postorder walk.
-static void addLinkOptionsPostorder(llvm::LLVMContext &Context,
+static void addLinkOptionsPostorder(CodeGenModule &CGM,
Module *Mod,
SmallVectorImpl<llvm::Value *> &Metadata,
llvm::SmallPtrSet<Module *, 16> &Visited) {
// Import this module's parent.
if (Mod->Parent && Visited.insert(Mod->Parent)) {
- addLinkOptionsPostorder(Context, Mod->Parent, Metadata, Visited);
+ addLinkOptionsPostorder(CGM, Mod->Parent, Metadata, Visited);
}
// Import this module's dependencies.
for (unsigned I = Mod->Imports.size(); I > 0; --I) {
if (Visited.insert(Mod->Imports[I-1]))
- addLinkOptionsPostorder(Context, Mod->Imports[I-1], Metadata, Visited);
+ addLinkOptionsPostorder(CGM, Mod->Imports[I-1], Metadata, Visited);
}
// Add linker options to link against the libraries/frameworks
// described by this module.
+ llvm::LLVMContext &Context = CGM.getLLVMContext();
for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) {
- // FIXME: -lfoo is Unix-centric and -framework Foo is Darwin-centric.
- // We need to know more about the linker to know how to encode these
- // options propertly.
-
- // Link against a framework.
+ // Link against a framework. Frameworks are currently Darwin only, so we
+ // don't to ask TargetCodeGenInfo for the spelling of the linker option.
if (Mod->LinkLibraries[I-1].IsFramework) {
llvm::Value *Args[2] = {
llvm::MDString::get(Context, "-framework"),
@@ -798,9 +809,10 @@ static void addLinkOptionsPostorder(llvm::LLVMContext &Context,
}
// Link against a library.
- llvm::Value *OptString
- = llvm::MDString::get(Context,
- "-l" + Mod->LinkLibraries[I-1].Library);
+ llvm::SmallString<24> Opt;
+ CGM.getTargetCodeGenInfo().getDependentLibraryOption(
+ Mod->LinkLibraries[I-1].Library, Opt);
+ llvm::Value *OptString = llvm::MDString::get(Context, Opt);
Metadata.push_back(llvm::MDNode::get(Context, OptString));
}
}
@@ -852,20 +864,23 @@ void CodeGenModule::EmitModuleLinkOptions() {
}
// Add link options for all of the imported modules in reverse topological
- // order.
+ // order. We don't do anything to try to order import link flags with respect
+ // to linker options inserted by things like #pragma comment().
SmallVector<llvm::Value *, 16> MetadataArgs;
Visited.clear();
for (llvm::SetVector<clang::Module *>::iterator M = LinkModules.begin(),
MEnd = LinkModules.end();
M != MEnd; ++M) {
if (Visited.insert(*M))
- addLinkOptionsPostorder(getLLVMContext(), *M, MetadataArgs, Visited);
+ addLinkOptionsPostorder(*this, *M, MetadataArgs, Visited);
}
std::reverse(MetadataArgs.begin(), MetadataArgs.end());
+ LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end());
// Add the linker options metadata flag.
getModule().addModuleFlag(llvm::Module::AppendUnique, "Linker Options",
- llvm::MDNode::get(getLLVMContext(), MetadataArgs));
+ llvm::MDNode::get(getLLVMContext(),
+ LinkerOptionsMetadata));
}
void CodeGenModule::EmitDeferred() {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 91138c607c3..1d6c7e98e5c 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -355,6 +355,9 @@ class CodeGenModule : public CodeGenTypeCache {
/// \brief The complete set of modules that has been imported.
llvm::SetVector<clang::Module *> ImportedModules;
+ /// \brief A vector of metadata strings.
+ SmallVector<llvm::Value *, 16> LinkerOptionsMetadata;
+
/// @name Cache for Objective-C runtime types
/// @{
@@ -906,6 +909,12 @@ public:
void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired);
+ /// \brief Appends Opts to the "Linker Options" metadata value.
+ void AppendLinkerOptions(StringRef Opts);
+
+ /// \brief Appends a dependent lib to the "Linker Options" metadata value.
+ void AddDependentLib(StringRef Lib);
+
llvm::GlobalVariable::LinkageTypes
getFunctionLinkage(const FunctionDecl *FD);
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp
index 69e5b323045..56067a47bbd 100644
--- a/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -20,6 +20,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
@@ -115,6 +116,14 @@ namespace {
Builder->EmitVTable(RD, DefinitionRequired);
}
+
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {
+ Builder->AppendLinkerOptions(Opts);
+ }
+
+ virtual void HandleDependentLibrary(llvm::StringRef Lib) {
+ Builder->AddDependentLib(Lib);
+ }
};
}
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 32b27b3172a..45fc475e341 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -143,6 +143,16 @@ bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList &args,
return false;
}
+void
+TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const {
+ // This assumes the user is passing a library name like "rt" instead of a
+ // filename like "librt.a/so", and that they don't care whether it's static or
+ // dynamic.
+ Opt = "-l";
+ Opt += Lib;
+}
+
static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
/// isEmptyField - Return true iff a the field is "empty", that is it
@@ -1256,6 +1266,18 @@ public:
};
+class WinX86_32TargetCodeGenInfo : public X86_32TargetCodeGenInfo {
+public:
+ WinX86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned RegParms)
+ : X86_32TargetCodeGenInfo(CGT, false, true, true, RegParms) {}
+
+ void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const {
+ Opt = "/DEFAULTLIB:";
+ Opt += Lib;
+ }
+};
+
class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
public:
WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
@@ -1274,6 +1296,12 @@ public:
AssignToArrayRange(CGF.Builder, Address, Eight8, 0, 16);
return false;
}
+
+ void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const {
+ Opt = "/DEFAULTLIB:";
+ Opt += Lib;
+ }
};
}
@@ -5173,8 +5201,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
case llvm::Triple::Win32:
return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Types, false, true, true,
- CodeGenOpts.NumRegisterParameters));
+ new WinX86_32TargetCodeGenInfo(Types,
+ CodeGenOpts.NumRegisterParameters));
default:
return *(TheTargetCodeGenInfo =
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index bb50ce69e31..dee7fd8dd40 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -18,6 +18,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
namespace llvm {
class GlobalValue;
@@ -167,6 +168,11 @@ namespace clang {
/// that unprototyped calls to varargs functions still succeed.
virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args,
const FunctionNoProtoType *fnType) const;
+
+ /// Gets the linker options necessary to link a dependent library on this
+ /// platform.
+ virtual void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const;
};
}
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 3d1249aa684..3c6f96ac2be 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -821,10 +821,16 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
}
// Verify that this is one of the 5 whitelisted options.
- // FIXME: warn that 'exestr' is deprecated.
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- if (!II->isStr("compiler") && !II->isStr("exestr") && !II->isStr("lib") &&
- !II->isStr("linker") && !II->isStr("user")) {
+ 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) {
PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
return;
}
@@ -837,11 +843,12 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
/*MacroExpansion=*/true))
return;
+ // FIXME: warn that 'exestr' is deprecated.
// FIXME: If the kind is "compiler" warn if the string is present (it is
// ignored).
- // FIXME: 'lib' requires a comment string.
- // FIXME: 'linker' requires a comment string, and has a specific list of
- // things that are allowable.
+ // The MSDN docs say that "lib" and "linker" require a string and have a short
+ // whitelist of linker options they support, but in practice MSVC doesn't
+ // issue a diagnostic. Therefore neither does clang.
if (Tok.isNot(tok::r_paren)) {
PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
@@ -857,4 +864,6 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
// If the pragma is lexically sound, notify any interested PPCallbacks.
if (PP.getPPCallbacks())
PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
+
+ Actions.ActOnPragmaMSComment(Kind, ArgumentString);
}
diff --git a/clang/lib/Parse/ParsePragma.h b/clang/lib/Parse/ParsePragma.h
index d9560f3181d..3c6f3434ad0 100644
--- a/clang/lib/Parse/ParsePragma.h
+++ b/clang/lib/Parse/ParsePragma.h
@@ -116,9 +116,12 @@ public:
/// PragmaCommentHandler - "\#pragma comment ...".
class PragmaCommentHandler : public PragmaHandler {
public:
- PragmaCommentHandler() : PragmaHandler("comment") {}
+ PragmaCommentHandler(Sema &Actions)
+ : PragmaHandler("comment"), Actions(Actions) {}
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken);
+private:
+ Sema &Actions;
};
} // end namespace clang
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 455139b881a..2117df45f3a 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -103,7 +103,7 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
PP.AddPragmaHandler(OpenMPHandler.get());
if (getLangOpts().MicrosoftExt) {
- MSCommentHandler.reset(new PragmaCommentHandler());
+ MSCommentHandler.reset(new PragmaCommentHandler(actions));
PP.AddPragmaHandler(MSCommentHandler.get());
}
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index e12bbde0d0d..bc19b382989 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
@@ -263,6 +264,26 @@ void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
MSStructPragmaOn = (Kind == PMSST_ON);
}
+void Sema::ActOnPragmaMSComment(PragmaMSCommentKind Kind, llvm::StringRef Arg) {
+ // FIXME: Serialize this.
+ switch (Kind) {
+ case PCK_Unknown:
+ llvm_unreachable("unexpected pragma comment kind");
+ case PCK_Linker:
+ Consumer.HandleLinkerOptionPragma(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::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
SourceLocation PragmaLoc) {
diff --git a/clang/test/Modules/autolink.m b/clang/test/Modules/autolink.m
index 4bf9d592a8f..2b31fe51542 100644
--- a/clang/test/Modules/autolink.m
+++ b/clang/test/Modules/autolink.m
@@ -35,7 +35,7 @@ int use_no_umbrella() {
// CHECK: !4 = metadata !{i32 6, metadata !"Linker Options", metadata ![[AUTOLINK_OPTIONS:[0-9]+]]}
// CHECK: ![[AUTOLINK_OPTIONS]] = metadata !{metadata ![[AUTOLINK_FRAMEWORK:[0-9]+]], metadata ![[AUTOLINK:[0-9]+]], metadata ![[DEPENDSONMODULE:[0-9]+]], metadata ![[MODULE:[0-9]+]], metadata ![[NOUMBRELLA:[0-9]+]]}
// CHECK: ![[AUTOLINK_FRAMEWORK]] = metadata !{metadata !"-framework", metadata !"autolink_framework"}
-// CHECK: ![[AUTOLINK]] = metadata !{metadata !"-lautolink"}
+// CHECK: ![[AUTOLINK]] = metadata !{metadata !"{{(-l|/DEFAULTLIB:)}}autolink"}
// CHECK: ![[DEPENDSONMODULE]] = metadata !{metadata !"-framework", metadata !"DependsOnModule"}
// CHECK: ![[MODULE]] = metadata !{metadata !"-framework", metadata !"Module"}
// CHECK: ![[NOUMBRELLA]] = metadata !{metadata !"-framework", metadata !"NoUmbrella"}
OpenPOWER on IntegriCloud