Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -4681,6 +4681,9 @@ def warn_missing_variable_declarations : Warning< "no previous extern declaration for non-static variable %0">, InGroup>, DefaultIgnore; +def note_static_for_internal_linkage : Note< + "declare 'static' if the %select{variable|function}0 is not intended to be " + "used outside of this translation unit">; def err_static_data_member_reinitialization : Error<"static data member %0 already has an initializer">; def err_redefinition : Error<"redefinition of %0">; Index: cfe/trunk/lib/Sema/SemaDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -11899,8 +11899,11 @@ while (prev && prev->isThisDeclarationADefinition()) prev = prev->getPreviousDecl(); - if (!prev) + if (!prev) { Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var; + Diag(var->getTypeSpecStartLoc(), diag::note_static_for_internal_linkage) + << /* variable */ 0; + } } // Cache the result of checking for constant initialization. @@ -13364,6 +13367,13 @@ ? FixItHint::CreateInsertion(FTL.getRParenLoc(), "void") : FixItHint{}); } + } else { + Diag(FD->getTypeSpecStartLoc(), diag::note_static_for_internal_linkage) + << /* function */ 1 + << (FD->getStorageClass() == SC_None + ? FixItHint::CreateInsertion(FD->getTypeSpecStartLoc(), + "static ") + : FixItHint{}); } // GNU warning -Wstrict-prototypes Index: cfe/trunk/test/Sema/warn-missing-prototypes.c =================================================================== --- cfe/trunk/test/Sema/warn-missing-prototypes.c +++ cfe/trunk/test/Sema/warn-missing-prototypes.c @@ -9,11 +9,17 @@ static int g(int x) { return x; } int h(int x) { return x; } // expected-warning{{no previous prototype for function 'h'}} +// expected-note@-1{{declare 'static' if the function is not intended to be used outside of this translation unit}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:1-[[@LINE-2]]:1}:"static " static int g2(); int g2(int x) { return x; } +extern int g3(int x) { return x; } // expected-warning{{no previous prototype for function 'g3'}} +// expected-note@-1{{declare 'static' if the function is not intended to be used outside of this translation unit}} +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:{{.*}}-[[@LINE-2]]:{{.*}}}:"{{.*}}" + void test(void); int h3(); // expected-note{{this declaration is not a prototype; add parameter declarations to make it one}} @@ -28,6 +34,7 @@ } int h2(int x) { return x; } // expected-warning{{no previous prototype for function 'h2'}} +// expected-note@-1{{declare 'static' if the function is not intended to be used outside of this translation unit}} int h3(int x) { return x; } // expected-warning{{no previous prototype for function 'h3'}} int h4(int x) { return x; } Index: cfe/trunk/test/Sema/warn-missing-variable-declarations.c =================================================================== --- cfe/trunk/test/Sema/warn-missing-variable-declarations.c +++ cfe/trunk/test/Sema/warn-missing-variable-declarations.c @@ -1,16 +1,19 @@ // RUN: %clang_cc1 -Wmissing-variable-declarations -fsyntax-only -verify %s int vbad1; // expected-warning{{no previous extern declaration for non-static variable 'vbad1'}} +// expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} int vbad2; int vbad2 = 10; // expected-warning{{no previous extern declaration for non-static variable 'vbad2'}} +// expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} -struct { +struct { // expected-note{{declare 'static' if the variable is not intended to be used outside of this translation unit}} int mgood1; } vbad3; // expected-warning{{no previous extern declaration for non-static variable 'vbad3'}} int vbad4; int vbad4 = 10; // expected-warning{{no previous extern declaration for non-static variable 'vbad4'}} +// expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} extern int vbad4; extern int vgood1; Index: cfe/trunk/test/SemaCXX/warn-missing-prototypes.cpp =================================================================== --- cfe/trunk/test/SemaCXX/warn-missing-prototypes.cpp +++ cfe/trunk/test/SemaCXX/warn-missing-prototypes.cpp @@ -1,9 +1,13 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-prototypes -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -Wmissing-prototypes -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s void f() { } // expected-warning {{no previous prototype for function 'f'}} +// expected-note@-1{{declare 'static' if the function is not intended to be used outside of this translation unit}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:1-[[@LINE-2]]:1}:"static " namespace NS { void f() { } // expected-warning {{no previous prototype for function 'f'}} + // expected-note@-1{{declare 'static' if the function is not intended to be used outside of this translation unit}} } namespace { @@ -32,3 +36,7 @@ // Don't warn on explicitly deleted functions. void j() = delete; + +extern void k() {} // expected-warning {{no previous prototype for function 'k'}} +// expected-note@-1{{declare 'static' if the function is not intended to be used outside of this translation unit}} +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:{{.*}}-[[@LINE-2]]:{{.*}}}:"{{.*}}" Index: cfe/trunk/test/SemaCXX/warn-missing-variable-declarations.cpp =================================================================== --- cfe/trunk/test/SemaCXX/warn-missing-variable-declarations.cpp +++ cfe/trunk/test/SemaCXX/warn-missing-variable-declarations.cpp @@ -1,11 +1,15 @@ -// RUN: %clang -Wmissing-variable-declarations -fsyntax-only -Xclang -verify -std=c++17 %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-variable-declarations -std=c++17 %s // Variable declarations that should trigger a warning. int vbad1; // expected-warning{{no previous extern declaration for non-static variable 'vbad1'}} +// expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} + int vbad2 = 10; // expected-warning{{no previous extern declaration for non-static variable 'vbad2'}} +// expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} namespace x { int vbad3; // expected-warning{{no previous extern declaration for non-static variable 'vbad3'}} + // expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} } // Variable declarations that should not trigger a warning. @@ -58,7 +62,9 @@ constexpr int constexpr_var = 0; inline constexpr int inline_constexpr_var = 0; extern const int extern_const_var = 0; // expected-warning {{no previous extern declaration}} +// expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} extern constexpr int extern_constexpr_var = 0; // expected-warning {{no previous extern declaration}} +// expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} template int var_template = 0; template constexpr int const_var_template = 0; @@ -69,7 +75,9 @@ template int var_template; extern template int var_template; template<> int var_template; // expected-warning {{no previous extern declaration}} +// expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} // FIXME: We give this specialization internal linkage rather than inheriting // the linkage from the template! We should not warn here. template<> int static_var_template; // expected-warning {{no previous extern declaration}} +// expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}} Index: cfe/trunk/test/SemaOpenCL/warn-missing-prototypes.cl =================================================================== --- cfe/trunk/test/SemaOpenCL/warn-missing-prototypes.cl +++ cfe/trunk/test/SemaOpenCL/warn-missing-prototypes.cl @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-prototypes %s void f() { } // expected-warning {{no previous prototype for function 'f'}} +// expected-note@-1{{declare 'static' if the function is not intended to be used outside of this translation unit}} // Don't warn about kernel functions. kernel void g() { }