diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/Visibility.h | 14 | ||||
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 9 | ||||
| -rw-r--r-- | clang/test/SemaCXX/linkage2.cpp | 15 |
3 files changed, 35 insertions, 3 deletions
diff --git a/clang/include/clang/Basic/Visibility.h b/clang/include/clang/Basic/Visibility.h index 604f05b0341..6ac52ed6b5e 100644 --- a/clang/include/clang/Basic/Visibility.h +++ b/clang/include/clang/Basic/Visibility.h @@ -89,6 +89,20 @@ public: mergeLinkage(other.getLinkage()); } + void mergeExternalVisibility(Linkage L) { + Linkage ThisL = getLinkage(); + if (!isExternallyVisible(L)) { + if (ThisL == VisibleNoLinkage) + ThisL = NoLinkage; + else if (ThisL == ExternalLinkage) + ThisL = UniqueExternalLinkage; + } + setLinkage(ThisL); + } + void mergeExternalVisibility(LinkageInfo Other) { + mergeExternalVisibility(Other.getLinkage()); + } + /// Merge in the visibility 'newVis'. void mergeVisibility(Visibility newVis, bool newExplicit) { Visibility oldVis = getVisibility(); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 41b6da3e580..7ae7e8209d0 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -471,7 +471,9 @@ static void mergeTemplateLV(LinkageInfo &LV, // instantiation with a visibility attribute. const TemplateArgumentList &templateArgs = spec->getTemplateArgs(); LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); - LV.mergeMaybeWithVisibility(argsLV, considerVisibility); + if (considerVisibility) + LV.mergeVisibility(argsLV); + LV.mergeExternalVisibility(argsLV); } static bool useInlineVisibilityHidden(const NamedDecl *D) { @@ -863,8 +865,9 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. LinkageInfo typeLV = getLVForType(*VD->getType(), computation); - LV.mergeMaybeWithVisibility(typeLV, - !LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()); + if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()) + LV.mergeVisibility(typeLV); + LV.mergeExternalVisibility(typeLV); if (isExplicitMemberSpecialization(VD)) { explicitSpecSuppressor = VD; diff --git a/clang/test/SemaCXX/linkage2.cpp b/clang/test/SemaCXX/linkage2.cpp index ed6e9677d5a..a811575c612 100644 --- a/clang/test/SemaCXX/linkage2.cpp +++ b/clang/test/SemaCXX/linkage2.cpp @@ -186,3 +186,18 @@ namespace test17 { g(); } } + +namespace test18 { + template <typename T> struct foo { + template <T *P> static void f() {} + static void *g() { return (void *)f<&x>; } + static T x; + }; + template <typename T> T foo<T>::x; + inline void *f() { + struct S { + }; + return foo<S>::g(); + } + void *h() { return f(); } +} |

