diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 0564f297a4f53f694fd1c958e19115a280af5d59..96766dca5bccc5bb48bc4444c1bf08a202c1d9b4 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -269,7 +269,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { if (D->isInAnonymousNamespace()) { const VarDecl *Var = dyn_cast(D); const FunctionDecl *Func = dyn_cast(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(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(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(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(); + if (getLinkage() != ExternalLinkage) + return false; + + if (getAttr()) + return false; const DeclContext *DC = getDeclContext(); if (DC->isRecord()) return false; - for (; !DC->isTranslationUnit(); DC = DC->getParent()) { - if (const LinkageSpecDecl *Linkage = dyn_cast(DC)) { - if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) - return getStorageClass() != SC_Static && - !getAttr(); - - 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")) diff --git a/clang/test/SemaCXX/linkage.cpp b/clang/test/SemaCXX/linkage.cpp index c373f498470ec53f55f593dc58652ddcc44e310f..6b73d596e01ba226b4fee941d8f22e66bc1d8140 100644 --- a/clang/test/SemaCXX/linkage.cpp +++ b/clang/test/SemaCXX/linkage.cpp @@ -76,15 +76,13 @@ extern "C" { struct X { int f() { extern int g(); - // FIXME: We don't compute the correct linkage for this variable - // at the moment - // extern int a; + extern int a; // Test both for mangling in the code generation and warnings from use // of internal, undefined names via -Werror. // CHECK: call i32 @g( - // FIXME: load i32* @a, - return g();// + a; + // CHECK: load i32* @a, + return g() + a; } }; }