diff options
-rw-r--r-- | include/clang/AST/Decl.h | 16 | ||||
-rw-r--r-- | include/clang/AST/DeclBase.h | 8 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 51 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 22 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 8 |
6 files changed, 61 insertions, 48 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index d0bf559d1e..a0c76c069b 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -830,6 +830,14 @@ public: /// external, C linkage. bool isExternC() const; + /// \brief Determines whether this variable's context is, or is nested within, + /// a C++ extern "C" linkage spec. + bool isInExternCContext() const; + + /// \brief Determines whether this variable's context is, or is nested within, + /// a C++ extern "C++" linkage spec. + bool isInExternCXXContext() const; + /// isLocalVarDecl - Returns true for local variable declarations /// other than parameters. Note that this includes static variables /// inside of functions. It also includes variables inside blocks. @@ -1715,6 +1723,14 @@ public: /// external, C linkage. bool isExternC() const; + /// \brief Determines whether this function's context is, or is nested within, + /// a C++ extern "C" linkage spec. + bool isInExternCContext() const; + + /// \brief Determines whether this function's context is, or is nested within, + /// a C++ extern "C++" linkage spec. + bool isInExternCXXContext() const; + /// \brief Determines whether this is a global function. bool isGlobal() const; diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index a4a52e2a78..754facfb59 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -1096,14 +1096,6 @@ public: /// C++0x scoped enums), and C++ linkage specifications. bool isTransparentContext() const; - /// \brief Determines whether this context is, or is nested within, - /// a C++ extern "C" linkage spec. - bool isExternCContext() const; - - /// \brief Determines whether this context is, or is nested within, - /// a C++ extern "C++" linkage spec. - bool isExternCXXContext() const; - /// \brief Determine whether this declaration context is equivalent /// to the declaration context DC. bool Equals(const DeclContext *DC) const { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index ff012fc401..ab9d73b917 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -471,9 +471,9 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) { FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>(); } -template <typename T> static bool isInExternCContext(T *D) { +template <typename T> static bool isFirstInExternCContext(T *D) { const T *First = D->getFirstDeclaration(); - return First->getDeclContext()->isExternCContext(); + return First->isInExternCContext(); } static bool isSingleLineExternC(const Decl &D) { @@ -548,8 +548,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 || !isInExternCContext(Var)) && - (!Func || !isInExternCContext(Func))) + if ((!Var || !isFirstInExternCContext(Var)) && + (!Func || !isFirstInExternCContext(Func))) return LinkageInfo::uniqueExternal(); } @@ -626,7 +626,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // // Note that we don't want to make the variable non-external // because of this, but unique-external linkage suits us. - if (Context.getLangOpts().CPlusPlus && !isInExternCContext(Var)) { + if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) { LinkageInfo TypeLV = Var->getType()->getLinkageAndVisibility(); if (TypeLV.getLinkage() != ExternalLinkage) return LinkageInfo::uniqueExternal(); @@ -660,7 +660,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // this translation unit. However, we should use the C linkage // rules instead for extern "C" declarations. if (Context.getLangOpts().CPlusPlus && - !Function->getDeclContext()->isExternCContext() && + !Function->isInExternCContext() && Function->getType()->getLinkage() == UniqueExternalLinkage) return LinkageInfo::uniqueExternal(); @@ -997,7 +997,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, LVComputationKind computation) { if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { if (Function->isInAnonymousNamespace() && - !Function->getDeclContext()->isExternCContext()) + !Function->isInExternCContext()) return LinkageInfo::uniqueExternal(); // This is a "void f();" which got merged with a file static. @@ -1020,8 +1020,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { if (Var->hasExternalStorage()) { - if (Var->isInAnonymousNamespace() && - !Var->getDeclContext()->isExternCContext()) + if (Var->isInAnonymousNamespace() && !Var->isInExternCContext()) return LinkageInfo::uniqueExternal(); LinkageInfo LV; @@ -1522,8 +1521,7 @@ static LanguageLinkage getLanguageLinkageTemplate(const T &D) { // If the first decl is in an extern "C" context, any other redeclaration // will have C language linkage. If the first one is not in an extern "C" // context, we would have reported an error for any other decl being in one. - const T *First = D.getFirstDeclaration(); - if (First->getDeclContext()->isExternCContext()) + if (isFirstInExternCContext(&D)) return CLanguageLinkage; return CXXLanguageLinkage; } @@ -1549,6 +1547,29 @@ bool VarDecl::isExternC() const { return isExternCTemplate(*this); } +static bool isLinkageSpecContext(const DeclContext *DC, + LinkageSpecDecl::LanguageIDs ID) { + while (DC->getDeclKind() != Decl::TranslationUnit) { + if (DC->getDeclKind() == Decl::LinkageSpec) + return cast<LinkageSpecDecl>(DC)->getLanguage() == ID; + DC = DC->getParent(); + } + return false; +} + +template <typename T> +static bool isInLanguageSpecContext(T *D, LinkageSpecDecl::LanguageIDs ID) { + return isLinkageSpecContext(D->getLexicalDeclContext(), ID); +} + +bool VarDecl::isInExternCContext() const { + return isInLanguageSpecContext(this, LinkageSpecDecl::lang_c); +} + +bool VarDecl::isInExternCXXContext() const { + return isInLanguageSpecContext(this, LinkageSpecDecl::lang_cxx); +} + VarDecl *VarDecl::getCanonicalDecl() { return getFirstDeclaration(); } @@ -2070,6 +2091,14 @@ bool FunctionDecl::isExternC() const { return isExternCTemplate(*this); } +bool FunctionDecl::isInExternCContext() const { + return isInLanguageSpecContext(this, LinkageSpecDecl::lang_c); +} + +bool FunctionDecl::isInExternCXXContext() const { + return isInLanguageSpecContext(this, LinkageSpecDecl::lang_cxx); +} + bool FunctionDecl::isGlobal() const { if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this)) return Method->isStatic(); diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 7b7900640b..084a4321d8 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -819,28 +819,6 @@ bool DeclContext::isTransparentContext() const { return false; } -bool DeclContext::isExternCContext() const { - const DeclContext *DC = this; - while (DC->DeclKind != Decl::TranslationUnit) { - if (DC->DeclKind == Decl::LinkageSpec) - return cast<LinkageSpecDecl>(DC)->getLanguage() - == LinkageSpecDecl::lang_c; - DC = DC->getParent(); - } - return false; -} - -bool DeclContext::isExternCXXContext() const { - const DeclContext *DC = this; - while (DC->DeclKind != Decl::TranslationUnit) { - if (DC->DeclKind == Decl::LinkageSpec) - return cast<LinkageSpecDecl>(DC)->getLanguage() - == LinkageSpecDecl::lang_cxx; - DC = DC->getParent(); - } - return false; -} - bool DeclContext::Encloses(const DeclContext *DC) const { if (getPrimaryContext() != this) return getPrimaryContext()->Encloses(DC); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6ebd1d1410..ff183c96e0 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1731,8 +1731,8 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D, // Must be in an extern "C" context. Entities declared directly within // a record are not extern "C" even if the record is in such a context. - const DeclContext *DC = D->getFirstDeclaration()->getDeclContext(); - if (DC->isRecord() || !DC->isExternCContext()) + const SomeDecl *First = D->getFirstDeclaration(); + if (First->getDeclContext()->isRecord() || !First->isInExternCContext()) return; // OK, this is an internal linkage entity inside an extern "C" linkage diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b5e2c6ebe8..8f78ead59e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2246,11 +2246,9 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) { return false; LanguageLinkage OldLinkage = Old->getLanguageLinkage(); - if (OldLinkage == CXXLanguageLinkage && - New->getLexicalDeclContext()->isExternCContext()) + if (OldLinkage == CXXLanguageLinkage && New->isInExternCContext()) return true; - if (OldLinkage == CLanguageLinkage && - New->getLexicalDeclContext()->isExternCXXContext()) + if (OldLinkage == CLanguageLinkage && New->isInExternCXXContext()) return true; return false; } @@ -5153,7 +5151,7 @@ static bool mayConflictWithNonVisibleExternC(const T *ND) { // This code runs before the init of foo is set, and therefore before // the type of foo is known. Not knowing the type we cannot know its linkage // unless it is in an extern C block. - if (!DC->isExternCContext()) { + if (!ND->isInExternCContext()) { const ASTContext &Context = ND->getASTContext(); if (Context.getLangOpts().CPlusPlus) return false; |