forked from OSchip/llvm-project
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:
parent
b0eea8b54b
commit
7d14b3c9b3
|
@ -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 "
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue