diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-10-23 20:19:32 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-10-23 20:19:32 +0000 |
commit | e4851f26eb7be1f71f919bb5890da7e3583f727d (patch) | |
tree | 7caffec8839ce3c6091984f57c26b712485ef020 | |
parent | 4cdad3151bfb2075c6bdbfe89fbb08f31a90a45b (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166498 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 11 | ||||
-rw-r--r-- | test/Sema/warn-missing-variable-declarations.c | 36 | ||||
-rw-r--r-- | test/Sema/warn-missing-variable-declarations.cpp | 39 |
5 files changed, 91 insertions, 0 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index efa974839a..56cb206042 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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 " diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index eef5a2694a..c7d378f1ac 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -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); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 162c50b7fe..19442b98c1 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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; diff --git a/test/Sema/warn-missing-variable-declarations.c b/test/Sema/warn-missing-variable-declarations.c new file mode 100644 index 0000000000..cf911c2a89 --- /dev/null +++ b/test/Sema/warn-missing-variable-declarations.c @@ -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; diff --git a/test/Sema/warn-missing-variable-declarations.cpp b/test/Sema/warn-missing-variable-declarations.cpp new file mode 100644 index 0000000000..77c4c01501 --- /dev/null +++ b/test/Sema/warn-missing-variable-declarations.cpp @@ -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; +} |