alexfh created this revision.
Missing 'static' on functions that are intended to be local to a translation
unit seems to be the most common cause of -Wmissing-prototypes warnings, so
suggesting a fix seems to be convenient and useful.
https://reviews.llvm.org/D32170
Files:
include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/SemaCXX/warn-missing-prototypes.cpp
Index: test/SemaCXX/warn-missing-prototypes.cpp
===================================================================
--- test/SemaCXX/warn-missing-prototypes.cpp
+++ test/SemaCXX/warn-missing-prototypes.cpp
@@ -1,6 +1,22 @@
// 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 -implicit-check-not=fix-it:
-void f() { } // expected-warning {{no previous prototype for function 'f'}}
+void f() { } // expected-warning {{no previous prototype for function 'f'; did you mean to mark the function 'static'?}}
+// CHECK: fix-it:"{{.*}}":{4:1-4:1}:"static "
+
+#define F2 void f2() { }
+
+F2 // expected-warning {{no previous prototype for function 'f2'}}
+
+extern void f3() {} // expected-warning {{no previous prototype for function 'f3'}}
+extern "C" void f4() {} // expected-warning {{no previous prototype for function 'f4'}}
+extern "C++" void f5() {} // expected-warning {{no previous prototype for function 'f5'}}
+extern "C" {
+ void f6() {} // expected-warning {{no previous prototype for function 'f6'}}
+}
+extern "C++" {
+ void f7() {} // expected-warning {{no previous prototype for function 'f7'}}
+}
namespace NS {
void f() { } // expected-warning {{no previous prototype for function 'f'}}
@@ -16,6 +32,7 @@
void f() { }
};
+
// Don't warn about inline functions.
inline void g() { }
@@ -32,3 +49,6 @@
// Don't warn on explicitly deleted functions.
void j() = delete;
+
+// Don't warn on static functions.
+static void s() {}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -11649,7 +11649,8 @@
}
static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
- const FunctionDecl*& PossibleZeroParamPrototype) {
+ const FunctionDecl*& PossibleZeroParamPrototype,
+ bool *PossibleMissingStatic) {
// Don't warn about invalid declarations.
if (FD->isInvalidDecl())
return false;
@@ -11686,21 +11687,27 @@
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
// scope, because they aren't visible from the header.
if (Prev->getLexicalDeclContext()->isFunctionOrMethod())
continue;
- MissingPrototype = !Prev->getType()->isFunctionProtoType();
+ if (Prev->getType()->isFunctionProtoType())
+ return false;
+
if (FD->getNumParams() == 0)
PossibleZeroParamPrototype = Prev;
break;
}
- return MissingPrototype;
+ // Check whether applying a 'static' could make sense for this function.
+ *PossibleMissingStatic = FD->getDeclContext() &&
+ FD->getDeclContext()->isTranslationUnit() &&
+ FD->getStorageClass() == SC_None;
+
+ return true;
}
void
@@ -12099,8 +12106,19 @@
// 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)) {
- Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+ bool PossibleMissingStatic = false;
+ if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype,
+ &PossibleMissingStatic)) {
+ if (PossibleMissingStatic) {
+ auto DiagBuilder =
+ Diag(FD->getLocation(), diag::warn_missing_prototype_maybe_static)
+ << FD;
+ SourceLocation Loc = FD->getLocStart();
+ if (Loc.isFileID())
+ DiagBuilder << FixItHint::CreateInsertion(Loc, "static ");
+ } else {
+ Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+ }
if (PossibleZeroParamPrototype) {
// We found a declaration that is not a prototype,
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -4545,9 +4545,12 @@
"%select{function|method|block}0 has been explicitly marked sentinel here">;
def warn_missing_prototype : Warning<
"no previous prototype for function %0">,
- InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
+ InGroup<MissingPrototypes>, DefaultIgnore;
+def warn_missing_prototype_maybe_static : Warning<
+ "no previous prototype for function %0; did you mean to mark the function 'static'?">,
+ InGroup<MissingPrototypes>, 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 'void' to make it a prototype for a zero-parameter function">;
def warn_strict_prototypes : Warning<
"this %select{function declaration is not|"
"old-style function definition is not preceded by}0 a prototype">,
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -285,6 +285,7 @@
def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
def MismatchedTags : DiagGroup<"mismatched-tags">;
def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingPrototypes : DiagGroup<"missing-prototypes">;
def ModuleBuild : DiagGroup<"module-build">;
def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits