This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

c: __FUNCTION__ etc.


How about this for a patch, then?  It makes the 3 separate, and adds 5
new testcases, four along the lines of your __func__ tests.

[What's to stop a clever linker from fixing the strings to be identical
again?]

Neil.

	* c-common.c: Update comments.
	* c-decl.c: Update comments.
	* c-parse.in: Update.
	(yylexname): Handle __FUNC__ and __PRETTY_FUNC__ similarly
	to __func__.
doc:
	* extend.texi: Update.
testsuite:
	* gcc.dg/FUNCTN-1.c, gcc.dg/FUNCTN-2.c, gcc.dg/FUNCTN-3.c,
	gcc.dg/FUNCTN-4.c, gcc.dg/FUNCTN-5.c: New tests.

============================================================
Index: gcc/c-common.c
--- gcc/c-common.c	2001/12/05 23:19:54	1.279
+++ gcc/c-common.c	2001/12/10 00:16:02
@@ -234,7 +234,7 @@ struct fname_var_t
   const int pretty;	/* How pretty is it? */
 };
 
-/* The three ways of getting then name of the current function.  */
+/* The three ways of getting the name of the current function.  */
 
 const struct fname_var_t fname_vars[] =
 {
============================================================
Index: gcc/c-decl.c
--- gcc/c-decl.c	2001/12/07 22:19:47	1.282
+++ gcc/c-decl.c	2001/12/10 00:16:19
@@ -3119,13 +3119,12 @@ c_init_decl_processing ()
   ggc_add_tree_root (&static_dtors, 1);
 }
 
-/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
-   decl, NAME is the initialization string and TYPE_DEP indicates whether
-   NAME depended on the type of the function.  As we don't yet implement
-   delayed emission of static data, we mark the decl as emitted
-   so it is not placed in the output.  Anything using it must therefore pull
-   out the STRING_CST initializer directly.  This does mean that these names
-   are string merging candidates, which is wrong for C99's __func__.  FIXME.  */
+/* Create the VAR_DECL for __func__, __FUNCTION__ etc.  ID is the name
+   to give the decl and TYPE_DEP indicates whether the resulting
+   string depends on the type of the function.  As we don't yet
+   implement delayed emission of static data, we mark the decl as
+   emitted so it is not placed in the output.  Anything using it must
+   therefore pull out the STRING_CST initializer directly.  */
 
 static tree
 c_make_fname_decl (id, type_dep)
============================================================
Index: gcc/c-parse.in
--- gcc/c-parse.in	2001/12/08 22:34:54	1.120
+++ gcc/c-parse.in	2001/12/10 00:16:26
@@ -113,8 +113,8 @@ end ifobjc
 %token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P
 %token PTR_VALUE PTR_BASE PTR_EXTENT
 
-/* function name can be a string const or a var decl. */
-%token STRING_FUNC_NAME VAR_FUNC_NAME
+/* __func__, __FUNCTION__ or __PRETTY_FUNCTION__.  */
+%token VAR_FUNC_NAME
 
 /* Add precedence rules to solve dangling else s/r conflict */
 %nonassoc IF
@@ -3415,8 +3415,8 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_CHOOSE_EXPR */			CHOOSE_EXPR,
   /* RID_TYPES_COMPATIBLE_P */		TYPES_COMPATIBLE_P,
 
-  /* RID_FUNCTION_NAME */		STRING_FUNC_NAME,
-  /* RID_PRETTY_FUNCTION_NAME */	STRING_FUNC_NAME,
+  /* RID_FUNCTION_NAME */		VAR_FUNC_NAME,
+  /* RID_PRETTY_FUNCTION_NAME */	VAR_FUNC_NAME,
   /* RID_C99_FUNCTION_NAME */		VAR_FUNC_NAME,
 
   /* C++ */
@@ -3565,22 +3565,9 @@ ifobjc
 	  && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
 end ifobjc
       {
-	int yycode = rid_to_yy[(int) rid_code];
-	if (yycode == STRING_FUNC_NAME)
-	  {
-	    /* __FUNCTION__ and __PRETTY_FUNCTION__ get converted
-	       to string constants.  */
-	    const char *name = fname_string (rid_code);
-	  
-	    yylval.ttype
-	      = combine_strings (build_string (strlen (name) + 1, name));
-	    last_token = CPP_STRING;  /* so yyerror won't choke */
-	    return STRING;
-	  }
-      
 	/* Return the canonical spelling for this keyword.  */
 	yylval.ttype = ridpointers[(int) rid_code];
-	return yycode;
+	return rid_to_yy[(int) rid_code];
       }
     }
 
