Nico noticed that the patch included an infinite loop from when I
renamed merge2 to mergeWithMin.
An updated patch is attached.
Cheers,
Rafael
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 760e598..83e9c5b 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -251,6 +251,7 @@ public:
mergeLinkage(Other.linkage());
}
+ // Merge the visibility V giving preference to explicit ones.
void mergeVisibility(Visibility V, bool E = false) {
// If one has explicit visibility and the other doesn't, keep the
// explicit one.
@@ -262,14 +263,32 @@ public:
// If both are explicit or both are implicit, keep the minimum.
setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E);
}
+ // Merge the visibility V, keeping the most restrictive one.
+ void mergeVisibilityWithMin(Visibility V, bool E = false) {
+ // Never increase the visibility
+ if (visibility() < V)
+ return;
+
+ // If this visibility is explicit, keep it.
+ if (visibilityExplicit() && !E)
+ return;
+ setVisibility(V, E);
+ }
void mergeVisibility(LinkageInfo Other) {
mergeVisibility(Other.visibility(), Other.visibilityExplicit());
}
+ void mergeVisibilityWithMin(LinkageInfo Other) {
+ mergeVisibilityWithMin(Other.visibility(), Other.visibilityExplicit());
+ }
void merge(LinkageInfo Other) {
mergeLinkage(Other);
mergeVisibility(Other);
}
+ void mergeWithMin(LinkageInfo Other) {
+ mergeLinkage(Other);
+ mergeVisibilityWithMin(Other);
+ }
friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) {
L.merge(R);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d80e06b..ee00c3c 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -176,9 +176,9 @@ static LinkageInfo getLVForTemplateArgumentList(const
TemplateArgument *Args,
break;
case TemplateArgument::Pack:
- LV.merge(getLVForTemplateArgumentList(Args[I].pack_begin(),
- Args[I].pack_size(),
- F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(Args[I].pack_begin(),
+ Args[I].pack_size(),
+ F));
break;
}
}
@@ -279,6 +279,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const
NamedDecl *D, LVFlags F) {
// scope and no storage-class specifier, its linkage is
// external.
LinkageInfo LV;
+ LV.mergeVisibility(Context.getLangOptions().getVisibilityMode());
if (F.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) {
@@ -413,7 +414,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const
NamedDecl *D, LVFlags F) {
LV.merge(getLVForDecl(specInfo->getTemplate(),
F.onlyTemplateVisibility()));
const TemplateArgumentList &templateArgs =
*specInfo->TemplateArguments;
- LV.merge(getLVForTemplateArgumentList(templateArgs, F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(templateArgs, F));
}
}
@@ -439,7 +440,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const
NamedDecl *D, LVFlags F) {
// The arguments at which the template was instantiated.
const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
- LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs, F));
}
}
@@ -482,11 +483,6 @@ static LinkageInfo getLVForNamespaceScopeDecl(const
NamedDecl *D, LVFlags F) {
if (LV.linkage() != ExternalLinkage)
return LinkageInfo(LV.linkage(), DefaultVisibility, false);
- // If we didn't end up with hidden visibility, consider attributes
- // and -fvisibility.
- if (F.ConsiderGlobalVisibility)
- LV.mergeVisibility(Context.getLangOptions().getVisibilityMode());
-
return LV;
}
@@ -503,6 +499,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
LVFlags F) {
return LinkageInfo::none();
LinkageInfo LV;
+ LV.mergeVisibility(D->getASTContext().getLangOptions().getVisibilityMode());
// The flags we're going to use to compute the class's visibility.
LVFlags ClassF = F;
@@ -544,7 +541,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
LVFlags F) {
if (FunctionTemplateSpecializationInfo *spec
= MD->getTemplateSpecializationInfo()) {
if (shouldConsiderTemplateLV(MD, spec)) {
- LV.merge(getLVForTemplateArgumentList(*spec->TemplateArguments, F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments,
+ F));
if (F.ConsiderTemplateParameterTypes)
LV.merge(getLVForTemplateParameterList(
spec->getTemplate()->getTemplateParameters()));
@@ -583,7 +581,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
LVFlags F) {
if (shouldConsiderTemplateLV(spec)) {
// Merge template argument/parameter information for member
// class template specializations.
- LV.merge(getLVForTemplateArgumentList(spec->getTemplateArgs(), F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(spec->getTemplateArgs(),
+ F));
if (F.ConsiderTemplateParameterTypes)
LV.merge(getLVForTemplateParameterList(
spec->getSpecializedTemplate()->getTemplateParameters()));
@@ -601,13 +600,6 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
LVFlags F) {
LV.mergeVisibility(TypeLV.visibility(), TypeLV.visibilityExplicit());
}
- F.ConsiderGlobalVisibility &= !LV.visibilityExplicit();
-
- // Apply -fvisibility if desired.
- if (F.ConsiderGlobalVisibility && LV.visibility() != HiddenVisibility) {
-
LV.mergeVisibility(D->getASTContext().getLangOptions().getVisibilityMode());
- }
-
return LV;
}
diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp
index 67ac098..8bf34eb 100644
--- a/test/CodeGenCXX/visibility.cpp
+++ b/test/CodeGenCXX/visibility.cpp
@@ -5,6 +5,21 @@
#define PROTECTED __attribute__((visibility("protected")))
#define DEFAULT __attribute__((visibility("default")))
+namespace test25 {
+ template<typename T>
+ struct X {
+ template<typename U>
+ struct definition {
+ };
+ };
+
+ class DEFAULT A { };
+
+ X<int>::definition<A> a;
+ // CHECK: @_ZN6test251aE = global
+ // CHECK-HIDDEN: @_ZN6test251aE = hidden global
+}
+
// CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10
// CHECK: @_ZN5Test71aE = hidden global
// CHECK: @_ZN5Test71bE = global
@@ -500,3 +515,52 @@ namespace PR11690_2 {
// CHECK: define weak_odr void
@_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
// CHECK-HIDDEN: define weak_odr void
@_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
}
+
+namespace test23 {
+ // Having a template argument that is explicitly visible should not make
+ // the template instantiation visible.
+ template <typename T>
+ struct X {
+ static void f() {
+ }
+ };
+
+ class DEFAULT A;
+
+ void g() {
+ X<A> y;
+ y.f();
+ }
+ // CHECK: define linkonce_odr void @_ZN6test231XINS_1AEE1fEv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test231XINS_1AEE1fEv
+}
+
+namespace PR12001 {
+ template <typename P1>
+ void Bind(const P1& p1) {
+ }
+
+ class DEFAULT Version { };
+
+ void f() {
+ Bind(Version());
+ }
+ // CHECK: define linkonce_odr void @_ZN7PR120014BindINS_7VersionEEEvRKT_
+ // CHECK-HIDDEN: define linkonce_odr hidden void
@_ZN7PR120014BindINS_7VersionEEEvRKT_
+}
+
+namespace test24 {
+ class DEFAULT A { };
+
+ struct S {
+ template <typename T>
+ void mem() {}
+ };
+
+ void test() {
+ S s;
+ s.mem<A>();
+ }
+ // CHECK: define linkonce_odr void @_ZN6test241S3memINS_1AEEEvv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test241S3memINS_1AEEEvv
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits