diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-01-15 01:23:58 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-01-15 01:23:58 +0000 |
commit | 750dc2b16fffa579f96ad053f061976a15ed4665 (patch) | |
tree | 439d63563bc1de3a5787eb8bb8e4b9ad90393923 /lib/AST/Decl.cpp | |
parent | 1136ef09ff327c2032ec20e2c2ab87cdbf017b1b (diff) |
Change linkage computation so it doesn't depend on FunctionDecl::isExternC or VarDecl::isExternC, and instead queries what it actually cares about: whether the given declaration is inside an extern "C" context. Fundamentally, figuring out whether a function/variable uses C linkage requires knowing the linkage, and the logic in FunctionDecl::isExternC and VarDecl::isExternC was getting it wrong. Given that, fix FunctionDecl::isExternC and VarDecl::isExternC to use much simpler implementations that depend on the fixed linkage computation.
Fixes a regression to test/SemaCXX/linkage.cpp caused by a new warning exposing the fact that the internal state was wrong.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148207 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r-- | lib/AST/Decl.cpp | 66 |
1 files changed, 27 insertions, 39 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 0564f297a4..96766dca5b 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -269,7 +269,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { if (D->isInAnonymousNamespace()) { const VarDecl *Var = dyn_cast<VarDecl>(D); const FunctionDecl *Func = dyn_cast<FunctionDecl>(D); - if ((!Var || !Var->isExternC()) && (!Func || !Func->isExternC())) + if ((!Var || !Var->getDeclContext()->isExternCContext()) && + (!Func || !Func->getDeclContext()->isExternCContext())) return LinkageInfo::uniqueExternal(); } @@ -330,7 +331,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // // Note that we don't want to make the variable non-external // because of this, but unique-external linkage suits us. - if (Context.getLangOptions().CPlusPlus && !Var->isExternC()) { + if (Context.getLangOptions().CPlusPlus && + !Var->getDeclContext()->isExternCContext()) { LinkageInfo TypeLV = getLVForType(Var->getType()); if (TypeLV.linkage() != ExternalLinkage) return LinkageInfo::uniqueExternal(); @@ -400,7 +402,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // unique-external linkage, it's not legally usable from outside // this translation unit. However, we should use the C linkage // rules instead for extern "C" declarations. - if (Context.getLangOptions().CPlusPlus && !Function->isExternC() && + if (Context.getLangOptions().CPlusPlus && + !Function->getDeclContext()->isExternCContext() && Function->getType()->getLinkage() == UniqueExternalLinkage) return LinkageInfo::uniqueExternal(); @@ -762,7 +765,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { // external linkage. if (D->getLexicalDeclContext()->isFunctionOrMethod()) { if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { - if (Function->isInAnonymousNamespace() && !Function->isExternC()) + if (Function->isInAnonymousNamespace() && + !Function->getDeclContext()->isExternCContext()) return LinkageInfo::uniqueExternal(); LinkageInfo LV; @@ -783,7 +787,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { if (const VarDecl *Var = dyn_cast<VarDecl>(D)) if (Var->getStorageClass() == SC_Extern || Var->getStorageClass() == SC_PrivateExtern) { - if (Var->isInAnonymousNamespace() && !Var->isExternC()) + if (Var->isInAnonymousNamespace() && + !Var->getDeclContext()->isExternCContext()) return LinkageInfo::uniqueExternal(); LinkageInfo LV; @@ -1167,27 +1172,17 @@ SourceRange VarDecl::getSourceRange() const { } bool VarDecl::isExternC() const { - ASTContext &Context = getASTContext(); - if (!Context.getLangOptions().CPlusPlus) - return (getDeclContext()->isTranslationUnit() && - getStorageClass() != SC_Static) || - (getDeclContext()->isFunctionOrMethod() && hasExternalStorage()); + if (getLinkage() != ExternalLinkage) + return false; const DeclContext *DC = getDeclContext(); - if (DC->isFunctionOrMethod()) + if (DC->isRecord()) return false; - for (; !DC->isTranslationUnit(); DC = DC->getParent()) { - if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { - if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) - return getStorageClass() != SC_Static; - - break; - } - - } - - return false; + ASTContext &Context = getASTContext(); + if (!Context.getLangOptions().CPlusPlus) + return true; + return DC->isExternCContext(); } VarDecl *VarDecl::getCanonicalDecl() { @@ -1687,27 +1682,21 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { } bool FunctionDecl::isExternC() const { - ASTContext &Context = getASTContext(); - // In C, any non-static, non-overloadable function has external - // linkage. - if (!Context.getLangOptions().CPlusPlus) - return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>(); + if (getLinkage() != ExternalLinkage) + return false; + + if (getAttr<OverloadableAttr>()) + return false; const DeclContext *DC = getDeclContext(); if (DC->isRecord()) return false; - for (; !DC->isTranslationUnit(); DC = DC->getParent()) { - if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { - if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) - return getStorageClass() != SC_Static && - !getAttr<OverloadableAttr>(); - - break; - } - } + ASTContext &Context = getASTContext(); + if (!Context.getLangOptions().CPlusPlus) + return true; - return isMain(); + return isMain() || DC->isExternCContext(); } bool FunctionDecl::isGlobal() const { @@ -2352,8 +2341,7 @@ FunctionDecl::MemoryFunctionKind FunctionDecl::getMemoryFunctionKind() { return MFK_Strndup; default: - if (getLinkage() == ExternalLinkage && - (!getASTContext().getLangOptions().CPlusPlus || isExternC())) { + if (isExternC()) { if (FnInfo->isStr("memset")) return MFK_Memset; else if (FnInfo->isStr("memcpy")) |