diff options
-rw-r--r-- | include/clang/Basic/Attr.td | 4 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 | ||||
-rw-r--r-- | test/CodeGenCXX/visibility.cpp | 52 | ||||
-rw-r--r-- | utils/TableGen/ClangAttrEmitter.cpp | 8 |
5 files changed, 73 insertions, 10 deletions
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 0b3b3cb33f..7d05b72a74 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -93,6 +93,9 @@ class Attr { list<string> Namespaces = []; // Set to true for attributes with arguments which require delayed parsing. bit LateParsed = 0; + // Set to false to prevent an attribute from being propagated from a template + // to the instantiation. + bit Clone = 1; // Set to true for attributes which must be instantiated within templates bit TemplateDependent = 0; // Set to true for attributes that have a corresponding AST node. @@ -660,6 +663,7 @@ def VecTypeHint : Attr { } def Visibility : InheritableAttr { + let Clone = 0; let Spellings = ["visibility"]; let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 15fa790203..21405d223d 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -158,14 +158,12 @@ getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), OnlyTemplate); } -static bool shouldConsiderTemplateLV(const FunctionDecl *fn, - const FunctionTemplateSpecializationInfo *spec) { - return !(spec->isExplicitSpecialization() && - fn->hasAttr<VisibilityAttr>()); +static bool shouldConsiderTemplateLV(const FunctionDecl *fn) { + return !fn->hasAttr<VisibilityAttr>(); } static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) { - return !(d->isExplicitSpecialization() && d->hasAttr<VisibilityAttr>()); + return !d->hasAttr<VisibilityAttr>(); } static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, @@ -376,7 +374,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // this is an explicit specialization with a visibility attribute. if (FunctionTemplateSpecializationInfo *specInfo = Function->getTemplateSpecializationInfo()) { - if (shouldConsiderTemplateLV(Function, specInfo)) { + if (shouldConsiderTemplateLV(Function)) { LV.merge(getLVForDecl(specInfo->getTemplate(), true)); const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; @@ -407,8 +405,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // The arguments at which the template was instantiated. const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); - LV.merge(getLVForTemplateArgumentList(TemplateArgs, - OnlyTemplate)); + LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs, + OnlyTemplate)); } } @@ -527,7 +525,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) { // the template parameters and arguments. if (FunctionTemplateSpecializationInfo *spec = MD->getTemplateSpecializationInfo()) { - if (shouldConsiderTemplateLV(MD, spec)) { + if (shouldConsiderTemplateLV(MD)) { LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments, OnlyTemplate)); if (!OnlyTemplate) diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 51dffac59c..0182b3dcc4 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -102,7 +102,8 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, } else { Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); - New->addAttr(NewAttr); + if (NewAttr) + New->addAttr(NewAttr); } } } diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp index 2aa067886a..9de9265db2 100644 --- a/test/CodeGenCXX/visibility.cpp +++ b/test/CodeGenCXX/visibility.cpp @@ -712,3 +712,55 @@ namespace test36 { // CHECK: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv } + +namespace test37 { + struct HIDDEN foo { + }; + template<class T> + DEFAULT void bar() {} + template DEFAULT void bar<foo>(); + // CHECK: define weak_odr void @_ZN6test373barINS_3fooEEEvv + // CHECK-HIDDEN: define weak_odr void @_ZN6test373barINS_3fooEEEvv +} + +namespace test38 { + template<typename T> + class DEFAULT foo { + void bar() {} + }; + struct HIDDEN zed { + }; + template class foo<zed>; + // CHECK: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv + // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv +} + +namespace test39 { + class DEFAULT default_t; + class HIDDEN hidden_t; + template <class T> class A { + template <class U> class B { + HIDDEN void hidden() {} + void noattr() {} + template <class V> void temp() {} + }; + }; + template class DEFAULT A<hidden_t>; + template class DEFAULT A<hidden_t>::B<hidden_t>; + template void A<hidden_t>::B<hidden_t>::temp<default_t>(); + template void A<hidden_t>::B<hidden_t>::temp<hidden_t>(); + + // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv + // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv + // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv + + // GCC produces a default for this one. Why? + // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv + + // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv + // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv + // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv + + // GCC produces a default for this one. Why? + // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv +} diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 772fc2f526..8a8987720e 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -1004,6 +1004,14 @@ void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) { continue; OS << " case attr::" << R.getName() << ": {\n"; + bool ShouldClone = R.getValueAsBit("Clone"); + + if (!ShouldClone) { + OS << " return NULL;\n"; + OS << " }\n"; + continue; + } + OS << " const " << R.getName() << "Attr *A = cast<" << R.getName() << "Attr>(At);\n"; bool TDependent = R.getValueAsBit("TemplateDependent"); |