aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/Decl.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-01-05 01:28:37 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-01-05 01:28:37 +0000
commit6acc4bc44db341d499a925cfe68bea89390039a4 (patch)
tree639c7a71648b8b6656211864d7e21f92ac1793fb /lib/AST/Decl.cpp
parentba3c9ca16b3992248ec654ce9ec8c841c1c6d1e9 (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.cpp31
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())