diff options
Diffstat (limited to 'lib')
-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 |