diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2013-01-05 01:28:37 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2013-01-05 01:28:37 +0000 |
commit | 6acc4bc44db341d499a925cfe68bea89390039a4 (patch) | |
tree | 639c7a71648b8b6656211864d7e21f92ac1793fb /lib/AST/Decl.cpp | |
parent | ba3c9ca16b3992248ec654ce9ec8c841c1c6d1e9 (diff) |
Assert that redeclarations have the same linkage.
It is somewhat hard to test linkage, so I decided to try to add an assert. This
already found some interesting cases where there were different.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171585 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r-- | lib/AST/Decl.cpp | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 8b8e1ee752..35e61b5775 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -268,8 +268,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (D->isInAnonymousNamespace()) { const VarDecl *Var = dyn_cast<VarDecl>(D); const FunctionDecl *Func = dyn_cast<FunctionDecl>(D); - if ((!Var || !Var->getDeclContext()->isExternCContext()) && - (!Func || !Func->getDeclContext()->isExternCContext())) + if ((!Var || !Var->hasCLanguageLinkage()) && + (!Func || !Func->hasCLanguageLinkage())) return LinkageInfo::uniqueExternal(); } @@ -634,6 +634,31 @@ LinkageInfo NamedDecl::getLinkageAndVisibility() const { CachedLinkage = LV.linkage(); CacheValidAndVisibility = LV.visibility() + 1; CachedVisibilityExplicit = LV.visibilityExplicit(); + +#ifndef NDEBUG + // In C (because of gnu inline) and in c++ with microsoft extensions an + // static can follow an extern, so we can have two decls with different + // linkages. + const LangOptions &Opts = getASTContext().getLangOpts(); + if (!Opts.CPlusPlus || Opts.MicrosoftExt) + return LV; + + // We have just computed the linkage for this decl. By induction we know + // that all other computed linkages match, check that the one we just computed + // also does. + NamedDecl *D = NULL; + for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + NamedDecl *T = cast<NamedDecl>(*I); + if (T == this) + continue; + if (T->CacheValidAndVisibility != 0) { + D = T; + break; + } + } + assert(!D || D->CachedLinkage == CachedLinkage); +#endif + return LV; } @@ -772,7 +797,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, bool OnlyTemplate) { // one such matching entity, the program is ill-formed. Otherwise, // if no matching entity is found, the block scope entity receives // external linkage. - if (D->getLexicalDeclContext()->isFunctionOrMethod()) { + if (D->getDeclContext()->isFunctionOrMethod()) { if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { if (Function->isInAnonymousNamespace() && !Function->getDeclContext()->isExternCContext()) |