aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-10-23 20:19:32 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-10-23 20:19:32 +0000
commite4851f26eb7be1f71f919bb5890da7e3583f727d (patch)
tree7caffec8839ce3c6091984f57c26b712485ef020
parent4cdad3151bfb2075c6bdbfe89fbb08f31a90a45b (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.td3
-rw-r--r--lib/Sema/Sema.cpp2
-rw-r--r--lib/Sema/SemaDecl.cpp11
-rw-r--r--test/Sema/warn-missing-variable-declarations.c36
-rw-r--r--test/Sema/warn-missing-variable-declarations.cpp39
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;
+}