From ddd0d18c9c07025d578f445dc9a3544020861197 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 1 Nov 2018 10:19:31 +0100 Subject: [PATCH] Make __PRETTY_FUNCTION__-like functions mergeable string csts (PR c++/64266). 2018-11-01 Martin Liska Jason Merrill PR c++/64266 PR bootstrap/70422 PR ipa/81277 * cp-tree.h (DECL_FNAME_P): New macro. * decl.c (cp_make_fname_decl): Set DECL_DECLARED_CONSTEXPR_P, DECL_VALUE_EXPR, DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P. (cp_finish_decl): * lambda.c (is_capture_proxy): Use DECL_FNAME_P. * pt.c (tsubst_expr): Handle DECL_PRETTY_FUNCTION_P. 2018-11-01 Martin Liska Jason Merrill PR c++/64266 PR bootstrap/70422 PR ipa/81277 * g++.dg/cpp0x/constexpr-__func__2.C: Make it a compilation test. * g++.old-deja/g++.ext/pretty4.C: Remove as the run-time assumptions are not longer valid. Co-Authored-By: Jason Merrill From-SVN: r265711 --- gcc/cp/ChangeLog | 13 +++ gcc/cp/cp-tree.h | 8 ++ gcc/cp/decl.c | 25 ++++-- gcc/cp/lambda.c | 1 + gcc/cp/pt.c | 16 ++-- gcc/testsuite/ChangeLog | 11 +++ .../g++.dg/cpp0x/constexpr-__func__2.C | 7 +- gcc/testsuite/g++.old-deja/g++.ext/pretty4.C | 85 ------------------- 8 files changed, 60 insertions(+), 106 deletions(-) delete mode 100644 gcc/testsuite/g++.old-deja/g++.ext/pretty4.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8e586a1f514..6d483455922 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2018-11-01 Martin Liska + Jason Merrill + + PR c++/64266 + PR bootstrap/70422 + PR ipa/81277 + * cp-tree.h (DECL_FNAME_P): New macro. + * decl.c (cp_make_fname_decl): Set DECL_DECLARED_CONSTEXPR_P, + DECL_VALUE_EXPR, DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P. + (cp_finish_decl): + * lambda.c (is_capture_proxy): Use DECL_FNAME_P. + * pt.c (tsubst_expr): Handle DECL_PRETTY_FUNCTION_P. + 2018-10-31 Nathan Sidwell * cp-tree.h (OVL_DEDUP_P): New. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 03e88838cbe..42449f10a48 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3132,6 +3132,14 @@ struct GTY(()) lang_decl { (DECL_NAME (NODE) \ && id_equal (DECL_NAME (NODE), "__PRETTY_FUNCTION__")) +/* For a DECL, true if it is __func__ or similar. */ +#define DECL_FNAME_P(NODE) \ + (VAR_P (NODE) && DECL_NAME (NODE) && DECL_ARTIFICIAL (NODE) \ + && DECL_HAS_VALUE_EXPR_P (NODE) \ + && (id_equal (DECL_NAME (NODE), "__PRETTY_FUNCTION__") \ + || id_equal (DECL_NAME (NODE), "__FUNCTION__") \ + || id_equal (DECL_NAME (NODE), "__func__"))) + /* Nonzero if the variable was declared to be thread-local. We need a special C++ version of this test because the middle-end DECL_THREAD_LOCAL_P uses the symtab, so we can't use it for diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 11320b65e71..1cea5262b62 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4465,7 +4465,7 @@ cp_fname_init (const char* name, tree *type_p) static tree cp_make_fname_decl (location_t loc, tree id, int type_dep) { - const char *const name = (type_dep && processing_template_decl + const char *const name = (type_dep && in_template_function () ? NULL : fname_as_string (type_dep)); tree type; tree init = cp_fname_init (name, &type); @@ -4474,23 +4474,35 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep) if (name) free (CONST_CAST (char *, name)); - TREE_STATIC (decl) = 1; + /* As we're using pushdecl_with_scope, we must set the context. */ + DECL_CONTEXT (decl) = current_function_decl; + TREE_READONLY (decl) = 1; DECL_ARTIFICIAL (decl) = 1; + DECL_DECLARED_CONSTEXPR_P (decl) = 1; + TREE_STATIC (decl) = 1; TREE_USED (decl) = 1; + if (init) + { + SET_DECL_VALUE_EXPR (decl, init); + DECL_HAS_VALUE_EXPR_P (decl) = 1; + /* For decl_constant_var_p. */ + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1; + } + if (current_function_decl) { DECL_CONTEXT (decl) = current_function_decl; decl = pushdecl_outermost_localscope (decl); - cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE, - LOOKUP_ONLYCONVERTING); + if (decl != error_mark_node) + add_decl_expr (decl); } else { DECL_THIS_STATIC (decl) = true; - pushdecl_top_level_and_finish (decl, init); + pushdecl_top_level_and_finish (decl, NULL_TREE); } return decl; @@ -7052,8 +7064,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, init = NULL_TREE; release_tree_vector (cleanups); } - else if (!DECL_PRETTY_FUNCTION_P (decl)) + else { + gcc_assert (!DECL_PRETTY_FUNCTION_P (decl)); /* Deduce array size even if the initializer is dependent. */ maybe_deduce_size_from_array_init (decl, init); /* And complain about multiple initializers. */ diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 297327f1ab6..318671bbcd0 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -262,6 +262,7 @@ is_capture_proxy (tree decl) && DECL_HAS_VALUE_EXPR_P (decl) && !DECL_ANON_UNION_VAR_P (decl) && !DECL_DECOMPOSITION_P (decl) + && !DECL_FNAME_P (decl) && LAMBDA_FUNCTION_P (DECL_CONTEXT (decl))); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index fc6cf989501..2dc0cb1629c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16735,6 +16735,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, register_local_specialization (inst, decl); break; } + else if (DECL_PRETTY_FUNCTION_P (decl)) + decl = make_fname_decl (DECL_SOURCE_LOCATION (decl), + DECL_NAME (decl), + true/*DECL_PRETTY_FUNCTION_P (decl)*/); else if (DECL_IMPLICIT_TYPEDEF_P (decl) && LAMBDA_TYPE_P (TREE_TYPE (decl))) /* Don't copy the old closure; we'll create a new one in @@ -16793,17 +16797,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, complain, in_decl, &first, &cnt); - if (VAR_P (decl) - && DECL_PRETTY_FUNCTION_P (decl)) - { - /* For __PRETTY_FUNCTION__ we have to adjust the - initializer. */ - const char *const name - = cxx_printable_name (current_function_decl, 2); - init = cp_fname_init (name, &TREE_TYPE (decl)); - } - else - init = tsubst_init (init, decl, args, complain, in_decl); + init = tsubst_init (init, decl, args, complain, in_decl); if (VAR_P (decl)) const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 157b5888637..8a0e66d4951 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2018-11-01 Martin Liska + Jason Merrill + + PR c++/64266 + PR bootstrap/70422 + PR ipa/81277 + * g++.dg/cpp0x/constexpr-__func__2.C: Make it a compilation + test. + * g++.old-deja/g++.ext/pretty4.C: Remove as the run-time + assumptions are not longer valid. + 2018-10-31 Thomas Koenig PR fortran/20520 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C index e6782905423..673fb4f3a93 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-__func__2.C @@ -1,5 +1,5 @@ // PR c++/70353 -// { dg-do link { target c++11 } } +// { dg-do compile { target c++11 } } constexpr const char* ce () { @@ -8,6 +8,5 @@ constexpr const char* ce () const char *c = ce(); -int main() -{ -} +#define SA(X) static_assert((X),#X) +SA(ce()[0] == 'c'); diff --git a/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C b/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C deleted file mode 100644 index 9017d567132..00000000000 --- a/gcc/testsuite/g++.old-deja/g++.ext/pretty4.C +++ /dev/null @@ -1,85 +0,0 @@ -// { dg-do run } -// Copyright (C) 2000 Free Software Foundation, Inc. -// Contributed by Nathan Sidwell 3 Mar 2000 - -// __PRETTY_FUNCTION__, __FUNCTION__ and __function__ should have the -// type char const [X], where X is the right value for that particular function - -static void const *strings[4]; -static void const *tpls[4]; -static unsigned pos = 0; -static int fail; -static void const *ptr = 0; - -void unover (char const (*)[5]) {} -void foo (char const (*)[5]) {} -void foo (void *) {fail = 1;} -void foo (void const *) {fail = 1;} -void baz (char const (&)[5]) {} - -template void PV (char const (&objRef)[I]) -{ - strings[pos] = objRef; - tpls[pos] = __PRETTY_FUNCTION__; - pos++; -} - -void fn () -{ - PV (__FUNCTION__); - PV (__func__); - PV (__PRETTY_FUNCTION__); - PV ("wibble"); -} - -void baz () -{ - ptr = __FUNCTION__; - // there should be no string const merging - if (ptr == "baz") - fail = 1; - // but all uses should be the same. - if (ptr != __FUNCTION__) - fail = 1; -} -int baz (int) -{ - return ptr == __FUNCTION__; -} - -int main () -{ - // make sure we actually emit the VAR_DECL when needed, and things have the - // expected type. - foo (&__FUNCTION__); - baz (__FUNCTION__); - unover (&__FUNCTION__); - if (fail) - return 1; - - // __FUNCTION__ should be unique across functions with the same base name - // (it's a local static, _not_ a string). - baz (); - if (fail) - return 1; - if (baz (1)) - return 1; - fn (); - - // Check the names of fn. They should all be distinct strings (though two - // will have the same value). - if (strings[0] == strings[1]) - return 1; - if (strings[0] == strings[2]) - return 1; - if (strings[1] == strings[2]) - return 1; - - // check the names of the template functions so invoked - if (tpls[0] != tpls[1]) - return 1; - if (tpls[0] == tpls[2]) - return 1; - - return 0; -} -- 2.30.2