Hi Rafael,<div><br></div><div>I have a reduced repro for the regression caused by this CL (as mentioned in IRC). I attached it to <a href="http://llvm.org/PR12835">http://llvm.org/PR12835</a></div><div><br></div><div>Nico<br>
<br><div class="gmail_quote">On Tue, May 15, 2012 at 7:09 AM, Rafael Espindola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: rafael<br>
Date: Tue May 15 09:09:55 2012<br>
New Revision: 156821<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=156821&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=156821&view=rev</a><br>
Log:<br>
Fix our handling of visibility in explicit template instantiations.<br>
<br>
* Don't copy the visibility attribute during instantiations. We have to be able<br>
  to distinguish<br>
<br>
 struct HIDDEN foo {};<br>
 template<class T><br>
 DEFAULT void bar() {}<br>
 template DEFAULT void bar<foo>();<br>
<br>
from<br>
<br>
 struct HIDDEN foo {};<br>
 template<class T><br>
 DEFAULT void bar() {}<br>
 template void bar<foo>();<br>
<br>
* If an instantiation has an attribute, it takes precedence over an attribute<br>
  in the template.<br>
<br>
* With instantiation attributes handled with the above logic, we can now<br>
  select the minimum visibility when looking at template arguments.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/Attr.td<br>
    cfe/trunk/lib/AST/Decl.cpp<br>
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
    cfe/trunk/test/CodeGenCXX/visibility.cpp<br>
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/Attr.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=156821&r1=156820&r2=156821&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=156821&r1=156820&r2=156821&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/Attr.td (original)<br>
+++ cfe/trunk/include/clang/Basic/Attr.td Tue May 15 09:09:55 2012<br>
@@ -93,6 +93,9 @@<br>
   list<string> Namespaces = [];<br>
   // Set to true for attributes with arguments which require delayed parsing.<br>
   bit LateParsed = 0;<br>
+  // Set to false to prevent an attribute from being propagated from a template<br>
+  // to the instantiation.<br>
+  bit Clone = 1;<br>
   // Set to true for attributes which must be instantiated within templates<br>
   bit TemplateDependent = 0;<br>
   // Set to true for attributes that have a corresponding AST node.<br>
@@ -660,6 +663,7 @@<br>
 }<br>
<br>
 def Visibility : InheritableAttr {<br>
+  let Clone = 0;<br>
   let Spellings = ["visibility"];<br>
   let Args = [EnumArgument<"Visibility", "VisibilityType",<br>
                            ["default", "hidden", "internal", "protected"],<br>
<br>
Modified: cfe/trunk/lib/AST/Decl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=156821&r1=156820&r2=156821&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=156821&r1=156820&r2=156821&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/Decl.cpp (original)<br>
+++ cfe/trunk/lib/AST/Decl.cpp Tue May 15 09:09:55 2012<br>
@@ -158,14 +158,12 @@<br>
   return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), OnlyTemplate);<br>
 }<br>
<br>
-static bool shouldConsiderTemplateLV(const FunctionDecl *fn,<br>
-                               const FunctionTemplateSpecializationInfo *spec) {<br>
-  return !(spec->isExplicitSpecialization() &&<br>
-           fn->hasAttr<VisibilityAttr>());<br>
+static bool shouldConsiderTemplateLV(const FunctionDecl *fn) {<br>
+  return !fn->hasAttr<VisibilityAttr>();<br>
 }<br>
<br>
 static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) {<br>
-  return !(d->isExplicitSpecialization() && d->hasAttr<VisibilityAttr>());<br>
+  return !d->hasAttr<VisibilityAttr>();<br>
 }<br>
<br>
 static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,<br>
@@ -376,7 +374,7 @@<br>
     // this is an explicit specialization with a visibility attribute.<br>
     if (FunctionTemplateSpecializationInfo *specInfo<br>
                                = Function->getTemplateSpecializationInfo()) {<br>
-      if (shouldConsiderTemplateLV(Function, specInfo)) {<br>
+      if (shouldConsiderTemplateLV(Function)) {<br>
         LV.merge(getLVForDecl(specInfo->getTemplate(),<br>
                               true));<br>
         const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;<br>
@@ -407,8 +405,8 @@<br>
<br>
         // The arguments at which the template was instantiated.<br>
         const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();<br>
-        LV.merge(getLVForTemplateArgumentList(TemplateArgs,<br>
-                                              OnlyTemplate));<br>
+        LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs,<br>
+                                                     OnlyTemplate));<br>
       }<br>
     }<br>
