PR c++/66561 - __builtin_LINE at al. should yield constant expressions

PR c++/66561 - __builtin_LINE at al. should yield constant expressions
PR c++/66639 - declare __func__, __FUNCTION__ & __PRETTY_FUNCTION__ constexpr

gcc/testsuite/ChangeLog:
2016-05-03  Martin Sebor  <msebor@redhat.com>

	PR c++/66561
	* c-c++-common/builtin_location.c: New test.
	* g++.dg/cpp1y/builtin_location.C: New test.

gcc/cp/ChangeLog:
2016-05-03  Martin Sebor  <msebor@redhat.com>

	PR c++/66561
	* tree.c (builtin_valid_in_constant_expr_p): Treat BUILT_IN_FILE,
	BUILT_IN_FUNCTION, and BUILT_IN_LINE as constant expressions.

gcc/ChangeLog:
2016-05-03  Martin Sebor  <msebor@redhat.com>

	PR c++/66561
	* builtins.c (fold_builtin_FILE): New function.
	(fold_builtin_FUNCTION, fold_builtin_LINE): New functions.
	(fold_builtin_0): Call them.
	* gimplify.c (gimplify_call_expr): Remove the handling of
	BUILT_IN_FILE, BUILT_IN_FUNCTION, and BUILT_IN_LINE.

	PR c++/66561
	* doc/extend.texi (Other Builtins): Update __builtin_FILE,
	__builtin_FUNCTION, and __builtin_LINE to reflect they yield
	constants.

	PR c++/66639
	* doc/extend.texi (Function Names as Strings): Update __func__,
	__FUNCTION__, __PRETTY_FUNCTION__ to reflect they evaluate to
	constants.

From-SVN: r235845
This commit is contained in:
Martin Sebor 2016-05-03 21:15:28 +00:00 committed by Martin Sebor
parent 9663f8f748
commit b25aad5fda
9 changed files with 366 additions and 42 deletions

View File

@ -1,3 +1,22 @@
2016-05-03 Martin Sebor <msebor@redhat.com>
PR c++/66561
* builtins.c (fold_builtin_FILE): New function.
(fold_builtin_FUNCTION, fold_builtin_LINE): New functions.
(fold_builtin_0): Call them.
* gimplify.c (gimplify_call_expr): Remove the handling of
BUILT_IN_FILE, BUILT_IN_FUNCTION, and BUILT_IN_LINE.
PR c++/66561
* doc/extend.texi (Other Builtins): Update __builtin_FILE,
__builtin_FUNCTION, and __builtin_LINE to reflect they yield
constants.
PR c++/66639
* doc/extend.texi (Function Names as Strings): Update __func__,
__FUNCTION__, __PRETTY_FUNCTION__ to reflect they evaluate to
constants.
2016-05-03 Jakub Jelinek <jakub@redhat.com>
Richard Biener <rguenther@suse.de>

View File

