diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2013-04-25 13:10:46 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2013-04-25 13:10:46 +0000 |
| commit | 7e2e4fafc01c5c79f1441c98a4286176890adb37 (patch) | |
| tree | 308117eea64dc046479c4b9928f5f31aa022299a | |
| parent | 04d3f4960816c390ff02c92722182044095ec5a3 (diff) | |
| download | llvm-7e2e4fafc01c5c79f1441c98a4286176890adb37.zip llvm-7e2e4fafc01c5c79f1441c98a4286176890adb37.tar.gz llvm-7e2e4fafc01c5c79f1441c98a4286176890adb37.tar.bz2 | |
Fix a case in linkage computation that should check for single line extern "C".
llvm-svn: 180263
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 17 | ||||
| -rw-r--r-- | clang/test/SemaCXX/undefined-internal.cpp | 7 |
2 files changed, 18 insertions, 6 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index cb375eb..a431c53 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -476,6 +476,13 @@ template <typename T> static bool isInExternCContext(T *D) { return First->getDeclContext()->isExternCContext(); } +static bool isSingleLineExternC(const Decl &D) { + if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext())) + if (SD->getLanguage() == LinkageSpecDecl::lang_c && !SD->hasBraces()) + return true; + return false; +} + static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVComputationKind computation) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && @@ -504,7 +511,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, return PrevVar->getLinkageAndVisibility(); if (Var->getStorageClass() != SC_Extern && - Var->getStorageClass() != SC_PrivateExtern) + Var->getStorageClass() != SC_PrivateExtern && + !isSingleLineExternC(*Var)) return LinkageInfo::internal(); } @@ -1580,11 +1588,8 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( // A declaration directly contained in a linkage-specification is treated // as if it contains the extern specifier for the purpose of determining // the linkage of the declared name and whether it is a definition. - const DeclContext *DC = getDeclContext(); - if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(DC)) { - if (SD->getLanguage() == LinkageSpecDecl::lang_c && !SD->hasBraces()) - return DeclarationOnly; - } + if (isSingleLineExternC(*this)) + return DeclarationOnly; // C99 6.9.2p2: // A declaration of an object that has file scope without an initializer, diff --git a/clang/test/SemaCXX/undefined-internal.cpp b/clang/test/SemaCXX/undefined-internal.cpp index 839fdaf..1b76a86 100644 --- a/clang/test/SemaCXX/undefined-internal.cpp +++ b/clang/test/SemaCXX/undefined-internal.cpp @@ -323,3 +323,10 @@ namespace test13 { } } +namespace test14 { + extern "C" const int foo; + + int f() { + return foo; + } +} |
