Index: docs/LanguageExtensions.rst =================================================================== --- docs/LanguageExtensions.rst +++ docs/LanguageExtensions.rst @@ -2725,3 +2725,11 @@ * The decision about which section-kind applies to each global is taken in the back-end. Once the section-kind is known, appropriate section name, as specified by the user using ``#pragma clang section`` directive, is applied to that global. + +Specifying Linker Options on ELF Targets +======================================== + +The ``#pragma comment(lib, ...)`` directive is supported on all ELF targets. +The second parameter is the library name (without the traditional Unix prefix of +``lib``). This allows you to provide an implicit link of dependent libraries. + Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1094,6 +1094,8 @@ /// value. void AddDependentLib(StringRef Lib); + void AddELFLibDirective(StringRef Lib); + llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD); void setFunctionLinkage(GlobalDecl GD, llvm::Function *F) { Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -1411,6 +1411,12 @@ LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); } +void CodeGenModule::AddELFLibDirective(StringRef Lib) { + auto &C = getLLVMContext(); + LinkerOptionsMetadata.push_back(llvm::MDNode::get( + C, {llvm::MDString::get(C, "lib"), llvm::MDString::get(C, Lib)})); +} + void CodeGenModule::AddDependentLib(StringRef Lib) { llvm::SmallString<24> Opt; getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt); @@ -4345,7 +4351,11 @@ AppendLinkerOptions(PCD->getArg()); break; case PCK_Lib: - AddDependentLib(PCD->getArg()); + if (getTarget().getTriple().isOSBinFormatELF() && + !getTarget().getTriple().isPS4()) + AddELFLibDirective(PCD->getArg()); + else + AddDependentLib(PCD->getArg()); break; case PCK_Compiler: case PCK_ExeStr: Index: lib/Parse/ParsePragma.cpp =================================================================== --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -295,7 +295,8 @@ OpenMPHandler.reset(new PragmaNoOpenMPHandler()); PP.AddPragmaHandler(OpenMPHandler.get()); - if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { + if (getLangOpts().MicrosoftExt || + getTargetInfo().getTriple().isOSBinFormatELF()) { MSCommentHandler.reset(new PragmaCommentHandler(Actions)); PP.AddPragmaHandler(MSCommentHandler.get()); } @@ -377,7 +378,8 @@ PP.RemovePragmaHandler(OpenMPHandler.get()); OpenMPHandler.reset(); - if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { + if (getLangOpts().MicrosoftExt || + getTargetInfo().getTriple().isOSBinFormatELF()) { PP.RemovePragmaHandler(MSCommentHandler.get()); MSCommentHandler.reset(); } @@ -2449,6 +2451,12 @@ return; } + if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) + << II->getName(); + return; + } + // On PS4, issue a warning about any pragma comments other than // #pragma comment lib. if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) { Index: test/CodeGen/elf-linker-options.c =================================================================== --- /dev/null +++ test/CodeGen/elf-linker-options.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple i686---elf -emit-llvm %s -o - | FileCheck %s + +#pragma comment(lib, "alpha") + +// CHECK: !llvm.linker.options = !{[[NODE:![0-9]+]]} +// CHECK: [[NODE]] = !{!"lib", !"alpha"} + Index: test/CodeGen/pragma-comment.c =================================================================== --- test/CodeGen/pragma-comment.c +++ test/CodeGen/pragma-comment.c @@ -23,10 +23,9 @@ // CHECK: ![[bar]] = !{!" /bar=2"} // CHECK: ![[foo]] = !{!" /foo=\22foo bar\22"} -// LINUX: !{!"-lmsvcrt.lib"} -// LINUX: !{!"-lkernel32"} -// LINUX: !{!"-lUSER32.LIB"} -// LINUX: !{!" /bar=2"} +// LINUX: !{!"lib", !"msvcrt.lib"} +// LINUX: !{!"lib", !"kernel32"} +// LINUX: !{!"lib", !"USER32.LIB"} // PS4: !{!"\01msvcrt.lib"} // PS4: !{!"\01kernel32"} Index: test/Preprocessor/pragma-comment-linux.c =================================================================== --- /dev/null +++ test/Preprocessor/pragma-comment-linux.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fsyntax-only -verify %s -Wunknown-pragmas + +#pragma comment(linker, "") +// expected-warning@-1 {{'#pragma comment linker' ignored}} + Index: test/Preprocessor/pragma_microsoft.c =================================================================== --- test/Preprocessor/pragma_microsoft.c +++ test/Preprocessor/pragma_microsoft.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -Wunknown-pragmas -// RUN: not %clang_cc1 %s -fms-extensions -E | FileCheck %s +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc %s -fsyntax-only -verify -fms-extensions -Wunknown-pragmas +// RUN: not %clang_cc1 -triple i686-unknown-windows-msvc %s -fms-extensions -E | FileCheck %s // REQUIRES: non-ps4-sdk // rdar://6495941