diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-01-09 00:47:56 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-01-09 00:47:56 +0000 |
commit | 7dc80e1c4dd44ce2b2da0fc3daff786c3d02348b (patch) | |
tree | 814ae8e165f243a597bdd6dddd3d1cefea6b7d2a /lib/Sema/SemaDecl.cpp | |
parent | e178e70e14380cf8828a307f912fcdbd3882b752 (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.cpp | 41 |
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 |