Fix PR16060.

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.

llvm-svn: 182962
This commit is contained in:
Rafael Espindola 2013-05-30 21:23:15 +00:00
parent 4a01e59354
commit 503276be05
3 changed files with 35 additions and 3 deletions

View File

@ -89,6 +89,20 @@ public:
mergeLinkage(other.getLinkage()); 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'. /// Merge in the visibility 'newVis'.
void mergeVisibility(Visibility newVis, bool newExplicit) { void mergeVisibility(Visibility newVis, bool newExplicit) {
Visibility oldVis = getVisibility(); Visibility oldVis = getVisibility();

View File

@ -471,7 +471,9 @@ static void mergeTemplateLV(LinkageInfo &LV,
// instantiation with a visibility attribute. // instantiation with a visibility attribute.
const TemplateArgumentList &templateArgs = spec->getTemplateArgs(); const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
LV.mergeMaybeWithVisibility(argsLV, considerVisibility); if (considerVisibility)
LV.mergeVisibility(argsLV);
LV.mergeExternalVisibility(argsLV);
} }
static bool useInlineVisibilityHidden(const NamedDecl *D) { 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 // Modify the variable's linkage by its type, but ignore the
// type's visibility unless it's a definition. // type's visibility unless it's a definition.
LinkageInfo typeLV = getLVForType(*VD->getType(), computation); LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
LV.mergeMaybeWithVisibility(typeLV, if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()); LV.mergeVisibility(typeLV);
LV.mergeExternalVisibility(typeLV);
if (isExplicitMemberSpecialization(VD)) { if (isExplicitMemberSpecialization(VD)) {
explicitSpecSuppressor = VD; explicitSpecSuppressor = VD;

View File

@ -186,3 +186,18 @@ namespace test17 {
g(); 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(); }
}