A couple of tweaks to the visibility rules:
- tags with C linkage should ignore visibility=hidden
- functions and variables with explicit visibility attributes should
ignore the linkage of their types
Either of these should be sufficient to fix PR8457.
Also, FileCheck-ize a test case.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117351 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 42e762d..5cc745d 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -212,9 +212,13 @@
// given variable or function shall be identical...
// C does not have an equivalent rule.
//
+ // Ignore this if we've got an explicit attribute; the user
+ // probably knows what they're doing.
+ //
// Note that we don't want to make the variable non-external
// because of this, but unique-external linkage suits us.
- if (Context.getLangOptions().CPlusPlus && !Var->isExternC()) {
+ if (Context.getLangOptions().CPlusPlus && !Var->isExternC() &&
+ !Var->hasAttr<VisibilityAttr>()) {
LVPair TypeLV = Var->getType()->getLinkageAndVisibility();
if (TypeLV.first != ExternalLinkage)
return LVPair(UniqueExternalLinkage, DefaultVisibility);
@@ -247,7 +251,8 @@
} else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// Modify the function's LV by the LV of its type unless this is
// C or extern "C". See the comment above about variables.
- if (Context.getLangOptions().CPlusPlus && !Function->isExternC()) {
+ if (Context.getLangOptions().CPlusPlus && !Function->isExternC() &&
+ !Function->hasAttr<VisibilityAttr>()) {
LVPair TypeLV = Function->getType()->getLinkageAndVisibility();
if (TypeLV.first != ExternalLinkage)
return LVPair(UniqueExternalLinkage, DefaultVisibility);
@@ -321,8 +326,11 @@
ConsiderDashFVisibility = false;
}
+ // Consider -fvisibility unless the type has C linkage.
if (ConsiderDashFVisibility)
- ConsiderDashFVisibility = Tag->isDefinition();
+ ConsiderDashFVisibility =
+ (Context.getLangOptions().CPlusPlus &&
+ !Tag->getDeclContext()->isExternCContext());
// - an enumerator belonging to an enumeration with external linkage;
} else if (isa<EnumConstantDecl>(D)) {
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 483352f..5606d54 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -529,6 +529,17 @@
return false;
}
+bool DeclContext::isExternCContext() const {
+ const DeclContext *DC = this;
+ while (DC->DeclKind != Decl::TranslationUnit) {
+ if (DC->DeclKind == Decl::LinkageSpec)
+ return cast<LinkageSpecDecl>(DC)->getLanguage()
+ == LinkageSpecDecl::lang_c;
+ DC = DC->getParent();
+ }
+ return false;
+}
+
bool DeclContext::Encloses(const DeclContext *DC) const {
if (getPrimaryContext() != this)
return getPrimaryContext()->Encloses(DC);