summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h1
-rw-r--r--clang/lib/Sema/SemaDecl.cpp9
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp8
-rw-r--r--clang/lib/Sema/SemaLookup.cpp8
-rw-r--r--clang/test/Modules/Inputs/no-linkage/decls.h6
-rw-r--r--clang/test/Modules/no-linkage.cpp25
6 files changed, 49 insertions, 8 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7c2fa049898..090559e0a29 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -279,6 +279,7 @@ class Sema {
// with internal linkage.
return isVisible(Old) || New->isExternallyVisible();
}
+ bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
public:
typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5123601d8a6..5215a7e0dc4 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1834,8 +1834,7 @@ static void filterNonConflictingPreviousTypedefDecls(Sema &S,
continue;
}
- if (!Old->isExternallyVisible())
- Filter.erase();
+ Filter.erase();
}
Filter.done();
@@ -3344,6 +3343,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (New->isInvalidDecl())
return;
+ if (!shouldLinkPossiblyHiddenDecl(Previous, New))
+ return;
+
VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate();
// 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();
}
- if (!shouldLinkPossiblyHiddenDecl(Old, New))
- return;
-
// Ensure the template parameters are compatible.
if (NewTemplate &&
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index b7278904185..eb010e9e39a 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -8684,9 +8684,11 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
assert(!R.isAmbiguous() && !R.empty());
// Check if we have a previous declaration with the same name.
- NamedDecl *PrevDecl = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName,
- ForRedeclaration);
- if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
+ LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ LookupQualifiedName(PrevR, CurContext->getRedeclContext());
+ NamedDecl *PrevDecl = PrevR.getAsSingle<NamedDecl>();
+ if (PrevDecl && !isVisible(PrevDecl))
PrevDecl = nullptr;
NamedDecl *ND = R.getFoundDecl();
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 7236e99942b..9b5d511818e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1547,6 +1547,14 @@ bool Sema::isVisibleSlow(const 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.
///
/// This routine determines whether the declaration D is visible in the current
diff --git a/clang/test/Modules/Inputs/no-linkage/decls.h b/clang/test/Modules/Inputs/no-linkage/decls.h
index 9e18e10ce99..c8d6de55f74 100644
--- a/clang/test/Modules/Inputs/no-linkage/decls.h
+++ b/clang/test/Modules/Inputs/no-linkage/decls.h
@@ -3,3 +3,9 @@ namespace NS = RealNS;
typedef int Typedef;
using AliasDecl = int;
using RealNS::UsingDecl;
+struct Struct {};
+extern int Variable;
+namespace AnotherNS {}
+enum X { Enumerator };
+void Overloads();
+void Overloads(int);
diff --git a/clang/test/Modules/no-linkage.cpp b/clang/test/Modules/no-linkage.cpp
index d4a9eaba403..1ec8f4075e4 100644
--- a/clang/test/Modules/no-linkage.cpp
+++ b/clang/test/Modules/no-linkage.cpp
@@ -7,11 +7,24 @@ namespace NS { int n; } // expected-note {{candidate}}
struct Typedef { int n; }; // expected-note {{candidate}}
int AliasDecl; // 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:3 {{candidate}}
// expected-note@decls.h:4 {{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_things() {
@@ -19,6 +32,12 @@ void use_things() {
use(NS::n);
use(AliasDecl);
use(UsingDecl);
+ use(RealNS::n);
+ use(Struct(0));
+ use(Variable);
+ use(AnotherNS);
+ use(Enumerator);
+ use(Overloads);
}
#include "decls.h"
@@ -28,4 +47,10 @@ void use_things_again() {
use(NS::n); // expected-error {{ambiguous}}
use(AliasDecl); // 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}}
}
OpenPOWER on IntegriCloud