diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5799,6 +5799,8 @@ InGroup; def err_non_static_static : Error< "non-static declaration of %0 follows static declaration">; +def err_extern_static : Error< + "extern declaration of %0 follows static declaration">; def err_extern_non_extern : Error< "extern declaration of %0 follows non-extern declaration">; def err_non_extern_extern : Error< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4637,6 +4637,15 @@ // the prior declaration. If no prior declaration is visible, or // if the prior declaration specifies no linkage, then the // identifier has external linkage. + + if (New->hasExternalStorage() && + Old->getCanonicalDecl()->getStorageClass() == SC_Static && + Old->isLocalVarDeclOrParm()) { + Diag(New->getLocation(), diag::err_extern_static) << New->getDeclName(); + Diag(OldLocation, PrevDiag); + return New->setInvalidDecl(); + } + if (New->hasExternalStorage() && Old->hasLinkage()) /* Okay */; else if (New->getCanonicalDecl()->getStorageClass() != SC_Static && diff --git a/clang/test/SemaCXX/extern_static.cpp b/clang/test/SemaCXX/extern_static.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/extern_static.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +void f(void) +{ + static int x; // expected-note {{previous definition is here}} + extern int x; // expected-error {{extern declaration of 'x' follows static declaration}} +} \ No newline at end of file