From 4188760f6bb20f91c6883dffd89204419f852dee Mon Sep 17 00:00:00 2001 From: John McCall Date: Sun, 29 Jan 2012 01:20:30 +0000 Subject: [PATCH] Complain about attempts to use 'protected' visibility on targets like Darwin that don't support it. We should also complain about invalid -fvisibility=protected, but that information doesn't seem to exist at the most appropriate time, so I've left a FIXME behind. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149186 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 3 +++ include/clang/Basic/TargetInfo.h | 13 +++++++++++++ lib/Basic/Targets.cpp | 6 ++++++ lib/Frontend/CompilerInvocation.cpp | 1 + lib/Sema/SemaDeclAttr.cpp | 13 ++++++++++--- test/CodeGenCXX/thunks.cpp | 4 ++-- test/Sema/attr-visibility.c | 9 +++++++++ 7 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 test/Sema/attr-visibility.c diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 948236edc6..7888ce555c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1740,6 +1740,9 @@ def warn_transparent_union_attribute_zero_fields : Warning< def warn_attribute_type_not_supported : Warning< "'%0' attribute argument not supported: %1">; def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">; +def warn_attribute_protected_visibility : + Warning<"target does not support 'protected' visibility; using 'default'">, + InGroup>; def err_unknown_machine_mode : Error<"unknown machine mode %0">; def err_unsupported_machine_mode : Error<"unsupported machine mode %0">; def err_mode_not_primitive : Error< diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index b1e1cbdf66..966797c4ff 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -479,6 +479,19 @@ public: const unsigned RegNum; }; + /// hasProtectedVisibility - Does this target support "protected" + /// visibility? + /// + /// Any target which dynamic libraries will naturally support + /// something like "default" (meaning that the symbol is visible + /// outside this shared object) and "hidden" (meaning that it isn't) + /// visibilities, but "protected" is really an ELF-specific concept + /// with wierd semantics designed around the convenience of dynamic + /// linker implementations. Which is not to suggest that there's + /// consistent target-independent semantics for "default" visibility + /// either; the entire thing is pretty badly mangled. + virtual bool hasProtectedVisibility() const { return true; } + virtual bool useGlobalsForAutomaticVariables() const { return false; } /// getCFStringSection - Return the section to use for CFString diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 5cdb36f16b..5dc63e79cf 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -218,6 +218,12 @@ public: return "__TEXT,__StaticInit,regular,pure_instructions"; } + /// Darwin does not support protected visibility. Darwin's "default" + /// is very similar to ELF's "protected"; Darwin requires a "weak" + /// attribute on declarations that can be dynamically replaced. + virtual bool hasProtectedVisibility() const { + return false; + } }; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index a189155e12..e9bb30325c 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1792,6 +1792,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, else if (Vis == "hidden") Opts.setVisibilityMode(HiddenVisibility); else if (Vis == "protected") + // FIXME: diagnose if target does not support protected visibility Opts.setVisibilityMode(ProtectedVisibility); else Diags.Report(diag::err_drv_invalid_value) diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index aa827a40c6..d4b9988d88 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1694,9 +1694,16 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { type = VisibilityAttr::Hidden; else if (TypeStr == "internal") type = VisibilityAttr::Hidden; // FIXME - else if (TypeStr == "protected") - type = VisibilityAttr::Protected; - else { + else if (TypeStr == "protected") { + // Complain about attempts to use protected visibility on targets + // (like Darwin) that don't support it. + if (!S.Context.getTargetInfo().hasProtectedVisibility()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility); + type = VisibilityAttr::Default; + } else { + type = VisibilityAttr::Protected; + } + } else { S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; return; } diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index 7c80b96b79..04d0820da7 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/test/CodeGenCXX/thunks.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=HIDDEN %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=HIDDEN %s namespace Test1 { diff --git a/test/Sema/attr-visibility.c b/test/Sema/attr-visibility.c new file mode 100644 index 0000000000..5cf269582a --- /dev/null +++ b/test/Sema/attr-visibility.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s + +void test0() __attribute__((visibility("default"))); +void test1() __attribute__((visibility("hidden"))); +void test2() __attribute__((visibility("internal"))); + +// rdar://problem/10753392 +void test3() __attribute__((visibility("protected"))); // expected-warning {{target does not support 'protected' visibility; using 'default'}} +