forked from OSchip/llvm-project
Fix our handling of visibility in explicit template instantiations.
* Don't copy the visibility attribute during instantiations. We have to be able to distinguish struct HIDDEN foo {}; template<class T> DEFAULT void bar() {} template DEFAULT void bar<foo>(); from struct HIDDEN foo {}; template<class T> DEFAULT void bar() {} template void bar<foo>(); * If an instantiation has an attribute, it takes precedence over an attribute in the template. * With instantiation attributes handled with the above logic, we can now select the minimum visibility when looking at template arguments. llvm-svn: 156821
This commit is contained in:
parent
ab5edc3e89
commit
7f90b7d4c2
|
@ -93,6 +93,9 @@ class Attr {
|
||||||
list<string> Namespaces = [];
|
list<string> Namespaces = [];
|
||||||
// Set to true for attributes with arguments which require delayed parsing.
|
// Set to true for attributes with arguments which require delayed parsing.
|
||||||
bit LateParsed = 0;
|
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
|
// Set to true for attributes which must be instantiated within templates
|
||||||
bit TemplateDependent = 0;
|
bit TemplateDependent = 0;
|
||||||
// Set to true for attributes that have a corresponding AST node.
|
// Set to true for attributes that have a corresponding AST node.
|
||||||
|
@ -660,6 +663,7 @@ def VecTypeHint : Attr {
|
||||||
}
|
}
|
||||||
|
|
||||||
def Visibility : InheritableAttr {
|
def Visibility : InheritableAttr {
|
||||||
|
let Clone = 0;
|
||||||
let Spellings = ["visibility"];
|
let Spellings = ["visibility"];
|
||||||
let Args = [EnumArgument<"Visibility", "VisibilityType",
|
let Args = [EnumArgument<"Visibility", "VisibilityType",
|
||||||
["default", "hidden", "internal", "protected"],
|
["default", "hidden", "internal", "protected"],
|
||||||
|
|
|
@ -158,14 +158,12 @@ getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
|
||||||
return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), OnlyTemplate);
|
return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), OnlyTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool shouldConsiderTemplateLV(const FunctionDecl *fn,
|
static bool shouldConsiderTemplateLV(const FunctionDecl *fn) {
|
||||||
const FunctionTemplateSpecializationInfo *spec) {
|
return !fn->hasAttr<VisibilityAttr>();
|
||||||
return !(spec->isExplicitSpecialization() &&
|
|
||||||
fn->hasAttr<VisibilityAttr>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) {
|
static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) {
|
||||||
return !(d->isExplicitSpecialization() && d->hasAttr<VisibilityAttr>());
|
return !d->hasAttr<VisibilityAttr>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
|
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.
|
// this is an explicit specialization with a visibility attribute.
|
||||||
if (FunctionTemplateSpecializationInfo *specInfo
|
if (FunctionTemplateSpecializationInfo *specInfo
|
||||||
= Function->getTemplateSpecializationInfo()) {
|
= Function->getTemplateSpecializationInfo()) {
|
||||||
if (shouldConsiderTemplateLV(Function, specInfo)) {
|
if (shouldConsiderTemplateLV(Function)) {
|
||||||
LV.merge(getLVForDecl(specInfo->getTemplate(),
|
LV.merge(getLVForDecl(specInfo->getTemplate(),
|
||||||
true));
|
true));
|
||||||
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
|
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
|
||||||
|
@ -407,7 +405,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||||
|
|
||||||
// The arguments at which the template was instantiated.
|
// The arguments at which the template was instantiated.
|
||||||
const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
|
const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
|
||||||
LV.merge(getLVForTemplateArgumentList(TemplateArgs,
|
LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs,
|
||||||
OnlyTemplate));
|
OnlyTemplate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,7 +525,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) {
|
||||||
// the template parameters and arguments.
|
// the template parameters and arguments.
|
||||||
if (FunctionTemplateSpecializationInfo *spec
|
if (FunctionTemplateSpecializationInfo *spec
|
||||||
= MD->getTemplateSpecializationInfo()) {
|
= MD->getTemplateSpecializationInfo()) {
|
||||||
if (shouldConsiderTemplateLV(MD, spec)) {
|
if (shouldConsiderTemplateLV(MD)) {
|
||||||
LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments,
|
LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments,
|
||||||
OnlyTemplate));
|
OnlyTemplate));
|
||||||
if (!OnlyTemplate)
|
if (!OnlyTemplate)
|
||||||
|
|
|
@ -102,6 +102,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||||
} else {
|
} else {
|
||||||
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
|
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
|
||||||
*this, TemplateArgs);
|
*this, TemplateArgs);
|
||||||
|
if (NewAttr)
|
||||||
New->addAttr(NewAttr);
|
New->addAttr(NewAttr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -712,3 +712,55 @@ namespace test36 {
|
||||||
// CHECK: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv
|
// CHECK: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv
|
||||||
// CHECK-HIDDEN: 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
|
||||||
|
}
|
||||||
|
|
|
@ -1004,6 +1004,14 @@ void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
OS << " case attr::" << R.getName() << ": {\n";
|
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<"
|
OS << " const " << R.getName() << "Attr *A = cast<"
|
||||||
<< R.getName() << "Attr>(At);\n";
|
<< R.getName() << "Attr>(At);\n";
|
||||||
bool TDependent = R.getValueAsBit("TemplateDependent");
|
bool TDependent = R.getValueAsBit("TemplateDependent");
|
||||||
|
|
Loading…
Reference in New Issue