+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>
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. */
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:
+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
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;
@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
@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:
@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
@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})
}
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:
;
}
+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
--- /dev/null
+/* 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 ()));
--- /dev/null
+// 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);