Add a new warning -Wmissing-variable-declarations, to warn about variables

defined without a previous declaration.  This is similar to
-Wmissing-prototypes, but for variables instead of functions.

Patch by Ed Schouten.

llvm-svn: 166498
This commit is contained in:
Eli Friedman 2012-10-23 20:19:32 +00:00
parent b0eea8b54b
commit 7d14b3c9b3
5 changed files with 91 additions and 0 deletions

View File

@ -3139,6 +3139,9 @@ def note_sentinel_here : Note<
def warn_missing_prototype : Warning<
"no previous prototype for function %0">,
InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
def warn_missing_variable_declarations : Warning<
"no previous extern declaration for non-static variable %0">,
InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore;
def err_redefinition : Error<"redefinition of %0">;
def err_definition_of_implicitly_declared_member : Error<
"definition of implicitly declared %select{default constructor|copy "

View File

@ -665,6 +665,8 @@ void Sema::ActOnEndOfTranslationUnit() {
diag::err_tentative_def_incomplete_type))
VD->setInvalidDecl();
CheckCompleteVariableDeclaration(VD);
// Notify the consumer that we've completed a tentative definition.
if (!VD->isInvalidDecl())
Consumer.CompleteTentativeDefinition(VD);

View File

@ -7148,6 +7148,17 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
}
if (var->isThisDeclarationADefinition() &&
var->getLinkage() == ExternalLinkage) {
// Find a previous declaration that's not a definition.
VarDecl *prev = var->getPreviousDecl();
while (prev && prev->isThisDeclarationADefinition())
prev = prev->getPreviousDecl();
if (!prev)
Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var;
}
// All the following checks are C++ only.
if (!getLangOpts().CPlusPlus) return;

View File

@ -0,0 +1,36 @@
// RUN: %clang -Wmissing-variable-declarations -fsyntax-only -Xclang -verify %s
int vbad1; // expected-warning{{no previous extern declaration for non-static variable 'vbad1'}}
int vbad2;
int vbad2 = 10; // expected-warning{{no previous extern declaration for non-static variable 'vbad2'}}
struct {
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'}}
extern int vbad4;
extern int vgood1;
int vgood1;
int vgood1 = 10;
// RUN: %clang -Wmissing-variable-declarations -fsyntax-only -Xclang -verify %s
int vbad1; // expected-warning{{no previous extern declaration for non-static variable 'vbad1'}}
int vbad2;
int vbad2 = 10; // expected-warning{{no previous extern declaration for non-static variable 'vbad2'}}
struct {
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'}}
extern int vbad4;
extern int vgood1;
int vgood1;
int vgood1 = 10;

View File

@ -0,0 +1,39 @@
// RUN: %clang -Wmissing-variable-declarations -fsyntax-only -Xclang -verify %s
// Variable declarations that should trigger a warning.
int vbad1; // expected-warning{{no previous extern declaration for non-static variable 'vbad1'}}
int vbad2 = 10; // expected-warning{{no previous extern declaration for non-static variable 'vbad2'}}
// Variable declarations that should not trigger a warning.
static int vgood1;
extern int vgood2;
int vgood2;
static struct {
int mgood1;
} vgood3;
// Functions should never trigger a warning.
void fgood1(void);
void fgood2(void) {
int lgood1;
static int lgood2;
}
static void fgood3(void) {
int lgood3;
static int lgood4;
}
// Structures, namespaces and classes should be unaffected.
struct sgood1 {
int mgood2;
};
struct {
int mgood3;
} sgood2;
class CGood1 {
static int MGood1;
};
int CGood1::MGood1;
namespace {
int mgood4;
}