]> granicus.if.org Git - clang/commitdiff
Fix PR16060.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 30 May 2013 21:23:15 +0000 (21:23 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 30 May 2013 21:23:15 +0000 (21:23 +0000)
The testcase in PR16060 points out that while template arguments can
show that a type is not externally visible, the standards still says
they have external linkage.

In terms of our implementation, it means that we should merge just the
isExternallyVisible bit, not the formal linkage.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182962 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Visibility.h
lib/AST/Decl.cpp
test/SemaCXX/linkage2.cpp

index 604f05b03414427908808720c00dd64c993fbe50..6ac52ed6b5e1d8fc106ba4d689dbd6d4af69a851 100644 (file)
@@ -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();
index 41b6da3e58021906170776ed6dea78ab79efb158..7ae7e8209d0204425531203a9bfb124ceb5dbb3f 100644 (file)
@@ -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;
index ed6e9677d5a4e081b4af3c8bc08da5c4a8d6a580..a811575c612e7788724ffb2228e7edeb78fcbdb4 100644 (file)
@@ -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(); }
+}