[modules] Fix some more cases where we used to reject a conflict between two

declarations that are not simultaneously visible, and where at least one of
them has internal/no linkage.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@253283 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Smith 2015-11-17 03:02:41 +00:00
parent f7d4ef04b8
commit b795ce04a7
6 changed files with 49 additions and 8 deletions

View File

@ -279,6 +279,7 @@ class Sema {
// with internal linkage. // with internal linkage.
return isVisible(Old) || New->isExternallyVisible(); return isVisible(Old) || New->isExternallyVisible();
} }
bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
public: public:
typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy; typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;

View File

@ -1834,8 +1834,7 @@ static void filterNonConflictingPreviousTypedefDecls(Sema &S,
continue; continue;
} }
if (!Old->isExternallyVisible()) Filter.erase();
Filter.erase();
} }
Filter.done(); Filter.done();
@ -3344,6 +3343,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (New->isInvalidDecl()) if (New->isInvalidDecl())
return; return;
if (!shouldLinkPossiblyHiddenDecl(Previous, New))
return;
VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate(); VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate();
// Verify the old decl was also a variable or variable template. // Verify the old decl was also a variable or variable template.
@ -3375,9 +3377,6 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return New->setInvalidDecl(); return New->setInvalidDecl();
} }
if (!shouldLinkPossiblyHiddenDecl(Old, New))
return;
// Ensure the template parameters are compatible. // Ensure the template parameters are compatible.
if (NewTemplate && if (NewTemplate &&
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),

View File

@ -8684,9 +8684,11 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
assert(!R.isAmbiguous() && !R.empty()); assert(!R.isAmbiguous() && !R.empty());
// Check if we have a previous declaration with the same name. // Check if we have a previous declaration with the same name.
NamedDecl *PrevDecl = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName, LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
ForRedeclaration); ForRedeclaration);
if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) LookupQualifiedName(PrevR, CurContext->getRedeclContext());
NamedDecl *PrevDecl = PrevR.getAsSingle<NamedDecl>();
if (PrevDecl && !isVisible(PrevDecl))
PrevDecl = nullptr; PrevDecl = nullptr;
NamedDecl *ND = R.getFoundDecl(); NamedDecl *ND = R.getFoundDecl();

View File

@ -1547,6 +1547,14 @@ bool Sema::isVisibleSlow(const NamedDecl *D) {
return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D)); return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D));
} }
bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
for (auto *D : R) {
if (isVisible(D))
return true;
}
return New->isExternallyVisible();
}
/// \brief Retrieve the visible declaration corresponding to D, if any. /// \brief Retrieve the visible declaration corresponding to D, if any.
/// ///
/// This routine determines whether the declaration D is visible in the current /// This routine determines whether the declaration D is visible in the current

View File

@ -3,3 +3,9 @@ namespace NS = RealNS;
typedef int Typedef; typedef int Typedef;
using AliasDecl = int; using AliasDecl = int;
using RealNS::UsingDecl; using RealNS::UsingDecl;
struct Struct {};
extern int Variable;
namespace AnotherNS {}
enum X { Enumerator };
void Overloads();
void Overloads(int);

View File

@ -7,11 +7,24 @@ namespace NS { int n; } // expected-note {{candidate}}
struct Typedef { int n; }; // expected-note {{candidate}} struct Typedef { int n; }; // expected-note {{candidate}}
int AliasDecl; // expected-note {{candidate}} int AliasDecl; // expected-note {{candidate}}
int UsingDecl; // expected-note {{candidate}} int UsingDecl; // expected-note {{candidate}}
namespace RealNS = NS; // expected-note {{candidate}}
typedef int Struct; // expected-note {{candidate}}
enum { Variable }; // expected-note {{candidate}}
const int AnotherNS = 0; // expected-note {{candidate}}
const int Enumerator = 0; // expected-note {{candidate}}
static int Overloads; // expected-note {{candidate}}
// expected-note@decls.h:1 {{candidate}}
// expected-note@decls.h:2 {{candidate}} // expected-note@decls.h:2 {{candidate}}
// expected-note@decls.h:3 {{candidate}} // expected-note@decls.h:3 {{candidate}}
// expected-note@decls.h:4 {{candidate}} // expected-note@decls.h:4 {{candidate}}
// expected-note@decls.h:5 {{candidate}} // expected-note@decls.h:5 {{candidate}}
// expected-note@decls.h:6 {{candidate}}
// expected-note@decls.h:7 {{candidate}}
// expected-note@decls.h:8 {{candidate}}
// expected-note@decls.h:9 {{candidate}}
// expected-note@decls.h:10 {{candidate}}
// expected-note@decls.h:11 {{candidate}}
void use(int); void use(int);
void use_things() { void use_things() {
@ -19,6 +32,12 @@ void use_things() {
use(NS::n); use(NS::n);
use(AliasDecl); use(AliasDecl);
use(UsingDecl); use(UsingDecl);
use(RealNS::n);
use(Struct(0));
use(Variable);
use(AnotherNS);
use(Enumerator);
use(Overloads);
} }
#include "decls.h" #include "decls.h"
@ -28,4 +47,10 @@ void use_things_again() {
use(NS::n); // expected-error {{ambiguous}} use(NS::n); // expected-error {{ambiguous}}
use(AliasDecl); // expected-error {{ambiguous}} use(AliasDecl); // expected-error {{ambiguous}}
use(UsingDecl); // expected-error {{ambiguous}} use(UsingDecl); // expected-error {{ambiguous}}
use(RealNS::n); // expected-error {{ambiguous}}
use(Struct(0)); // expected-error {{ambiguous}}
use(Variable); // expected-error {{ambiguous}}
use(AnotherNS); // expected-error {{ambiguous}}
use(Enumerator); // expected-error {{ambiguous}}
use(Overloads); // expected-error {{ambiguous}}
} }