============================================================
Index: gcc/doc/extend.texi
--- gcc/doc/extend.texi	2001/12/08 22:34:54	1.44
+++ gcc/doc/extend.texi	2001/12/10 00:16:45
@@ -4066,14 +4066,34 @@ This extension is not supported by GNU C
 @cindex @code{__PRETTY_FUNCTION__} identifier
 @cindex @code{__func__} identifier
 
-GCC predefines two magic identifiers to hold the name of the current
-function.  The identifier @code{__FUNCTION__} holds the name of the function
-as it appears in the source.  The identifier @code{__PRETTY_FUNCTION__}
-holds the name of the function pretty printed in a language specific
-fashion.
+GCC supports the magic word @code{__func__}, defined by the ISO
+standard C99:
 
-These names are always the same in a C function, but in a C++ function
-they may be different.  For example, this program:
+@display
+The identifier @code{__func__} is implicitly declared by the translator
+as if, immediately following the opening brace of each function
+definition, the declaration
+
+@smallexample
+static const char __func__[] = "function-name";
+@end smallexample
+
+appeared, where function-name is the name of the lexically-enclosing
+function.  This name is the unadorned name of the function.
+@end display
+
+By this definition, @code{__func__} is a variable, not a string literal.
+In particular, @code{__func__} does not catenate with other string
+literals.
+
+Further, GCC predefines two other special variables to hold the name
+of the current function.  The variable @code{__FUNCTION__} holds the
+name of the function, exactly as described above for @code{__func__}.
+The variable @code{__PRETTY_FUNCTION__} holds the name of the function
+pretty printed in a language specific fashion.
+
+These two names are always the same in a given C function, but in a
+C++ function they may be different.  For example, this program:
 
 @smallexample
 extern "C" @{
@@ -4106,42 +4126,20 @@ __FUNCTION__ = sub
 __PRETTY_FUNCTION__ = int  a::sub (int)
 @end smallexample
 
-The compiler automagically replaces the identifiers with a string
-literal containing the appropriate name.  Thus, they are neither
+Since the compiler creates them as variables, they are neither
 preprocessor macros, like @code{__FILE__} and @code{__LINE__}, nor
-variables.  This means that they catenate with other string literals, and
-that they can be used to initialize char arrays.  For example
-
-@smallexample
-char here[] = "Function " __FUNCTION__ " in " __FILE__;
-@end smallexample
-
-On the other hand, @samp{#ifdef __FUNCTION__} does not have any special
-meaning inside a function, since the preprocessor does not do anything
-special with the identifier @code{__FUNCTION__}.
-
-GCC also supports the magic word @code{__func__}, defined by the
-ISO standard C99:
-
-@display
-The identifier @code{__func__} is implicitly declared by the translator
-as if, immediately following the opening brace of each function
-definition, the declaration
-
-@smallexample
-static const char __func__[] = "function-name";
-@end smallexample
-
-appeared, where function-name is the name of the lexically-enclosing
-function.  This name is the unadorned name of the function.
-@end display
-
-By this definition, @code{__func__} is a variable, not a string literal.
-In particular, @code{__func__} does not catenate with other string
-literals.
+string literals.
 
-In @code{C++}, @code{__FUNCTION__} and @code{__PRETTY_FUNCTION__} are
-variables, declared in the same way as @code{__func__}.
+This means that they do not catenate with other string literals, that
+they cannot be used to initialize char arrays, and that @samp{#ifdef
+__FUNCTION__} does not have any special meaning, since the
+preprocessor does not do anything special with the identifier
+@code{__FUNCTION__}.
+
+In any given function, @code{__func__}, @code{__FUNCTION__} and
+@code{__PRETTY_FUNCTION__} all refer to distinct character arrays,
+even if the contents of those arrays are the same.  Further, they are
+also distinct from all other string literals in the program.
 
 @node Return Address
 @section Getting the Return or Frame Address of a Function
============================================================
Index: gcc/testsuite/gcc.dg/FUNCTN-1.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ gcc/testsuite/gcc.dg/FUNCTN-1.c	Sun Dec  9 16:16:45 2001
@@ -0,0 +1,25 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+/* Test for __FUNCTION__ and __PRETTY_FUNCTION__.  */
+
+/* Origin: Neil Booth, 9 Dec 2001.  Unashamed plagiarism of c99-func-1.c.  */
+
+/* { dg-do run } */
+
+extern void abort (void);
+extern int strcmp (const char *, const char *);
+extern void exit (int);
+
+int
+main (void)
+{
+  if (strcmp (__FUNCTION__, "main")
+      || sizeof (__FUNCTION__) != 5)
+    abort ();
+
+  if (strcmp (__PRETTY_FUNCTION__, "main")
+      || sizeof (__PRETTY_FUNCTION__) != 5)
+    abort ();
+
+  exit (0);
+}
============================================================
Index: gcc/testsuite/gcc.dg/FUNCTN-2.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ gcc/testsuite/gcc.dg/FUNCTN-2.c	Sun Dec  9 16:16:45 2001
@@ -0,0 +1,19 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+/* Test for __FUNCTION__ and __PRETTY_FUNCTION__.  */
+
+/* Origin: Neil Booth, 9 Dec 2001.  Unashamed plagiarism of c99-func-2.c.  */
+
+/* { dg-do compile } */
+
+void
+foo (void)
+{
+  __FUNCTION__ "foo"; /* { dg-error "parse error" "before string" } */
+}
+
+void
+bar (void)
+{
+  __PRETTY_FUNCTION__ "foo"; /* { dg-error "parse error" "before string" } */
+}
============================================================
Index: gcc/testsuite/gcc.dg/FUNCTN-3.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ gcc/testsuite/gcc.dg/FUNCTN-3.c	Sun Dec  9 16:16:45 2001
@@ -0,0 +1,26 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+/* Test for __FUNCTION__ and __PRETTY_FUNCTION__.  */
+
+/* Origin: Neil Booth, 9 Dec 2001.  */
+
+/* { dg-do run } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+  /* All of __FUNCTION__ and __PRETTY_FUNCTION__ should be distinct
+     from each other, and from any other string literal.  */
+  if ("main" == __FUNCTION__
+      || "main" == __PRETTY_FUNCTION__
+      || __FUNCTION__ == __PRETTY_FUNCTION__
+      || __func__ == __FUNCTION__
+      || __func__ == __PRETTY_FUNCTION__)
+    abort ();
+
+  exit (0);
+}
============================================================
Index: gcc/testsuite/gcc.dg/FUNCTN-4.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ gcc/testsuite/gcc.dg/FUNCTN-4.c	Sun Dec  9 16:16:45 2001
@@ -0,0 +1,16 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+/* Test for __FUNCTION__ and __PRETTY_FUNCTION__ being of type const
+   char [].  */
+
+/* Origin: Neil Booth, 9 Dec 2001.  Unashamed plagiarism of c99-func-4.c.  */
+
+/* { dg-do compile } */
+/* { dg-options -pedantic-errors } */
+
+void
+foo (void)
+{
+  char *p = __FUNCTION__; /* { dg-error "discards" "pointer to const" } */
+  char *q = __PRETTY_FUNCTION__; /* { dg-error "discards" "pointer to const" } */
+}
============================================================
Index: gcc/testsuite/gcc.dg/FUNCTN-5.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ gcc/testsuite/gcc.dg/FUNCTN-5.c	Sun Dec  9 16:16:45 2001
@@ -0,0 +1,21 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+/* Test of __FUNCTION__ and __PRETTY_FUNCTION__.  */
+
+/* Origin: Neil Booth, 9 Dec 2001.  */
+
+/* { dg-do run } */
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+  /* Test we don't somehow create separate decls for re-use.  */
+  if (__FUNCTION__ != __FUNCTION__
+      || __PRETTY_FUNCTION__ != __PRETTY_FUNCTION__)
+    abort ();
+
+  exit (0);
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]