aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/Decl.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-01-12 06:42:30 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-01-12 06:42:30 +0000
commit838dc597e25614c653a062a124b06a04d6b7f5eb (patch)
tree2c93daa5ee846c400fdfdc9b335b829f74048958 /lib/AST/Decl.cpp
parentbcfdd263b79c766db9154b009bd831ef83090c83 (diff)
Disable caching of visibility.
The testcase in pr14929 shows that this is extremely hard to do. If we choose to apply the attribute, that causes the visibility of some decls to change and that can happen really late (during codegen). Current gcc warns and ignores the attribute in this testcase with a warning. This suggest that the correct solution is to find a point in the compilation where we can compute the visibility and * assert it was never computed before * reject any attempts to compute it again in the future (with warnings). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172305 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r--lib/AST/Decl.cpp83
1 files changed, 43 insertions, 40 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index bf5bfaaef1..986430595b 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -104,14 +104,8 @@ getLVForTemplateParameterList(const TemplateParameterList *Params) {
return LV;
}
-/// Compute the linkage and visibility for the given declaration.
-static LinkageInfo computeLVForDecl(const NamedDecl *D, bool OnlyTemplate);
-
-static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) {
- if (!OnlyTemplate)
- return D->getLinkageAndVisibility();
- return computeLVForDecl(D, OnlyTemplate);
-}
+/// getLVForDecl - Get the linkage and visibility for the given declaration.
+static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate);
/// \brief Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
@@ -575,18 +569,18 @@ static void clearLinkageForClass(const CXXRecordDecl *record) {
i = record->decls_begin(), e = record->decls_end(); i != e; ++i) {
Decl *child = *i;
if (isa<NamedDecl>(child))
- cast<NamedDecl>(child)->ClearLVCache();
+ cast<NamedDecl>(child)->ClearLinkageCache();
}
}
void NamedDecl::anchor() { }
-void NamedDecl::ClearLVCache() {
+void NamedDecl::ClearLinkageCache() {
// Note that we can't skip clearing the linkage of children just
// because the parent doesn't have cached linkage: we don't cache
// when computing linkage for parent contexts.
- CacheValidAndVisibility = 0;
+ HasCachedLinkage = 0;
// If we're changing the linkage of a class, we need to reset the
// linkage of child declarations, too.
@@ -597,51 +591,66 @@ void NamedDecl::ClearLVCache() {
dyn_cast<ClassTemplateDecl>(const_cast<NamedDecl*>(this))) {
// Clear linkage for the template pattern.
CXXRecordDecl *record = temp->getTemplatedDecl();
- record->CacheValidAndVisibility = 0;
+ record->HasCachedLinkage = 0;
clearLinkageForClass(record);
// We need to clear linkage for specializations, too.
for (ClassTemplateDecl::spec_iterator
i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i)
- i->ClearLVCache();
+ i->ClearLinkageCache();
}
// Clear cached linkage for function template decls, too.
if (FunctionTemplateDecl *temp =
dyn_cast<FunctionTemplateDecl>(const_cast<NamedDecl*>(this))) {
- temp->getTemplatedDecl()->ClearLVCache();
+ temp->getTemplatedDecl()->ClearLinkageCache();
for (FunctionTemplateDecl::spec_iterator
i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i)
- i->ClearLVCache();
+ i->ClearLinkageCache();
}
}
Linkage NamedDecl::getLinkage() const {
- return getLinkageAndVisibility().linkage();
+ if (HasCachedLinkage) {
+ assert(Linkage(CachedLinkage) ==
+ getLVForDecl(this, true).linkage());
+ return Linkage(CachedLinkage);
+ }
+
+ CachedLinkage = getLVForDecl(this, true).linkage();
+ HasCachedLinkage = 1;
+
+#ifndef NDEBUG
+ verifyLinkage();
+#endif
+
+ return Linkage(CachedLinkage);
}
LinkageInfo NamedDecl::getLinkageAndVisibility() const {
- if (CacheValidAndVisibility) {
- Linkage L = static_cast<Linkage>(CachedLinkage);
- Visibility V = static_cast<Visibility>(CacheValidAndVisibility - 1);
- bool Explicit = CachedVisibilityExplicit;
- LinkageInfo LV(L, V, Explicit);
- assert(LV == computeLVForDecl(this, false));
- return LV;
+ LinkageInfo LI = getLVForDecl(this, false);
+ if (HasCachedLinkage) {
+ assert(Linkage(CachedLinkage) == LI.linkage());
+ return LI;
}
- LinkageInfo LV = computeLVForDecl(this, false);
- CachedLinkage = LV.linkage();
- CacheValidAndVisibility = LV.visibility() + 1;
- CachedVisibilityExplicit = LV.visibilityExplicit();
+ HasCachedLinkage = 1;
+ CachedLinkage = LI.linkage();
#ifndef NDEBUG
+ verifyLinkage();
+#endif
+
+ return LI;
+}
+
+void NamedDecl::verifyLinkage() const {
// 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;
+ return;
// 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
@@ -651,15 +660,12 @@ LinkageInfo NamedDecl::getLinkageAndVisibility() const {
NamedDecl *T = cast<NamedDecl>(*I);
if (T == this)
continue;
- if (T->CacheValidAndVisibility != 0) {
+ if (T->HasCachedLinkage != 0) {
D = T;
break;
}
}
assert(!D || D->CachedLinkage == CachedLinkage);
-#endif
-
- return LV;
}
llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const {
@@ -723,7 +729,7 @@ llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const {
return llvm::Optional<Visibility>();
}
-static LinkageInfo computeLVForDecl(const NamedDecl *D, bool OnlyTemplate) {
+static LinkageInfo getLVForDecl(const NamedDecl *D, bool OnlyTemplate) {
// Objective-C: treat all Objective-C declarations as having external
// linkage.
switch (D->getKind()) {
@@ -1192,7 +1198,7 @@ VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
void VarDecl::setStorageClass(StorageClass SC) {
assert(isLegalForVariable(SC));
if (getStorageClass() != SC)
- ClearLVCache();
+ ClearLinkageCache();
VarDeclBits.SClass = SC;
}
@@ -1714,9 +1720,6 @@ void FunctionDecl::setBody(Stmt *B) {
Body = B;
if (B)
EndRangeLoc = B->getLocEnd();
- for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); R != REnd;
- ++R)
- R->ClearLVCache();
}
void FunctionDecl::setPure(bool P) {
@@ -1825,7 +1828,7 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() {
void FunctionDecl::setStorageClass(StorageClass SC) {
assert(isLegalForFunction(SC));
if (getStorageClass() != SC)
- ClearLVCache();
+ ClearLinkageCache();
SClass = SC;
}
@@ -2595,8 +2598,8 @@ TagDecl* TagDecl::getCanonicalDecl() {
void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
TypedefNameDeclOrQualifier = TDD;
if (TypeForDecl)
- const_cast<Type*>(TypeForDecl)->ClearLVCache();
- ClearLVCache();
+ const_cast<Type*>(TypeForDecl)->ClearLinkageCache();
+ ClearLinkageCache();
}
void TagDecl::startDefinition() {