This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Abolish 'static' functions in local scope
- From: gkeating at apple dot com (Geoffrey Keating)
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 30 Aug 2004 15:13:41 -0700 (PDT)
- Subject: Abolish 'static' functions in local scope
GCC used to accept the following:
void foo() {
static void bar();
}
There are three problems with this:
1. There are three possible meanings for it:
A. This is a reference to a function foo() at the top level, which
is local to this translation unit.
B. This is a forward declaration of a nested function at this
level, which would be named something like "foo.1" in the
assembly; and that function can't access local variables of the
routine (which distinguishes it from being 'auto').
C. The 'static' should be ignored, making it a reference to a
function foo() at the top level which is visible across all
translation units.
I believe all three exist in real code. The last two exist in
GCC's testsuite. (A) exists in Apple's code base and
the Linux kernel.
2. None of these three meanings actually works completely in current
HEAD, or in 3.4; and the nature of the breakage is different in the
two releases.
3. This extension isn't documented. It's not even clear that it's
intentional. It is not used a lot; Apple's code base had only
about 13 projects out of hundreds.
So, I'm taking it out.
I'm making it an error, because trying to use (A) generates invalid
assembly, (C) is useless, and (B) is both dangerous and useless.
Bootstrapped & tested on powerpc-darwin.
--
- Geoffrey Keating <geoffk@apple.com>
===File ~/patches/gcc-staticlocalfunc.patch=================
2004-08-30 Geoffrey Keating <geoffk@apple.com>
PR 12738
PR 17205
Radar 3460526
Radar 3775729
* c-decl.c (grokdeclarator): Produce error for 'static' on local
function declaration.
Index: testsuite/ChangeLog
2004-08-30 Geoffrey Keating <geoffk@apple.com>
* gcc.dg/funcdef-storage-1.c: New.
* gcc.c-torture/compile/920625-2.c: Don't use 'static' to declare
an extern function in local scope.
* gcc.c-torture/execute/20010605-1.c: Don't use 'static inline' to
declare an 'auto inline' function in local scope.
* gcc.dg/20011130-1.c: Likewise.
* gcc.c-torture/execute/nest-stdar-1.c: Don't use 'static' to declare
an 'auto' function in local scope.
* gcc.dg/20021014-1.c: Likewise.
* gcc.dg/20030331-2.c: Likewise.
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.564
diff -u -p -u -p -r1.564 c-decl.c
--- c-decl.c 26 Aug 2004 21:30:15 -0000 1.564
+++ c-decl.c 30 Aug 2004 21:56:27 -0000
@@ -4659,26 +4659,29 @@ grokdeclarator (tree declarator, tree de
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- if (specbits & (1 << (int) RID_AUTO)
- && (pedantic || current_scope == file_scope))
- pedwarn ("invalid storage class for function `%s'", name);
- if (specbits & (1 << (int) RID_REGISTER))
+ if (specbits & (1 << (int) RID_REGISTER)
+ || specbits & (1 << (int) RID_THREAD))
error ("invalid storage class for function `%s'", name);
- if (specbits & (1 << (int) RID_THREAD))
- error ("invalid storage class for function `%s'", name);
- /* Function declaration not at file scope.
- Storage classes other than `extern' are not allowed
- and `extern' makes no difference. */
- if (current_scope != file_scope
- && (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE)))
- && pedantic)
- pedwarn ("invalid storage class for function `%s'", name);
+ else if (current_scope != file_scope)
+ {
+ /* Function declaration not at file scope. Storage
+ classes other than `extern' are not allowed, C99
+ 6.7.1p5, and `extern' makes no difference. However,
+ GCC allows 'auto', perhaps with 'inline', to support
+ nested functions. */
+ if (specbits & (1 << (int) RID_AUTO))
+ {
+ if (pedantic)
+ pedwarn ("invalid storage class for function `%s'", name);
+ }
+ if (specbits & (1 << (int) RID_STATIC))
+ error ("invalid storage class for function `%s'", name);
+ }
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_attr);
- DECL_LANG_SPECIFIC (decl)
- = GGC_CNEW (struct lang_decl);
+ DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
Index: testsuite/gcc.c-torture/compile/920625-2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/compile/920625-2.c,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 920625-2.c
--- testsuite/gcc.c-torture/compile/920625-2.c 16 Dec 1998 22:07:17 -0000 1.2
+++ testsuite/gcc.c-torture/compile/920625-2.c 30 Aug 2004 21:57:22 -0000
@@ -23,7 +23,7 @@ trashQueryResult(Widget w, Boolean delet
extern Cursor busy, left_ptr;
extern String cwd;
- static void freeReturnStruct(void);
+ extern void freeReturnStruct(void);
String rmstring;
int status;
XedwListReturnStruct *tmp;
@@ -58,7 +58,7 @@ copyQueryResult(Widget w, Boolean copy,
extern void destroy_button_dialog();
extern void changestate(Boolean);
extern Cursor busy, left_ptr;
- static void freeReturnStruct(void);
+ extern void freeReturnStruct(void);
int execute(String, String, String, Boolean);
extern String cwd;
String copystring;
Index: testsuite/gcc.c-torture/execute/20010605-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/20010605-1.c,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 20010605-1.c
--- testsuite/gcc.c-torture/execute/20010605-1.c 6 Jun 2001 03:08:21 -0000 1.2
+++ testsuite/gcc.c-torture/execute/20010605-1.c 30 Aug 2004 21:57:23 -0000
@@ -2,7 +2,7 @@ int main ()
{
int v = 42;
- static inline int fff (int x)
+ inline int fff (int x)
{
return x*10;
}
Index: testsuite/gcc.c-torture/execute/nest-stdar-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/nest-stdar-1.c,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 nest-stdar-1.c
--- testsuite/gcc.c-torture/execute/nest-stdar-1.c 16 Dec 1998 22:16:08 -0000 1.2
+++ testsuite/gcc.c-torture/execute/nest-stdar-1.c 30 Aug 2004 21:57:25 -0000
@@ -2,7 +2,7 @@
main ()
{
- static double f (int x, ...)
+ double f (int x, ...)
{
va_list args;
double a;
Index: testsuite/gcc.dg/20011130-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/20011130-1.c,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 20011130-1.c
--- testsuite/gcc.dg/20011130-1.c 3 Dec 2001 14:23:01 -0000 1.1
+++ testsuite/gcc.dg/20011130-1.c 30 Aug 2004 21:57:27 -0000
@@ -9,7 +9,7 @@
static int __attribute__((unused)) foo (int x)
{
- static inline int bar (int x)
+ inline int bar (int x)
{
int y;
y = x;
Index: testsuite/gcc.dg/20021014-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/20021014-1.c,v
retrieving revision 1.10
diff -u -p -u -p -r1.10 20021014-1.c
--- testsuite/gcc.dg/20021014-1.c 21 Feb 2004 02:58:24 -0000 1.10
+++ testsuite/gcc.dg/20021014-1.c 30 Aug 2004 21:57:28 -0000
@@ -10,7 +10,7 @@ extern void exit (int);
int foo (void)
{
- static int bar (int x)
+ int bar (int x)
{
return x + 3;
}
Index: testsuite/gcc.dg/20030331-2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/20030331-2.c,v
retrieving revision 1.3
diff -u -p -u -p -r1.3 20030331-2.c
--- testsuite/gcc.dg/20030331-2.c 3 Aug 2004 08:22:21 -0000 1.3
+++ testsuite/gcc.dg/20030331-2.c 30 Aug 2004 21:57:28 -0000
@@ -6,7 +6,7 @@ int foo() {
int yd;
float in[1][yd];
- static void bar() {
+ void bar() {
printf("%p\n",in[0]);
}
}
Index: testsuite/gcc.dg/funcdef-storage-1.c
===================================================================
RCS file: testsuite/gcc.dg/funcdef-storage-1.c
diff -N testsuite/gcc.dg/funcdef-storage-1.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/funcdef-storage-1.c 30 Aug 2004 21:57:30 -0000
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+void
+flarm(void)
+{
+ static void foo(); /* { dg-error "invalid storage class" } */
+
+ foo();
+}
+
+static void
+foo(void)
+{
+}
============================================================