gcc/ChangeLog:

2013-07-23  Florian Weimer  <fweimer@redhat.com>

	* doc/invoke.texi (Warning Options): Document -Wstatic-local.

c-family/ChangeLog:

2013-07-23  Florian Weimer  <fweimer@redhat.com>

	* c.opt (Wstatic-local): Add option -Wstatic-local.

c/ChangeLog:

2013-07-23  Florian Weimer  <fweimer@redhat.com>

	* c-decl.c (pushdecl): Implement -Wstatic-local.

cp/ChangeLog:

2013-07-23  Florian Weimer  <fweimer@redhat.com>

	* decl.c (cp_finish_decl): Implement -Wstatic-local.

testsuite/ChangeLog:

2013-07-23  Florian Weimer  <fweimer@redhat.com>

	* c-c++-common/Wstatic-local.c: New.
	* g++.dg/warn/Wstatic-local-1.C: New.
	* g++.dg/warn/Wstatic-local-2.C: New.

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 9690a08..7b9f3a2 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -745,6 +745,10 @@ Wmaybe-uninitialized
 C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall)
 ;
 
+Wstatic-local
+C ObjC C++ ObjC++ Warning Var(warn_static_local)
+Warn about static local variables
+
 Wunknown-pragmas
 C ObjC C++ ObjC++ Warning Var(warn_unknown_pragmas) LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0)
 Warn about unrecognized pragmas
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index f7ae648..9c718b5 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -2608,6 +2608,14 @@ pushdecl (tree x)
 	  || DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
     DECL_CONTEXT (x) = current_function_decl;
 
+  /* Optionally warn about non-const static variables declared inside
+     functions. */
+  if (current_function_decl && warn_static_local
+      && TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
+      && !TREE_READONLY (x))
+    warning_at (DECL_SOURCE_LOCATION (x), OPT_Wstatic_local,
+		"local variable declared static, but not const");
+
   /* Anonymous decls are just inserted in the scope.  */
   if (!name)
     {
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6fe4fed..1cd3726 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6387,6 +6387,14 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 	   non local class. Record the types it uses
 	   so that we can decide later to emit debug info for them.  */
 	record_types_used_by_current_var_decl (decl);
+
+      /* Optionally warn about static local variables which are
+	 not const. */
+      if (warn_static_local && TREE_STATIC (decl)
+	  && DECL_FUNCTION_SCOPE_P (decl)
+	  && !TREE_READONLY (decl) && TREE_CODE (type) != REFERENCE_TYPE)
+	warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wstatic_local,
+		    "local variable declared static, but not const");
     }
   else if (TREE_CODE (decl) == FIELD_DECL
 	   && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 3df4662..df94214 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -4393,6 +4393,13 @@ programs.
 Warn for variables that might be changed by @samp{longjmp} or
 @samp{vfork}.  This warning is also enabled by @option{-Wextra}.
 
+@item -Wstatic-local
+@opindex Wstatic-local
+@opindex Wno-static-local
+Warn for variables declared inside functions which are static, but not
+declared const.  These local variables represent potential thread
+safety hazards.
+
 @item -Wconditionally-supported @r{(C++ and Objective-C++ only)}
 @opindex Wconditionally-supported
 @opindex Wno-conditionally-supported
diff --git a/gcc/testsuite/c-c++-common/Wstatic-local.c b/gcc/testsuite/c-c++-common/Wstatic-local.c
new file mode 100644
index 0000000..a900569
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wstatic-local.c
@@ -0,0 +1,26 @@
+/* Test for -Wstatic-local */
+
+/* { dg-do compile } */
+/* { dg-options "-Wstatic-local" } */
+
+int a;
+static int b;
+const int c = 1;
+static const int d = 2;
+
+void
+g (void)
+{
+  static int v; /* { dg-warning "local variable declared static" } */
+  static const int v1 = 3;
+  static int *v2 = &v; /* { dg-warning "local variable declared static" } */
+  static const int *v3 = &v1; /* { dg-warning "local variable declared static" } */
+  static int *const v4 = &v;
+  static const char *w1 = "string"; /* { dg-warning "local variable declared static" } */
+  static const char *const w2 = "string";
+  static const char *x[] = {"string", 0};  /* { dg-warning "local variable declared static" } */
+  static const char *const x1[] = {"string", 0};
+
+  int z1;
+  const int z2 = 1;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wstatic-local-1.C b/gcc/testsuite/g++.dg/warn/Wstatic-local-1.C
new file mode 100644
index 0000000..bf6b965
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wstatic-local-1.C
@@ -0,0 +1,27 @@
+// Test -Wstatic-local.  Also see c-c++-common/Wstatic-local.c.
+
+// { dg-do compile }
+// { dg-options "-Wstatic-local" }
+
+template <class T> void
+g1()
+{
+  static T a = T(); // { dg-warning "local variable declared static" }
+  static const T b = a;
+}
+
+template <class T> void
+g2()
+{
+  static T a = T();
+  static const T b = a;
+}
+
+void
+h()
+{
+  g1<int>();
+  g2<const int>();
+  static int a = 5; // { dg-warning "local variable declared static" }
+  static int &b = a;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wstatic-local-2.C b/gcc/testsuite/g++.dg/warn/Wstatic-local-2.C
new file mode 100644
index 0000000..6f8b2c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wstatic-local-2.C
@@ -0,0 +1,28 @@
+// Test -Wstatic-local.  Also see c-c++-common/Wstatic-local.c.
+
+// { dg-do compile }
+// { dg-options "-std=c++11 -Wstatic-local" }
+
+static constexpr int a = 1;
+
+template <class T> void
+g1()
+{
+  static constexpr T a = T();
+  static constexpr T b = a;
+}
+
+template <class T> void
+g2()
+{
+  static constexpr T a = T();
+  static constexpr T b = a;
+}
+
+void
+h()
+{
+  g1<int>();
+  static constexpr int a = 5;
+  static int b = a; // { dg-warning "local variable declared static" }
+}