<br>
@@ -527,7 +525,7 @@<br>
     // the template parameters and arguments.<br>
     if (FunctionTemplateSpecializationInfo *spec<br>
            = MD->getTemplateSpecializationInfo()) {<br>
-      if (shouldConsiderTemplateLV(MD, spec)) {<br>
+      if (shouldConsiderTemplateLV(MD)) {<br>
         LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments,<br>
                                                      OnlyTemplate));<br>
         if (!OnlyTemplate)<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=156821&r1=156820&r2=156821&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=156821&r1=156820&r2=156821&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue May 15 09:09:55 2012<br>
@@ -102,7 +102,8 @@<br>
     } else {<br>
       Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,<br>
                                                          *this, TemplateArgs);<br>
-      New->addAttr(NewAttr);<br>
+      if (NewAttr)<br>
+        New->addAttr(NewAttr);<br>
     }<br>
   }<br>
 }<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/visibility.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=156821&r1=156820&r2=156821&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=156821&r1=156820&r2=156821&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/visibility.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/visibility.cpp Tue May 15 09:09:55 2012<br>
@@ -712,3 +712,55 @@<br>
   // CHECK: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv<br>
   // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv<br>
 }<br>
+<br>
+namespace test37 {<br>
+  struct HIDDEN foo {<br>
+  };<br>
+  template<class T><br>
+  DEFAULT void bar() {}<br>
+  template DEFAULT void bar<foo>();<br>
+  // CHECK: define weak_odr void @_ZN6test373barINS_3fooEEEvv<br>
+  // CHECK-HIDDEN: define weak_odr void @_ZN6test373barINS_3fooEEEvv<br>
+}<br>
+<br>
+namespace test38 {<br>
+  template<typename T><br>
+  class DEFAULT foo {<br>
+    void bar() {}<br>
+  };<br>
+  struct HIDDEN zed {<br>
+  };<br>
+  template class foo<zed>;<br>
+  // CHECK: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv<br>
+  // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv<br>
+}<br>
+<br>
+namespace test39 {<br>
+  class DEFAULT default_t;<br>
+  class HIDDEN hidden_t;<br>
+  template <class T> class A {<br>
+    template <class U> class B {<br>
+      HIDDEN void hidden() {}<br>
+      void noattr() {}<br>
+      template <class V> void temp() {}<br>
+    };<br>
+  };<br>
+  template class DEFAULT A<hidden_t>;<br>
+  template class DEFAULT A<hidden_t>::B<hidden_t>;<br>
+  template void A<hidden_t>::B<hidden_t>::temp<default_t>();<br>
+  template void A<hidden_t>::B<hidden_t>::temp<hidden_t>();<br>
+<br>
+  // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv<br>
+  // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv<br>
+  // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv<br>
+<br>
+  // GCC produces a default for this one. Why?<br>
+  // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv<br>
+<br>
+  // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv<br>
+  // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv<br>
+  // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv<br>
+<br>
+  // GCC produces a default for this one. Why?<br>
+  // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv<br>
+}<br>
<br>
Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=156821&r1=156820&r2=156821&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=156821&r1=156820&r2=156821&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)<br>
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Tue May 15 09:09:55 2012<br>
@@ -1004,6 +1004,14 @@<br>
       continue;<br>
<br>
     OS << "    case attr::" << R.getName() << ": {\n";<br>
+    bool ShouldClone = R.getValueAsBit("Clone");<br>
+<br>
+    if (!ShouldClone) {<br>
+      OS << "      return NULL;\n";<br>
+      OS << "    }\n";<br>
+      continue;<br>
+    }<br>
+<br>
     OS << "      const " << R.getName() << "Attr *A = cast<"<br>
        << R.getName() << "Attr>(At);\n";<br>
     bool TDependent = R.getValueAsBit("TemplateDependent");<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>