aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-01-09 00:47:56 +0000
committerDouglas Gregor <dgregor@apple.com>2013-01-09 00:47:56 +0000
commit7dc80e1c4dd44ce2b2da0fc3daff786c3d02348b (patch)
tree814ae8e165f243a597bdd6dddd3d1cefea6b7d2a /lib/Sema/SemaDecl.cpp
parente178e70e14380cf8828a307f912fcdbd3882b752 (diff)
When name lookup for a redeclaration finds declarations that are known
(because they are part of some module) but have not been made visible (because they are in a submodule that wasn't imported), filter out those declarations unless both the old declaration and the new declaration have external linkage. When one or both has internal linkage, there should be no conflict unless both are imported. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171925 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 5b610b9605..d7a204325f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1568,6 +1568,40 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
return New;
}
+/// \brief Filter out any previous declarations that the given declaration
+/// should not consider because they are not permitted to conflict, e.g.,
+/// because they come from hidden sub-modules and do not refer to the same
+/// entity.
+static void filterNonConflictingPreviousDecls(ASTContext &context,
+ NamedDecl *decl,
+ LookupResult &previous){
+ // This is only interesting when modules are enabled.
+ if (!context.getLangOpts().Modules)
+ return;
+
+ // Empty sets are uninteresting.
+ if (previous.empty())
+ return;
+
+ // If this declaration has external
+ bool hasExternalLinkage = (decl->getLinkage() == ExternalLinkage);
+
+ LookupResult::Filter filter = previous.makeFilter();
+ while (filter.hasNext()) {
+ NamedDecl *old = filter.next();
+
+ // Non-hidden declarations are never ignored.
+ if (!old->isHidden())
+ continue;
+
+ // If either has no-external linkage, ignore the old declaration.
+ if (!hasExternalLinkage || old->getLinkage() != ExternalLinkage)
+ filter.erase();
+ }
+
+ filter.done();
+}
+
bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
QualType OldType;
if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
@@ -4139,6 +4173,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
// in an outer scope, it isn't the same thing.
FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false,
/*ExplicitInstantiationOrSpecialization=*/false);
+ filterNonConflictingPreviousDecls(Context, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
MergeTypedefNameDecl(NewTD, Previous);
@@ -4768,6 +4803,9 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
Previous.addDecl(Pos->second);
}
+ // Filter out any non-conflicting previous declarations.
+ filterNonConflictingPreviousDecls(Context, NewVD, Previous);
+
if (T->isVoidType() && !NewVD->hasExternalStorage()) {
Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
<< T;
@@ -6118,6 +6156,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
Previous.addDecl(Pos->second);
}
+ // Filter out any non-conflicting previous declarations.
+ filterNonConflictingPreviousDecls(Context, NewFD, Previous);
+
bool Redeclaration = false;
// Merge or overload the declaration with an existing declaration of