On Thu, 13 Sep 2012, Diego Novillo wrote: > > Thanks for the patch! > > > On 2012-09-13 08:46 , Richard Guenther wrote: > > > Index: gcc/testsuite/g++.dg/ext/builtin-location.C > > =================================================================== > > *** /dev/null 1970-01-01 00:00:00.000000000 +0000 > > --- gcc/testsuite/g++.dg/ext/builtin-location.C 2012-09-13 > > 14:27:34.868103539 +0200 > > *************** > > *** 0 **** > > --- 1,20 ---- > > + // { dg-do link } > > + > > + #include <cstdio> > > + > > + void bar (const char *file = __builtin_FILE (), > > + const char *function = __builtin_FUNCTION (), > > + int line = __builtin_LINE ()) > > + { > > + printf ("%s (%s): %d\n", file, function, line); > > Shouldn't this test that it is getting the file, function and line for the > call to bar() inside of main? > > Maybe something like: > > const char *FILE; > const char *FN; > int LINE; > > void bar (const char *file = __builtin_FILE (), > const char *function = __builtin_FUNCTION (), > int line = __builtin_LINE ()) > { > FILE = file; > FN = function; > LINE = line; > } > > int main() > { > bar(); > if (LINE != __LINE__ - 1) > return 1; > if (strcmp (function, "main") != 0) > return 1; > if (strcmp (file, "builtin-location.C") != 0) > return 1; > return 0; > }
Indeed - like the following, bootstrapped / tested on x86_64-unknown-linux-gnu, applied. Richard. 2012-09-14 Richard Guenther <rguent...@suse.de> * builtin-types.def (BT_FN_CONST_STRING): Add. * builtins.def (BUILT_IN_FILE, BUILT_IN_FUNCTION, BUILT_IN_LINE): New builtins. * gimplify.c (gimplify_call_expr): Expand them. * doc/extend.texi (__builtin_LINE, __builtin_FUNCTION, __builtin_FILE): Document. * g++.dg/torture/builtin-location.C: New testcase. Index: gcc/builtin-types.def =================================================================== *** gcc/builtin-types.def.orig 2012-09-14 10:29:09.000000000 +0200 --- gcc/builtin-types.def 2012-09-14 10:36:56.980591201 +0200 *************** DEF_POINTER_TYPE (BT_PTR_PTR, BT_PTR) *** 140,145 **** --- 140,146 ---- DEF_FUNCTION_TYPE_0 (BT_FN_VOID, BT_VOID) DEF_FUNCTION_TYPE_0 (BT_FN_BOOL, BT_BOOL) DEF_FUNCTION_TYPE_0 (BT_FN_PTR, BT_PTR) + DEF_FUNCTION_TYPE_0 (BT_FN_CONST_STRING, BT_CONST_STRING) DEF_FUNCTION_TYPE_0 (BT_FN_PID, BT_PID) DEF_FUNCTION_TYPE_0 (BT_FN_INT, BT_INT) DEF_FUNCTION_TYPE_0 (BT_FN_UINT, BT_UINT) Index: gcc/builtins.def =================================================================== *** gcc/builtins.def.orig 2012-09-14 10:29:09.000000000 +0200 --- gcc/builtins.def 2012-09-14 10:36:56.980591201 +0200 *************** DEF_BUILTIN_STUB (BUILT_IN_EH_POINTER, " *** 801,806 **** --- 801,811 ---- DEF_BUILTIN_STUB (BUILT_IN_EH_FILTER, "__builtin_eh_filter") DEF_BUILTIN_STUB (BUILT_IN_EH_COPY_VALUES, "__builtin_eh_copy_values") + /* __FILE__, __LINE__, __FUNCTION__ as builtins. */ + DEF_GCC_BUILTIN (BUILT_IN_FILE, "FILE", BT_FN_CONST_STRING, ATTR_NOTHROW_LEAF_LIST) + DEF_GCC_BUILTIN (BUILT_IN_FUNCTION, "FUNCTION", BT_FN_CONST_STRING, ATTR_NOTHROW_LEAF_LIST) + DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST) + /* Synchronization Primitives. */ #include "sync-builtins.def" Index: gcc/gimplify.c =================================================================== *** gcc/gimplify.c.orig 2012-09-14 10:29:09.000000000 +0200 --- gcc/gimplify.c 2012-09-14 10:36:56.983591201 +0200 *************** gimplify_call_expr (tree *expr_p, gimple *** 2498,2518 **** transform all calls in the same manner as the expanders do, but we do transform most of them. */ fndecl = get_callee_fndecl (*expr_p); ! if (fndecl && DECL_BUILT_IN (fndecl)) ! { ! tree new_tree = fold_call_expr (input_location, *expr_p, !want_value); ! ! if (new_tree && new_tree != *expr_p) ! { ! /* There was a transformation of this call which computes the ! same value, but in a more efficient way. Return and try ! again. */ ! *expr_p = new_tree; ! return GS_OK; ! } ! ! if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL ! && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_VA_START) { builtin_va_start_p = TRUE; if (call_expr_nargs (*expr_p) < 2) --- 2498,2508 ---- transform all calls in the same manner as the expanders do, but we do transform most of them. */ fndecl = get_callee_fndecl (*expr_p); ! if (fndecl ! && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) ! switch (DECL_FUNCTION_CODE (fndecl)) ! { ! case BUILT_IN_VA_START: { builtin_va_start_p = TRUE; if (call_expr_nargs (*expr_p) < 2) *************** gimplify_call_expr (tree *expr_p, gimple *** 2527,2532 **** --- 2517,2556 ---- *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p)); return GS_OK; } + break; + } + case BUILT_IN_LINE: + { + expanded_location loc = expand_location (EXPR_LOCATION (*expr_p)); + *expr_p = build_int_cst (TREE_TYPE (*expr_p), loc.line); + return GS_OK; + } + case BUILT_IN_FILE: + { + expanded_location loc = expand_location (EXPR_LOCATION (*expr_p)); + *expr_p = build_string_literal (strlen (loc.file) + 1, loc.file); + return GS_OK; + } + case BUILT_IN_FUNCTION: + { + const char *function; + function = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); + *expr_p = build_string_literal (strlen (function) + 1, function); + return GS_OK; + } + default: + ; + } + if (fndecl && DECL_BUILT_IN (fndecl)) + { + tree new_tree = fold_call_expr (input_location, *expr_p, !want_value); + if (new_tree && new_tree != *expr_p) + { + /* There was a transformation of this call which computes the + same value, but in a more efficient way. Return and try + again. */ + *expr_p = new_tree; + return GS_OK; } } Index: gcc/doc/extend.texi =================================================================== *** gcc/doc/extend.texi.orig 2012-09-14 10:29:09.000000000 +0200 --- gcc/doc/extend.texi 2012-09-14 10:36:56.985591201 +0200 *************** means that the compiler can assume for x *** 8324,8329 **** --- 8324,8344 ---- (char *) x - 8 is 32 byte aligned. @end deftypefn + @deftypefn {Built-in Function} int __builtin_LINE () + This function is the equivalent to the preprocessor @code{__LINE__} + macro and returns the line number of the invocation of the built-in. + @end deftypefn + + @deftypefn {Built-in Function} int __builtin_FUNCTION () + This function is the equivalent to the preprocessor @code{__FUNCTION__} + macro and returns the function name the invocation of the built-in is in. + @end deftypefn + + @deftypefn {Built-in Function} int __builtin_FILE () + This function is the equivalent to the preprocessor @code{__FILE__} + macro and returns the file name the invocation of the built-in is in. + @end deftypefn + @deftypefn {Built-in Function} void __builtin___clear_cache (char *@var{begin}, char *@var{end}) This function is used to flush the processor's instruction cache for the region of memory between @var{begin} inclusive and @var{end} Index: gcc/testsuite/g++.dg/torture/builtin-location.C =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/g++.dg/torture/builtin-location.C 2012-09-14 10:42:39.465579370 +0200 *************** *** 0 **** --- 1,31 ---- + // { dg-do run } + + #include <cstring> + + const char *gfile; + const char *gfn; + int gline; + + void bar (const char *file = __builtin_FILE (), + const char *function = __builtin_FUNCTION (), + int line = __builtin_LINE ()) + { + gfile = file; + gfn = function; + gline = line; + } + + extern "C" void abort (void); + + int main() + { + int here; + bar (); here = __LINE__; + if (std::strcmp (gfn, __FUNCTION__) != 0) + abort (); + if (std::strcmp (gfile, __FILE__) != 0) + abort (); + if (gline != here) + abort (); + return 0; + }