summaryrefslogtreecommitdiffstats
path: root/clang/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
commit3552dabfe14af081a6a4434d3f908f420d0a3668 (patch)
treedbca0969816dbfb1702e5ffef63f75ab907e230e /clang/lib/Sema/SemaDecl.cpp
parent0ec3c5ca803cf2e431a6fddb1c504c63007d723d (diff)
downloadbcm5719-llvm-3552dabfe14af081a6a4434d3f908f420d0a3668.tar.gz
bcm5719-llvm-3552dabfe14af081a6a4434d3f908f420d0a3668.zip
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. llvm-svn: 171925
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5b610b96050..d7a204325ff 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/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
OpenPOWER on IntegriCloud