diff options
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r-- | lib/AST/Decl.cpp | 74 |
1 files changed, 30 insertions, 44 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index da6f03a34c..4b92069762 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -858,49 +858,14 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, return LV; } -static void clearLinkageForClass(const CXXRecordDecl *record) { - for (CXXRecordDecl::decl_iterator - i = record->decls_begin(), e = record->decls_end(); i != e; ++i) { - Decl *child = *i; - if (isa<NamedDecl>(child)) - cast<NamedDecl>(child)->ClearLinkageCache(); - } -} - void NamedDecl::anchor() { } -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. - - HasCachedLinkage = 0; - - // If we're changing the linkage of a class, we need to reset the - // linkage of child declarations, too. - if (const CXXRecordDecl *record = dyn_cast<CXXRecordDecl>(this)) - clearLinkageForClass(record); - - if (ClassTemplateDecl *temp = dyn_cast<ClassTemplateDecl>(this)) { - // Clear linkage for the template pattern. - CXXRecordDecl *record = temp->getTemplatedDecl(); - 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->ClearLinkageCache(); - } +bool NamedDecl::isLinkageValid() const { + if (!HasCachedLinkage) + return true; - // Clear cached linkage for function template decls, too. - if (FunctionTemplateDecl *temp = dyn_cast<FunctionTemplateDecl>(this)) { - temp->getTemplatedDecl()->ClearLinkageCache(); - for (FunctionTemplateDecl::spec_iterator - i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) - i->ClearLinkageCache(); - } - + return getLVForDecl(this, LVForExplicitValue).getLinkage() == + Linkage(CachedLinkage); } Linkage NamedDecl::getLinkage() const { @@ -1515,7 +1480,7 @@ VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void VarDecl::setStorageClass(StorageClass SC) { assert(isLegalForVariable(SC)); if (getStorageClass() != SC) - ClearLinkageCache(); + assert(isLinkageValid()); VarDeclBits.SClass = SC; } @@ -1560,10 +1525,27 @@ static LanguageLinkage getLanguageLinkageTemplate(const T &D) { return CXXLanguageLinkage; } +template<typename T> +static bool isExternCTemplate(const T &D) { + // Since the context is ignored for class members, they can only have C++ + // language linkage or no language linkage. + const DeclContext *DC = D.getDeclContext(); + if (DC->isRecord()) { + assert(D.getASTContext().getLangOpts().CPlusPlus); + return false; + } + + return D.getLanguageLinkage() == CLanguageLinkage; +} + LanguageLinkage VarDecl::getLanguageLinkage() const { return getLanguageLinkageTemplate(*this); } +bool VarDecl::isExternC() const { + return isExternCTemplate(*this); +} + VarDecl *VarDecl::getCanonicalDecl() { return getFirstDeclaration(); } @@ -2077,6 +2059,10 @@ LanguageLinkage FunctionDecl::getLanguageLinkage() const { return getLanguageLinkageTemplate(*this); } +bool FunctionDecl::isExternC() const { + return isExternCTemplate(*this); +} + bool FunctionDecl::isGlobal() const { if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this)) return Method->isStatic(); @@ -2129,7 +2115,7 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { void FunctionDecl::setStorageClass(StorageClass SC) { assert(isLegalForFunction(SC)); if (getStorageClass() != SC) - ClearLinkageCache(); + assert(isLinkageValid()); SClass = SC; } @@ -2867,8 +2853,8 @@ TagDecl* TagDecl::getCanonicalDecl() { void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { TypedefNameDeclOrQualifier = TDD; if (TypeForDecl) - const_cast<Type*>(TypeForDecl)->ClearLinkageCache(); - ClearLinkageCache(); + assert(TypeForDecl->isLinkageValid()); + assert(isLinkageValid()); } void TagDecl::startDefinition() { |