Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -638,6 +638,11 @@ Flags<[DriverOption, CC1Option]>, HelpText<"Disable generation of linker directives for automatic library linking">; +def fir_type_names_EQ : Joined<["-"], "fir-type-names=">, + Flags<[CC1Option]>, + HelpText<"Whether to use IR type names (option: auto, never, always)">, + Values<"auto,never,always">; + // C++ Coroutines TS def fcoroutines_ts : Flag <["-"], "fcoroutines-ts">, Group, Flags<[DriverOption, CC1Option]>, Index: include/clang/Frontend/CodeGenOptions.h =================================================================== --- include/clang/Frontend/CodeGenOptions.h +++ include/clang/Frontend/CodeGenOptions.h @@ -107,6 +107,13 @@ Embed_Marker // Embed a marker as a placeholder for bitcode. }; + /// Should LLVM types be given human-readable names? + enum IRNameKind { + IRNames_Auto, ///< Determine from other options. + IRNames_Never, ///< No type names. + IRNames_Always ///< Types must be named. + }; + /// The code model to use (-mcmodel). std::string CodeModel; Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -72,6 +72,11 @@ CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled. /// \brief Embed Bitcode mode (off/all/bitcode/marker). ENUM_CODEGENOPT(EmbedBitcode, EmbedBitcodeKind, 2, Embed_Off) + +/// Should LLVM IR types be given human-readable names? +/// \see CodeGenOptions::IRNameKind. +ENUM_CODEGENOPT(IRTypeNames, IRNameKind, 4, IRNames_Auto) + CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables ///< are required. CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled. Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -884,6 +884,25 @@ std::unique_ptr(CoverageInfo)); } + // Specify names for IR types in the cases: + // - if it requested explicitly, by option '-fir-type-names=use', + // - if compilation produces IR representation, or + // - in Debug build. + if (CI.getCodeGenOpts().getIRTypeNames() == CodeGenOptions::IRNames_Auto) { +#ifdef NDEBUG + if ((BA == Backend_EmitBC || + BA == Backend_EmitLL || + (BA == Backend_EmitObj && + CI.getCodeGenOpts().getEmbedBitcode() != CodeGenOptions::Embed_Off) || + !LinkModules.empty())) + CI.getCodeGenOpts().setIRTypeNames(CodeGenOptions::IRNames_Always); + else + CI.getCodeGenOpts().setIRTypeNames(CodeGenOptions::IRNames_Never); +#else + CI.getCodeGenOpts().setIRTypeNames(CodeGenOptions::IRNames_Always); +#endif + } + std::unique_ptr Result(new BackendConsumer( BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.cpp @@ -51,10 +51,13 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty, StringRef suffix) { + if (getCodeGenOpts().getIRTypeNames() == CodeGenOptions::IRNames_Never) + return; + SmallString<256> TypeName; llvm::raw_svector_ostream OS(TypeName); OS << RD->getKindName() << '.'; - + // Name the codegen type after the typedef name // if there is no tag type name available if (RD->getIdentifier()) { Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -3279,6 +3279,8 @@ if (C.getDriver().embedBitcodeMarkerOnly() && !C.getDriver().isUsingLTO()) CmdArgs.push_back("-fembed-bitcode=marker"); + Args.AddLastArg(CmdArgs, options::OPT_fir_type_names_EQ); + // We normally speed up the clang process a bit by skipping destructors at // exit, but when we're generating diagnostics we can rely on some of the // cleanup. Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -804,6 +804,20 @@ } } + if (Arg *A = Args.getLastArg(OPT_fir_type_names_EQ)) { + StringRef Name = A->getValue(); + auto Info = llvm::StringSwitch(Name) + .Case("auto", CodeGenOptions::IRNames_Auto) + .Case("never", CodeGenOptions::IRNames_Never) + .Case("always", CodeGenOptions::IRNames_Always) + .Default(-1); + if (Info == -1) { + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; + Success = false; + } else + Opts.setIRTypeNames(static_cast(Info)); + } + Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type); Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions); Opts.InstrumentFunctionsAfterInlining = Index: test/CodeGenCXX/pr29160.cpp =================================================================== --- test/CodeGenCXX/pr29160.cpp +++ test/CodeGenCXX/pr29160.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple i686-linux-gnu %s -o /dev/null -S -emit-llvm +// RUN: %clang_cc1 -std=c++11 -triple i686-linux-gnu -DNAMELESS -fir-type-names=never %s -o /dev/null -S -emit-llvm // // This test's failure mode is running ~forever. (For some value of "forever" // that's greater than 25 minutes on my machine) @@ -8,6 +9,7 @@ template static void ignore() {} Foo() { ignore(); } + struct ABC {}; }; struct Base { @@ -39,3 +41,9 @@ STAMP(Q, P); int main() { Q q; } + +#ifdef NAMELESS +// Without '-fir-type-names=none' compiler tries to create name for Q::ABC, +// which is really huge, so compilation never ends. +Q::ABC var; +#endif Index: test/CodeGenCXX/type-names.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/type-names.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -fir-type-names=always -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -fir-type-names=never -o - %s | FileCheck %s --check-prefix=UNNAMED + +struct C1 { + int a; + int *b; +}; + +C1 var_C1_a; +C1 var_C1_b[10]; +C1 *var_C1_c; +int (*var_C1_d)(const C1 &); + +struct C1A { + int a; + int *b; +}; + +C1A var_C1A_a; + +template struct C2 { + C1 a; + T b; + struct Inner { + }; +}; + +C2 var_C2_a; +C2 var_C2_b; +C2::Inner var_C2_c; + +struct C3 { + double a; + struct C4 { + int a; + float b; + }; +}; + +C3::C4 var_c4; + +namespace { +struct C5 { + int *a; +}; +} + +C5 var_C5_a; +void *var_C5_b = &var_C5_a; + +// CHECK: %struct.C1 = type { i32, i32* } +// CHECK: %struct.C1A = type { i32, i32* } +// CHECK: %struct.C2 = type { %struct.C1, i16 } +// CHECK: %struct.C2.0 = type { %struct.C1, i64 } +// CHECK: %"struct.C2::Inner" = type { i8 } +// CHECK: %"struct.C3::C4" = type { i32, float } +// CHECK: %"struct.(anonymous namespace)::C5" = type { i32* } + +// UNNAMED: %0 = type { i32, i32* } +// UNNAMED: %1 = type { i32, i32* } +// UNNAMED: %2 = type { %0, i16 } +// UNNAMED: %3 = type { %0, i64 } +// UNNAMED: %4 = type { i8 } +// UNNAMED: %5 = type { i32, float } +// UNNAMED: %6 = type { i32* }