From: Richard Smith Date: Tue, 14 May 2019 00:27:16 +0000 (+0000) Subject: PR41817: Fix regression in r359260 that caused the MS compatibility X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=32a452aa77fbe921168b1ec5d498eac904d80dc7;p=clang PR41817: Fix regression in r359260 that caused the MS compatibility extension allowing a "static" declaration to follow an "extern" declaration to stop working. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@360637 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 4e42dd7d3b..1ca66cfb5f 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -613,12 +613,41 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { static StorageClass getStorageClass(const Decl *D) { if (auto *TD = dyn_cast(D)) D = TD->getTemplatedDecl(); - if (D) { - if (auto *VD = dyn_cast(D)) - return VD->getStorageClass(); - if (auto *FD = dyn_cast(D)) - return FD->getStorageClass(); + if (!D) + return SC_None; + + if (auto *VD = dyn_cast(D)) { + // Generally, the storage class is determined by the first declaration. + auto SC = VD->getCanonicalDecl()->getStorageClass(); + + // ... except that MSVC permits an 'extern' declaration to be redeclared + // 'static' as an extension. + if (SC == SC_Extern) { + for (auto *Redecl : VD->redecls()) { + if (Redecl->getStorageClass() == SC_Static) + return SC_Static; + if (Redecl->getStorageClass() != SC_Extern && + !Redecl->isLocalExternDecl() && !Redecl->getFriendObjectKind()) + break; + } + } + return SC; } + + if (auto *FD = dyn_cast(D)) { + auto SC = FD->getCanonicalDecl()->getStorageClass(); + if (SC == SC_Extern) { + for (auto *Redecl : FD->redecls()) { + if (Redecl->getStorageClass() == SC_Static) + return SC_Static; + if (Redecl->getStorageClass() != SC_Extern && + !Redecl->isLocalExternDecl() && !Redecl->getFriendObjectKind()) + break; + } + } + return SC; + } + return SC_None; } @@ -634,7 +663,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // A name having namespace scope (3.3.6) has internal linkage if it // is the name of - if (getStorageClass(D->getCanonicalDecl()) == SC_Static) { + if (getStorageClass(D) == SC_Static) { // - a variable, variable template, function, or function template // that is explicitly declared static; or // (This bullet corresponds to C99 6.2.2p3.) diff --git a/test/CodeGen/ms-compat-extern-static.c b/test/CodeGen/ms-compat-extern-static.c new file mode 100644 index 0000000000..2ad60ef7bc --- /dev/null +++ b/test/CodeGen/ms-compat-extern-static.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -fms-extensions -triple x86_64-windows | FileCheck %s + +// CHECK: @n = internal global i32 1 +extern int n; +static int n = 1; +int *use = &n; + +// CHECK: define internal void @f( +extern void f(); +static void f() {} +void g() { return f(); }