Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -261,6 +261,9 @@ BENIGN_LANGOPT(DumpVTableLayouts , 1, 0, "dumping the layouts of emitted vtables") LANGOPT(NoConstantCFStrings , 1, 0, "no constant CoreFoundation strings") BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden visibility for inline C++ methods") +BENIGN_LANGOPT(VisibilityInlinesHiddenStaticLocalVar, 1, 0, + "hidden visibility for static local variables in inline C++ " + "methods when -fvisibility-inlines hidden is enabled") LANGOPT(GlobalAllocationFunctionVisibilityHidden , 1, 0, "hidden visibility for global operator new and delete declaration") BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype") BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1943,6 +1943,17 @@ def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group, HelpText<"Give inline C++ member functions hidden visibility by default">, Flags<[CC1Option]>; +def fvisibility_inlines_hidden_static_local_var : + Flag<["-"], "fvisibility-inlines-hidden-static-local-var">, Group, + HelpText<"When -fvisibility-inlines-hidden is enabled, static variables in " + "inline C++ member functions will also be given hidden visibility " + "by default">, + Flags<[CC1Option]>; +def fno_visibility_inlines_hidden_static_local_var : + Flag<["-"], "fno-visibility-inlines-hidden-static-local-var">, Group, + HelpText<"Disables -fvisibility-inlines-hidden-static-local-var " + "(this is the default on non-darwin targets)">, + Flags<[CC1Option]>; def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group, HelpText<"Give global types 'default' visibility and global functions and " "variables 'hidden' visibility by default">; Index: clang/lib/AST/Decl.cpp =================================================================== --- clang/lib/AST/Decl.cpp +++ clang/lib/AST/Decl.cpp @@ -1299,7 +1299,8 @@ // we should not make static local variables in the function hidden. LV = getLVForDecl(FD, computation); if (isa(D) && useInlineVisibilityHidden(FD) && - !LV.isVisibilityExplicit()) { + !LV.isVisibilityExplicit() && + !Context.getLangOpts().VisibilityInlinesHiddenStaticLocalVar) { assert(cast(D)->isStaticLocal()); // If this was an implicitly hidden inline method, check again for // explicit visibility on the parent class, and use that for static locals Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5209,6 +5209,8 @@ } Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); + Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden_static_local_var, + options::OPT_fno_visibility_inlines_hidden_static_local_var); Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden); Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ); Index: clang/lib/Driver/ToolChains/Darwin.cpp =================================================================== --- clang/lib/Driver/ToolChains/Darwin.cpp +++ clang/lib/Driver/ToolChains/Darwin.cpp @@ -2408,6 +2408,13 @@ // Enable compatibility mode for NSItemProviderCompletionHandler in // Foundation/NSItemProvider.h. CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking"); + + // Give static local variables in inline functions hidden visibility when + // -fvisibility-inlines-hidden is enabled. + if (!DriverArgs.getLastArgNoClaim( + options::OPT_fvisibility_inlines_hidden_static_local_var, + options::OPT_fno_visibility_inlines_hidden_static_local_var)) + CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var"); } DerivedArgList * Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -2766,6 +2766,9 @@ if (Args.hasArg(OPT_fvisibility_inlines_hidden)) Opts.InlineVisibilityHidden = 1; + if (Args.hasArg(OPT_fvisibility_inlines_hidden_static_local_var)) + Opts.VisibilityInlinesHiddenStaticLocalVar = 1; + if (Args.hasArg(OPT_fvisibility_global_new_delete_hidden)) Opts.GlobalAllocationFunctionVisibilityHidden = 1; Index: clang/test/CodeGenCXX/visibility-inlines-hidden-static-local-var.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/visibility-inlines-hidden-static-local-var.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fvisibility-inlines-hidden -fvisibility-inlines-hidden-static-local-var %s -emit-llvm -o - | FileCheck %s + +#define used __attribute__((used)) + +used inline void f1() { + // CHECK: @_ZZ2f1vE6f1_var = linkonce_odr hidden global i32 0 + static int f1_var = 0; +} + +__attribute__((visibility("default"))) +used inline void f2() { + // CHECK: @_ZZ2f2vE6f2_var = linkonce_odr global i32 0 + static int f2_var = 0; +} + +struct S { + used void f3() { + // CHECK: @_ZZN1S2f3EvE6f3_var = linkonce_odr hidden global i32 0 + static int f3_var = 0; + } + + void f6(); + void f7(); +}; + +used void f4() { + // CHECK: @_ZZ2f4vE6f4_var = internal global i32 0 + static int f4_var = 0; +} + +__attribute__((visibility("default"))) +used void f5() { + // CHECK: @_ZZ2f5vE6f5_var = internal global i32 0 + static int f5_var = 0; +} + +used void S::f6() { + // CHECK: @_ZZN1S2f6EvE6f6_var = internal global i32 0 + static int f6_var = 0; +} + +used inline void S::f7() { + // CHECK: @_ZZN1S2f7EvE6f7_var = linkonce_odr hidden global i32 0 + static int f7_var = 0; +} + + +struct __attribute__((visibility("default"))) S2 { + used void f8() { + // CHECK: @_ZZN2S22f8EvE6f8_var = linkonce_odr hidden global i32 0 + static int f8_var = 0; + } +}; Index: clang/test/Driver/darwin-objc-options.m =================================================================== --- clang/test/Driver/darwin-objc-options.m +++ clang/test/Driver/darwin-objc-options.m @@ -46,3 +46,12 @@ // RUN: %clang -target x86_64-linux-gnu -### %s 2>&1 | FileCheck --check-prefix=OTHER_COMPATIBILITY %s // DARWIN_COMPATIBILITY: -fcompatibility-qualified-id-block-type-checking // OTHER_COMPATIBILITY-NOT: -fcompatibility-qualified-id-block-type-checking + +// Add -fvisibility-inlines-hidden-static-local-var on Darwin. +// RUN: %clang -target x86_64-apple-darwin10 -### %s 2>&1 | FileCheck --check-prefix=DARWIN_INLINES_HIDDEN %s +// RUN: %clang -target x86_64-apple-darwin10 -fno-visibility-inlines-hidden-static-local-var -### %s 2>&1 | FileCheck --check-prefix=DARWIN_INLINES_HIDDEN_EXPLICIT_NO %s +// RUN: %clang -target x86_64-linux-gnu -### %s 2>&1 | FileCheck --check-prefix=NO_DARWIN_INLINES_HIDDEN %s +// DARWIN_INLINES_HIDDEN: -fvisibility-inlines-hidden-static-local-var +// DARWIN_INLINES_HIDDEN_EXPLICIT_NO-NOT: -fvisibility-inlines-hidden-static-local-var +// DARWIN_INLINES_HIDDEN_EXPLICIT_NO: -fno-visibility-inlines-hidden-static-local-var +// NO_DARWIN_INLINES_HIDDEN-NOT: -fvisibility-inlines-hidden-static-local-var