aaronpuchert updated this revision to Diff 202479.
aaronpuchert added a comment.
This revision is now accepted and ready to land.
Show note suggesting to add `static`, move fix-it to note for functions, remove
fix-it for variables. Show note even for `extern` function definitions when we
can't build a proper fix-it.
Repository:
rC Clang
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D59402/new/
https://reviews.llvm.org/D59402
Files:
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/Sema/warn-missing-prototypes.c
test/Sema/warn-missing-variable-declarations.c
test/SemaCXX/warn-missing-prototypes.cpp
test/SemaCXX/warn-missing-variable-declarations.cpp
test/SemaOpenCL/warn-missing-prototypes.cl
Index: test/SemaOpenCL/warn-missing-prototypes.cl
===================================================================
--- test/SemaOpenCL/warn-missing-prototypes.cl
+++ 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() { }
Index: test/SemaCXX/warn-missing-variable-declarations.cpp
===================================================================
--- test/SemaCXX/warn-missing-variable-declarations.cpp
+++ 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<typename> int var_template = 0;
template<typename> constexpr int const_var_template = 0;
@@ -69,7 +75,9 @@
template int var_template<int[3]>;
extern template int var_template<int[4]>;
template<> int var_template<int[5]>; // 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<int[5]>; // 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: test/SemaCXX/warn-missing-prototypes.cpp
===================================================================
--- test/SemaCXX/warn-missing-prototypes.cpp
+++ 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,6 @@
// 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}}
Index: test/Sema/warn-missing-variable-declarations.c
===================================================================
--- test/Sema/warn-missing-variable-declarations.c
+++ 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: test/Sema/warn-missing-prototypes.c
===================================================================
--- test/Sema/warn-missing-prototypes.c
+++ test/Sema/warn-missing-prototypes.c
@@ -1,21 +1,26 @@
// RUN: %clang_cc1 -fsyntax-only -Wdocumentation -Wmissing-prototypes -verify %s
// RUN: %clang_cc1 -fsyntax-only -Wdocumentation -Wmissing-prototypes -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
-int f();
+int f(); // expected-note{{this declaration is not a prototype; add parameter declarations to make it one}}
int f(int x) { return x; } // expected-warning{{no previous prototype for function 'f'}}
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}}
+
void test(void);
-int h3();
+int h3(); // expected-note{{this declaration is not a prototype; add parameter declarations to make it one}}
int h4(int);
int h4();
@@ -26,6 +31,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; }
@@ -40,4 +46,4 @@
void not_a_prototype_test(); // expected-note{{this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function}}
void not_a_prototype_test() { } // expected-warning{{no previous prototype for function 'not_a_prototype_test'}}
-// CHECK: fix-it:"{{.*}}":{40:27-40:27}:"void"
+// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:27-[[@LINE-3]]:27}:"void"
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -11887,8 +11887,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.
@@ -12747,8 +12750,9 @@
Consumer.HandleInlineFunctionDefinition(D);
}
-static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
- const FunctionDecl*& PossibleZeroParamPrototype) {
+static bool
+ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
+ const FunctionDecl *&PossiblePrototype) {
// Don't warn about invalid declarations.
if (FD->isInvalidDecl())
return false;
@@ -12785,7 +12789,6 @@
if (FD->isDeleted())
return false;
- bool MissingPrototype = true;
for (const FunctionDecl *Prev = FD->getPreviousDecl();
Prev; Prev = Prev->getPreviousDecl()) {
// Ignore any declarations that occur in function or method
@@ -12793,13 +12796,11 @@
if (Prev->getLexicalDeclContext()->isFunctionOrMethod())
continue;
- MissingPrototype = !Prev->getType()->isFunctionProtoType();
- if (FD->getNumParams() == 0)
- PossibleZeroParamPrototype = Prev;
- break;
+ PossiblePrototype = Prev;
+ return Prev->getType()->isFunctionNoProtoType();
}
- return MissingPrototype;
+ return true;
}
void
@@ -13319,23 +13320,31 @@
// prototype declaration. This warning is issued even if the
// definition itself provides a prototype. The aim is to detect
// global functions that fail to be declared in header files.
- const FunctionDecl *PossibleZeroParamPrototype = nullptr;
- if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) {
+ const FunctionDecl *PossiblePrototype = nullptr;
+ if (ShouldWarnAboutMissingPrototype(FD, PossiblePrototype)) {
Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
- if (PossibleZeroParamPrototype) {
+ if (PossiblePrototype) {
// We found a declaration that is not a prototype,
// but that could be a zero-parameter prototype
- if (TypeSourceInfo *TI =
- PossibleZeroParamPrototype->getTypeSourceInfo()) {
+ if (TypeSourceInfo *TI = PossiblePrototype->getTypeSourceInfo()) {
TypeLoc TL = TI->getTypeLoc();
if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
- Diag(PossibleZeroParamPrototype->getLocation(),
+ Diag(PossiblePrototype->getLocation(),
diag::note_declaration_not_a_prototype)
- << PossibleZeroParamPrototype
- << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
+ << (FD->getNumParams() != 0)
+ << (FD->getNumParams() == 0
+ ? 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
// Warn if K&R function is defined without a previous declaration.
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -4652,7 +4652,8 @@
"no previous prototype for function %0">,
InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
def note_declaration_not_a_prototype : Note<
- "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">;
+ "this declaration is not a prototype; add %select{'void'|parameter declarations}0 "
+ "to make it %select{a prototype for a zero-parameter function|one}0">;
def warn_strict_prototypes : Warning<
"this %select{function declaration is not|block declaration is not|"
"old-style function definition is not preceded by}0 a prototype">,
@@ -4660,6 +4661,9 @@
def warn_missing_variable_declarations : Warning<
"no previous extern declaration for non-static variable %0">,
InGroup<DiagGroup<"missing-variable-declarations">>, 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">;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits