Index: clang/include/clang/Basic/CodeGenOptions.def =================================================================== --- clang/include/clang/Basic/CodeGenOptions.def +++ clang/include/clang/Basic/CodeGenOptions.def @@ -162,6 +162,7 @@ CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled. CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN. CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt +CODEGENOPT(UniqueInternalFuncNames, 1, 0) ///< Internal Linkage functions get unique names. /// When false, this attempts to generate code as if the result of an /// overflowing conversion matches the overflowing behavior of a target's native Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1971,6 +1971,12 @@ def fno_unique_section_names : Flag <["-"], "fno-unique-section-names">, Group, Flags<[CC1Option]>; +def funique_internal_funcnames : Flag <["-"], "funique-internal-funcnames">, + Group, Flags<[CC1Option]>, + HelpText<"Uniqueify Internal Linkage Function Names">; +def fno_unique_internal_funcnames : Flag <["-"], "fno-unique-internal-funcnames">, + Group; + def fstrict_return : Flag<["-"], "fstrict-return">, Group, Flags<[CC1Option]>, HelpText<"Always treat control flow paths that fall off the end of a " Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -1124,6 +1124,23 @@ const auto *ND = cast(GD.getDecl()); std::string MangledName = getMangledNameImpl(*this, GD, ND); + // With option -funique-internal-funcnames, functions with internal linkage + // should get unique names. Use the hash of module name to get a unique + // identifier as this is a best-effort solution. + if (getCodeGenOpts().UniqueInternalFuncNames && + dyn_cast(GD.getDecl()) && + getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage && + !getModule().getSourceFileName().empty()) { + llvm::MD5 Md5; + Md5.update(getModule().getSourceFileName()); + llvm::MD5::MD5Result R; + Md5.final(R); + SmallString<32> Str; + llvm::MD5::stringifyResult(R, Str); + std::string UniqueSuffix = ("." + Str).str(); + MangledName += UniqueSuffix; + } + // Ensure either we have different ABIs between host and device compilations, // says host compilation following MSVC ABI but device compilation follows // Itanium C++ ABI or, if they follow the same ABI, kernel names after Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -4222,6 +4222,8 @@ options::OPT_fno_function_sections, options::OPT_fdata_sections, options::OPT_fno_data_sections, + options::OPT_funique_internal_funcnames, + options::OPT_fno_unique_internal_funcnames, options::OPT_funique_section_names, options::OPT_fno_unique_section_names, options::OPT_mrestrict_it, @@ -4819,6 +4821,10 @@ options::OPT_fno_unique_section_names, true)) CmdArgs.push_back("-fno-unique-section-names"); + if (Args.hasFlag(options::OPT_funique_internal_funcnames, + options::OPT_fno_unique_internal_funcnames, false)) + CmdArgs.push_back("-funique-internal-funcnames"); + Args.AddLastArg(CmdArgs, options::OPT_finstrument_functions, options::OPT_finstrument_functions_after_inlining, options::OPT_finstrument_function_entry_bare); Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -958,6 +958,7 @@ Opts.StackSizeSection = Args.hasArg(OPT_fstack_size_section); Opts.UniqueSectionNames = !Args.hasArg(OPT_fno_unique_section_names); + Opts.UniqueInternalFuncNames = Args.hasArg(OPT_funique_internal_funcnames); Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables); Index: clang/test/CodeGen/unique-internal-funcnames.c =================================================================== --- /dev/null +++ clang/test/CodeGen/unique-internal-funcnames.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64 -S -emit-llvm -o - < %s | FileCheck %s --check-prefix=PLAIN +// RUN: %clang_cc1 -triple x86_64 -S -emit-llvm -funique-internal-funcnames -o - < %s | FileCheck %s --check-prefix=UNIQUE + +static int foo() { + return 0; +} + +int (*bar())() { + return foo; +} + +// PLAIN: @foo() +// UNIQUE-NOT: @foo() +// UNIQUE: @foo.{{[0-9a-f]+}}() Index: clang/test/Driver/funique-internal-funcnames.c =================================================================== --- /dev/null +++ clang/test/Driver/funique-internal-funcnames.c @@ -0,0 +1,4 @@ +// RUN: %clang -### -funique-internal-funcnames %s -c 2>&1 | FileCheck -check-prefix=CHECK-OPT %s +// RUN: %clang -### -funique-internal-funcnames -fno-unique-internal-funcnames %s -c 2>&1 | FileCheck -check-prefix=CHECK-NOOPT %s +// CHECK-OPT: "-funique-internal-funcnames" +// CHECK-NOOPT-NOT: {{-funique-internal-funcnames}}