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 <[email protected]>
* 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;
+ }