Make __PRETTY_FUNCTION__-like functions mergeable string csts (PR c++/64266).
2018-11-01 Martin Liska <mliska@suse.cz> Jason Merrill <jason@redhat.com> 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 <mliska@suse.cz> Jason Merrill <jason@redhat.com> 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 <jason@redhat.com> From-SVN: r265711
This commit is contained in:
parent
964f78b7e7
commit
ddd0d18c9c
@ -1,3 +1,16 @@
|
||||
2018-11-01 Martin Liska <mliska@suse.cz>
|
||||
Jason Merrill <jason@redhat.com>
|
||||
|
||||
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 <nathan@acm.org>
|
||||
|
||||
* cp-tree.h (OVL_DEDUP_P): New.
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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)));
|
||||
}
|
||||
|
||||
|
16
gcc/cp/pt.c
16
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
|
||||
|
@ -1,3 +1,14 @@
|
||||
2018-11-01 Martin Liska <mliska@suse.cz>
|
||||
Jason Merrill <jason@redhat.com>
|
||||
|
||||
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 <tkoenig@gcc.gnu.org>
|
||||
|
||||
PR fortran/20520
|
||||
|
@ -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');
|
||||
|
@ -1,85 +0,0 @@
|
||||
// { dg-do run }
|
||||
// Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
// Contributed by Nathan Sidwell 3 Mar 2000 <nathan@codesourcery.com>
|
||||
|
||||
// __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<unsigned I> 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user