diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -300,6 +300,14 @@ ``MSInheritanceAttr`` attributes to class template instantiations created for explicit template instantiation declarations. +- The ``-fno-auto-import`` option was added for MinGW targets. The option both + affects code generation (inhibiting generating indirection via ``.refptr`` + stubs for potentially auto imported symbols, generating smaller and more + efficient code) and linking (making the linker error out on such cases). + If the option only is used during code generation but not when linking, + linking may succeed but the resulting executables may expose issues at + runtime. + LoongArch Support ^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -38,6 +38,7 @@ CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new CODEGENOPT(AssumeUniqueVTables , 1, 1) ///< Assume a class has only one vtable. CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink +CODEGENOPT(AutoImport , 1, 1) ///< -fno-auto-import CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. CODEGENOPT(Backchain , 1, 0) ///< -mbackchain CODEGENOPT(ControlFlowGuardNoChecks , 1, 0) ///< -cfguard-no-checks diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1469,6 +1469,17 @@ "Disable generation of linker directives for automatic library linking">, PosFlag>; +let Flags = [TargetSpecific] in { +defm auto_import : BoolFOption<"auto-import", + CodeGenOpts<"AutoImport">, DefaultTrue, + NegFlag, + PosFlag>; +} // let Flags = [TargetSpecific] + // In the future this option will be supported by other offloading // languages and accept other values such as CPU/GPU architectures, // offload kinds and target aliases. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1419,6 +1419,7 @@ return false; const llvm::Triple &TT = CGM.getTriple(); + const auto &CGOpts = CGM.getCodeGenOpts(); if (TT.isWindowsGNUEnvironment()) { // In MinGW, variables without DLLImport can still be automatically // imported from a DLL by the linker; don't mark variables that @@ -1429,7 +1430,8 @@ // such variables can't be marked as DSO local. (Native TLS variables // can't be dllimported at all, though.) if (GV->isDeclarationForLinker() && isa(GV) && - (!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS)) + (!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS) && + CGOpts.AutoImport) return false; } @@ -1452,7 +1454,6 @@ return false; // If this is not an executable, don't assume anything is local. - const auto &CGOpts = CGM.getCodeGenOpts(); llvm::Reloc::Model RM = CGOpts.RelocationModel; const auto &LOpts = CGM.getLangOpts(); if (RM != llvm::Reloc::Static && !LOpts.PIE) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5623,6 +5623,11 @@ CmdArgs.push_back("-mms-bitfields"); } + if (Triple.isWindowsGNUEnvironment()) { + Args.addOptOutFlag(CmdArgs, options::OPT_fauto_import, + options::OPT_fno_auto_import); + } + // Non-PIC code defaults to -fdirect-access-external-data while PIC code // defaults to -fno-direct-access-external-data. Pass the option if different // from the default. diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -169,6 +169,10 @@ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); + if (!Args.hasFlag(options::OPT_fauto_import, options::OPT_fno_auto_import, + true)) + CmdArgs.push_back("--disable-auto-import"); + if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) { StringRef GuardArgs = A->getValue(); if (GuardArgs == "none") diff --git a/clang/test/CodeGen/dso-local-executable.c b/clang/test/CodeGen/dso-local-executable.c --- a/clang/test/CodeGen/dso-local-executable.c +++ b/clang/test/CodeGen/dso-local-executable.c @@ -9,12 +9,14 @@ // COFF-DAG: define dso_local ptr @zed() // COFF-DAG: declare dllimport void @import_func() -// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - | FileCheck --check-prefixes=MINGW,MINGW-NATIVE_TLS %s -// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - -femulated-tls | FileCheck --check-prefixes=MINGW,MINGW-EMUTLS %s +// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - | FileCheck --check-prefixes=MINGW,MINGW-NATIVE_TLS,MINGW-AUTO-IMPORT %s +// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - -fno-auto-import | FileCheck --check-prefixes=MINGW,MINGW-NATIVE_TLS,MINGW-NO-AUTO-IMPORT %s +// RUN: %clang_cc1 -triple x86_64-w64-mingw32 -emit-llvm %s -o - -femulated-tls | FileCheck --check-prefixes=MINGW,MINGW-EMUTLS,MINGW-AUTO-IMPORT %s // MINGW: @baz = dso_local global i32 42 // MINGW-NEXT: @import_var = external dllimport global i32 // MINGW-NEXT: @weak_bar = extern_weak global i32 -// MINGW-NEXT: @bar = external global i32 +// MINGW-AUTO-IMPORT-NEXT: @bar = external global i32 +// MINGW-NO-AUTO-IMPORT-NEXT: @bar = external dso_local global i32 // MINGW-NEXT: @local_thread_var = dso_local thread_local global i32 42 // MINGW-NATIVE_TLS-NEXT: @thread_var = external dso_local thread_local global i32 // MINGW-EMUTLS-NEXT: @thread_var = external thread_local global i32 diff --git a/clang/test/Driver/mingw-auto-import.c b/clang/test/Driver/mingw-auto-import.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/mingw-auto-import.c @@ -0,0 +1,15 @@ +// By default, we don't pass any -fauto-import to -cc1, as that's the default. +// +// RUN: %clang --target=x86_64-w64-windows-gnu -### %s 2>&1 | FileCheck --check-prefixes=DEFAULT %s +// RUN: %clang --target=x86_64-w64-windows-gnu -fno-auto-import -fauto-import -### %s 2>&1 | FileCheck --check-prefixes=DEFAULT %s +// DEFAULT: "-cc1" +// DEFAULT-NOT: no-auto-import +// DEFAULT-NOT: --disable-auto-import + +// When compiling with -fno-auto-import, we pass -fno-auto-import to -cc1 +// and --disable-auto-import to the linker. +// +// RUN: %clang --target=x86_64-w64-windows-gnu -fauto-import -fno-auto-import -### %s 2>&1 | FileCheck --check-prefixes=NO_AUTOIMPORT %s +// NO_AUTOIMPORT: "-cc1" +// NO_AUTOIMPORT: "-fno-auto-import" +// NO_AUTOIMPORT: "--disable-auto-import"