@ -8011,6 +8011,39 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
}
/* Fold a call to __builtin_FILE to a constant string. */
static inline tree
fold_builtin_FILE (location_t loc)
{
if (const char *fname = LOCATION_FILE (loc))
return build_string_literal (strlen (fname) + 1, fname);
return build_string_literal (1, "");
}
/* Fold a call to __builtin_FUNCTION to a constant string. */
static inline tree
fold_builtin_FUNCTION ()
{
if (current_function_decl)
{
const char *name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
return build_string_literal (strlen (name) + 1, name);
}
return build_string_literal (1, "");
}
/* Fold a call to __builtin_LINE to an integer constant. */
static inline tree
fold_builtin_LINE (location_t loc, tree type)
{
return build_int_cst (type, LOCATION_LINE (loc));
}
/* Fold a call to built-in function FNDECL with 0 arguments.
This function returns NULL_TREE if no simplification was possible. */
@ -8021,6 +8054,15 @@ fold_builtin_0 (location_t loc, tree fndecl)
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
switch (fcode)
{
case BUILT_IN_FILE:
return fold_builtin_FILE (loc);
case BUILT_IN_FUNCTION:
return fold_builtin_FUNCTION ();
case BUILT_IN_LINE:
return fold_builtin_LINE (loc, type);
CASE_FLT_FN (BUILT_IN_INF):
case BUILT_IN_INFD32:
case BUILT_IN_INFD64:

View File

@ -1,3 +1,9 @@
2016-05-03 Martin Sebor <msebor@redhat.com>
PR c++/66561
* tree.c (builtin_valid_in_constant_expr_p): Treat BUILT_IN_FILE,
BUILT_IN_FUNCTION, and BUILT_IN_LINE as constant expressions.
2016-05-03 Marek Polacek <polacek@redhat.com>
PR c/70859

View File

@ -346,10 +346,16 @@ builtin_valid_in_constant_expr_p (const_tree decl)
return false;
switch (DECL_FUNCTION_CODE (decl))
{
case BUILT_IN_CONSTANT_P:
case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
/* These always have constant results like the corresponding
macros/symbol. */
case BUILT_IN_FILE:
case BUILT_IN_FUNCTION:
case BUILT_IN_LINE:
/* These have constant results even if their operands are
non-constant. */
case BUILT_IN_CONSTANT_P:
case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
return true;
default:
return false;

View File

@ -8929,9 +8929,11 @@ This extension is not supported by GNU C++.
@cindex @code{__FUNCTION__} identifier
@cindex @code{__PRETTY_FUNCTION__} identifier
GCC provides three magic variables that hold the name of the current
function, as a string. The first of these is @code{__func__}, which
is part of the C99 standard:
GCC provides three magic constants that hold the name of the current
function as a string. In C++11 and later modes, all three are treated
as constant expressions and can be used in @code{constexpr} constexts.
The first of these constants is @code{__func__}, which is part of
the C99 standard:
The identifier @code{__func__} is implicitly declared by the translator
as if, immediately following the opening brace of each function
@ -8943,20 +8945,21 @@ static const char __func__[] = "function-name";
@noindent
appeared, where function-name is the name of the lexically-enclosing
function. This name is the unadorned name of the function.
function. This name is the unadorned name of the function. As an
extension, at file (or, in C++, namespace scope), @code{__func__}
evaluates to the empty string.
@code{__FUNCTION__} is another name for @code{__func__}, provided for
backward compatibility with old versions of GCC.
In C, @code{__PRETTY_FUNCTION__} is yet another name for
@code{__func__}. However, in C++, @code{__PRETTY_FUNCTION__} contains
the type signature of the function as well as its bare name. For
example, this program:
@code{__func__}, except that at file (or, in C++, namespace scope),
it evaluates to the string @code{"top level"}. In addition, in C++,
@code{__PRETTY_FUNCTION__} contains the signature of the function as
well as its bare name. For example, this program:
@smallexample
extern "C" @{
extern int printf (char *, ...);
@}
extern "C" int printf (const char *, ...);
class a @{
public:
@ -8985,7 +8988,7 @@ __PRETTY_FUNCTION__ = void a::sub(int)
@end smallexample
These identifiers are variables, not preprocessor macros, and may not
be used to initialize @code{char} arrays or be concatenated with other string
be used to initialize @code{char} arrays or be concatenated with string
literals.
@node Return Address
@ -11091,22 +11094,50 @@ means that the compiler can assume for @code{x}, set to @code{arg}, that
@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.
In a C++ default argument for a function @var{F}, it gets the line number of
the call to @var{F}.
This function is the equivalent of the preprocessor @code{__LINE__}
macro and returns a constant integer expression that evaluates to
the line number of the invocation of the built-in. When used as a C++
default argument for a function @var{F}, it returns the line number
of the call to @var{F}.
@end deftypefn
@deftypefn {Built-in Function} {const char *} __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.
This function is the equivalent of the @code{__FUNCTION__} symbol
and returns an address constant pointing to the name of the function
from which the built-in was invoked, or the empty string if
the invocation is not at function scope. When used as a C++ default
argument for a function @var{F}, it returns the name of @var{F}'s
caller or the empty string if the call was not made at function
scope.
@end deftypefn
@deftypefn {Built-in Function} {const char *} __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.
In a C++ default argument for a function @var{F}, it gets the file name of
the call to @var{F}.
This function is the equivalent of the preprocessor @code{__FILE__}
macro and returns an address constant pointing to the file name
containing the invocation of the built-in, or the empty string if
the invocation is not at function scope. When used as a C++ default
argument for a function @var{F}, it returns the file name of the call
to @var{F} or the empty string if the call was not made at function
scope.
For example, in the following, each call to function @code{foo} will
print a line similar to @code{"file.c:123: foo: message"} with the name
of the file and the line number of the @code{printf} call, the name of
the function @code{foo}, followed by the word @code{message}.
@smallexample
const char*
function (const char *func = __builtin_FUNCTION ())
@{
return func;
@}
void foo (void)
@{
printf ("%s:%i: %s: message\n", file (), line (), function ());
@}
@end smallexample
@end deftypefn
@deftypefn {Built-in Function} void __builtin___clear_cache (char *@var{begin}, char *@var{end})

View File

@ -2437,25 +2437,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
}
break;
}
case BUILT_IN_LINE:
{
*expr_p = build_int_cst (TREE_TYPE (*expr_p),
LOCATION_LINE (EXPR_LOCATION (*expr_p)));
return GS_OK;
}
case BUILT_IN_FILE:
{
const char *locfile = LOCATION_FILE (EXPR_LOCATION (*expr_p));
*expr_p = build_string_literal (strlen (locfile) + 1, locfile);
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:
;
}

View File

@ -1,3 +1,9 @@
2016-05-03 Martin Sebor <msebor@redhat.com>
PR c++/66561
* c-c++-common/builtin_location.c: New test.
* g++.dg/cpp1y/builtin_location.C: New test.
2016-05-03 Marek Polacek <polacek@redhat.com>
PR c/70859

View File

@ -0,0 +1,57 @@
/* PR c++/66561 - __builtin_LINE at al. should yield constant expressions */
/* { dg-do compile } */
#if __cplusplus >= 201103L
# define Assert(expr) static_assert ((expr), #expr)
#elif __STDC_VERSION__ >= 201112L
# define Assert(expr) _Static_assert ((expr), #expr)
#else
# define CONCAT(a, b) a ## b
# define CAT(a, b) CONCAT (a, b)
# define Assert(expr) typedef int CAT (Assert_, __LINE__) [1 - 2 * !(expr)]
#endif
/* Verify (in C) that __builtin_FILE() yields an address constant.
This test is ineffective in C++ where initializers of global
objects need not be constant expressions. */
const char* const file = __builtin_FILE ();
/* Verify (in C) that __builtin_FUNCTION() yields an address constant. */
const char* const function = __builtin_FUNCTION ();
/* Also verify that __builtin_constant_p() returns true for both. */
Assert (__builtin_constant_p (__builtin_FILE ()));
Assert (__builtin_constant_p (__builtin_FUNCTION ()));
/* Verify (in both C and C++ 11 and later) that both __builtin_FILE ()
and __builtin_FUNCTION() yield an address constant by making use
of a GCC extension that allows operands of arithmetic constant
expressions to be address constants. (Subtracting two literals
from one another is undefined in both C and C++ and should be
diagnosed. See c/70772.) */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
enum E0 {
e0 = __FILE__ - __FILE__,
e1 = __builtin_FILE () - __builtin_FILE (),
#if !__cplusplus || __cplusplus >= 201103L
/* Skip this test in C++ 98 where GCC rejects __FUNCTION__ in constant
expressions. */
e2 = __FUNCTION__ - __FUNCTION__,
e3 = __builtin_FUNCTION () - __builtin_FUNCTION ()
#endif
};
#pragma GCC diagnostic pop
/* Verify that __builtin_LINE () yields an integer constant expression. */
#line 13
int a [__builtin_LINE ()][__builtin_LINE ()];
enum F { f0 = __builtin_LINE () };
struct S { unsigned bitfield: __builtin_LINE (); } s;
Assert (__builtin_constant_p (__builtin_LINE ()));

View File

@ -0,0 +1,175 @@
// PR c++/66561 - __builtin_LINE at al. should yield constant expressions
// { dg-do compile { target c++11 } }
#define A(expr) static_assert ((expr), #expr)
#define FILE_1 "file_name.suffix"
#define FILE_2 "some_other_file_name.suffix"
#line 1 FILE_1
constexpr const char*
file1 ()
{
#if __cplusplus >= 201402L
// Do extra checking in C++ 14 and later.
constexpr const char *f1 = __FILE__;
constexpr const char *f2 = __builtin_FILE ();
A (0 == __builtin_strcmp (f1, f2));
return f1;
#else
// In C++ 11, a constexpr function body must consist of a single
// return statement and no declaratations.
return __builtin_FILE ();
#endif
}
#line 1 FILE_2
constexpr const char*
file2 ()
{
#if __cplusplus >= 201402L
constexpr const char *f1 = __FILE__;
constexpr const char *f2 = __builtin_FILE ();
A (0 == __builtin_strcmp (f1, f2));
return f1;
#else
return __builtin_FILE ();
#endif
}
#line 1 "bogus file name"
constexpr const char*
this_file (const char *fname = __builtin_FILE ())
{
return fname;
}
constexpr const char*
function ()
{
#if __cplusplus >= 201402L
constexpr const char *f1 = __FUNCTION__;
constexpr const char *f2 = __builtin_FUNCTION ();
A (0 == __builtin_strcmp (f1, f2));
return f1;
#else
return __builtin_FUNCTION ();
#endif
}
constexpr const char*
this_function (const char *func = __builtin_FUNCTION ())
{
return func;
}
constexpr int
line ()
{
#if __cplusplus >= 201402L
#line 123
constexpr int n1 = __LINE__;
constexpr int n2 = __builtin_LINE ();
A (123 == n1);
A (n1 + 1 == n2);
return n2;
#else
#line 123
// Newline.
return __builtin_LINE ();
#endif
}
constexpr int
this_line (int line = __builtin_LINE ())
{
return line;
}
// Exercise __builtin_FILE().
#line 1 "foobar"
constexpr const char* f1 = file1 ();
A (0 == __builtin_strcmp (f1, FILE_1));
#line 2 "foobar"
constexpr const char* f2 = file2 ();
A (0 == __builtin_strcmp (f2, FILE_2));
#define FILE_3 "this_file_name_right_here.this_suffix"
#line 1 FILE_3
constexpr const char* f3 = this_file ();
A (0 == __builtin_strcmp (f3, FILE_3));
#define FILE_4 "next_file_name.another_suffix"
#line 1 "foobar"
constexpr const char* f4 = this_file
(
#line 1 FILE_4
)
#line 1 "foobar"
;
A (0 == __builtin_strcmp (f4, FILE_4));
// Exercise __builtin_FUNCTION().
// Verify that __builtin_FUNCTION() returns the name of the function
// in which it is called.
constexpr const char* fun1 = function ();
A (0 == __builtin_strcmp (fun1, "function"));
// Verify that __builtin_FUNCTION() returns the empty string when
// it's invoked to set the default argument value in a function
// called at file scope.
constexpr const char* fun2 = this_function ();
A (0 == __builtin_strcmp (fun2, ""));
constexpr const char*
named_function ()
{
return this_function ();
}
constexpr const char* fun3 = named_function ();
A (0 == __builtin_strcmp (fun3, "named_function"));
// Exercise __builtin_LINE().
// Verify the line numbe returned by the built-in.
#line 4
constexpr int n1 = __builtin_LINE ();
A (n1 == 4);
// Verify the line number obtained by a constexpr function.
#line 5
constexpr int n2 = line ();
A (n2 == 124);
// Verify the line number determined by the default argument.
#line 6
constexpr int n3 = this_line ();
A (n3 == 6);
// Verify that the line number accounts for each of the calls.
#line 7
constexpr int n4 = this_line () + this_line ();
A (n4 == 14);
// Verify that the line number accounts for each of the calls when
// split over multiple lines.
#line 1
constexpr int n5 = this_line ()
#line 8
+ this_line ();
A (n5 == 9);
// Verify that the line number corresponds to the closing parenthesis
// of the function call.
#line 1
constexpr int n6 = this_line
(
#line 99
)
#line 1
;
A (n6 == 99);