From 91e920c9390f5293fdc84fbf9859dab53d7454b0 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 31 May 2017 16:46:58 +0000 Subject: [PATCH] cp-tree.h (lang_decl_slector): New enum. * cp-tree.h (lang_decl_slector): New enum. (lang_decl_base): Make selector an enum. Drop decomposition_p field. (lang_decl): Use enum for discrimination. (LANG_DECL_FN_CHECK, LANG_DECL_NS_CHECK, LANG_DECL_PARM_CHECK, LANG_DECL_DEOMP_CHECK): Use enum. (DECL_DECOMPOSITION_P): Use selector value. (SET_DECL_DECOMPOSITION_P): Delete. (retrofit_lang_decl): Lose SEL parm. (fit_decomposition_lang_decl): Declare. * decl.c (cp_finish_decomp, grokdeclarator): Use fit_decomposition_lang_decl. * lex.c (maybe_add_lang_decl_raw): New. Broken out of retrofit_lang_decl. (set_decl_linkage): New. Broken out of retrofit_lang_decl. Use enum. (fit_decomposition_lang_decl): Likewise. (retrofit_lang_decl): Use worker functions. (cxx_dup_lang_specific_decl): Use selector enum. (maybe_add_lang_type_raw): New. Broken out of ... (cxx_make_type_name): ... here. Call it. From-SVN: r248748 --- gcc/cp/ChangeLog | 23 ++++++++ gcc/cp/cp-tree.h | 47 ++++++++++------ gcc/cp/decl.c | 14 ++--- gcc/cp/lex.c | 162 ++++++++++++++++++++++++++++++++++++------------------- 4 files changed, 162 insertions(+), 84 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8cc3ca3..72a56f7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,26 @@ +2017-05-31 Nathan Sidwell + + * cp-tree.h (lang_decl_slector): New enum. + (lang_decl_base): Make selector an enum. Drop decomposition_p + field. + (lang_decl): Use enum for discrimination. + (LANG_DECL_FN_CHECK, LANG_DECL_NS_CHECK, LANG_DECL_PARM_CHECK, + LANG_DECL_DEOMP_CHECK): Use enum. + (DECL_DECOMPOSITION_P): Use selector value. + (SET_DECL_DECOMPOSITION_P): Delete. + (retrofit_lang_decl): Lose SEL parm. + (fit_decomposition_lang_decl): Declare. + * decl.c (cp_finish_decomp, grokdeclarator): Use + fit_decomposition_lang_decl. + * lex.c (maybe_add_lang_decl_raw): New. Broken out of + retrofit_lang_decl. + (set_decl_linkage): New. Broken out of retrofit_lang_decl. Use enum. + (fit_decomposition_lang_decl): Likewise. + (retrofit_lang_decl): Use worker functions. + (cxx_dup_lang_specific_decl): Use selector enum. + (maybe_add_lang_type_raw): New. Broken out of ... + (cxx_make_type_name): ... here. Call it. + 2017-05-30 Jason Merrill PR c++/80856 - ICE with local extern in template diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d6713f1..1c3cce8 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2423,13 +2423,25 @@ struct GTY(()) lang_type { #define NAMESPACE_LEVEL(NODE) \ (LANG_DECL_NS_CHECK (NODE)->level) +/* Discriminator values for lang_decl. */ + +enum lang_decl_selector +{ + lds_min, + lds_fn, + lds_ns, + lds_parm, + lds_decomp +}; + /* Flags shared by all forms of DECL_LANG_SPECIFIC. Some of the flags live here only to make lang_decl_min/fn smaller. Do not make this struct larger than 32 bits; instead, make sel smaller. */ struct GTY(()) lang_decl_base { - unsigned selector : 16; /* Larger than necessary for faster access. */ + /* Larger than necessary for faster access. */ + ENUM_BITFIELD(lang_decl_selector) selector : 16; ENUM_BITFIELD(languages) language : 1; unsigned use_template : 2; unsigned not_really_extern : 1; /* var or fn */ @@ -2444,8 +2456,7 @@ struct GTY(()) lang_decl_base { unsigned u2sel : 1; unsigned concept_p : 1; /* applies to vars and functions */ unsigned var_declared_inline_p : 1; /* var */ - unsigned decomposition_p : 1; /* var */ - /* 1 spare bit */ + /* 2 spare bits */ }; /* True for DECL codes which have template info and access. */ @@ -2577,12 +2588,13 @@ struct GTY(()) lang_decl_decomp { struct GTY(()) lang_decl { union GTY((desc ("%h.base.selector"))) lang_decl_u { + /* Nothing of only the base type exists. */ struct lang_decl_base GTY ((default)) base; - struct lang_decl_min GTY((tag ("0"))) min; - struct lang_decl_fn GTY ((tag ("1"))) fn; - struct lang_decl_ns GTY((tag ("2"))) ns; - struct lang_decl_parm GTY((tag ("3"))) parm; - struct lang_decl_decomp GTY((tag ("4"))) decomp; + struct lang_decl_min GTY((tag ("lds_min"))) min; + struct lang_decl_fn GTY ((tag ("lds_fn"))) fn; + struct lang_decl_ns GTY((tag ("lds_ns"))) ns; + struct lang_decl_parm GTY((tag ("lds_parm"))) parm; + struct lang_decl_decomp GTY((tag ("lds_decomp"))) decomp; } u; }; @@ -2603,26 +2615,29 @@ struct GTY(()) lang_decl { lang_decl_fn, look down through a TEMPLATE_DECL into its result. */ #define LANG_DECL_FN_CHECK(NODE) __extension__ \ ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (STRIP_TEMPLATE (NODE)); \ - if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != 1) \ + if (!DECL_DECLARES_FUNCTION_P (NODE) \ + || lt->u.base.selector != lds_fn) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ <->u.fn; }) #define LANG_DECL_NS_CHECK(NODE) __extension__ \ ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ - if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != 2) \ + if (TREE_CODE (NODE) != NAMESPACE_DECL \ + || lt->u.base.selector != lds_ns) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ <->u.ns; }) #define LANG_DECL_PARM_CHECK(NODE) __extension__ \ ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ - if (TREE_CODE (NODE) != PARM_DECL) \ + if (TREE_CODE (NODE) != PARM_DECL \ + || lt->u.base.selector != lds_parm) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ <->u.parm; }) #define LANG_DECL_DECOMP_CHECK(NODE) __extension__ \ ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!VAR_P (NODE) \ - || lt->u.base.selector != 4) \ + || lt->u.base.selector != lds_decomp) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ <->u.decomp; }) @@ -3893,11 +3908,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) declaration or one of VAR_DECLs for the user identifiers in it. */ #define DECL_DECOMPOSITION_P(NODE) \ (VAR_P (NODE) && DECL_LANG_SPECIFIC (NODE) \ - ? DECL_LANG_SPECIFIC (NODE)->u.base.decomposition_p \ + ? DECL_LANG_SPECIFIC (NODE)->u.base.selector == lds_decomp \ : false) -#define SET_DECL_DECOMPOSITION_P(NODE) \ - (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.decomposition_p \ - = true) /* The underlying artificial VAR_DECL for structured binding. */ #define DECL_DECOMP_BASE(NODE) \ @@ -6338,7 +6350,8 @@ extern tree unqualified_name_lookup_error (tree, extern tree unqualified_fn_lookup_error (cp_expr); extern tree build_lang_decl (enum tree_code, tree, tree); extern tree build_lang_decl_loc (location_t, enum tree_code, tree, tree); -extern void retrofit_lang_decl (tree, int = 0); +extern void retrofit_lang_decl (tree); +extern void fit_decomposition_lang_decl (tree, tree); extern tree copy_decl (tree CXX_MEM_STAT_INFO); extern tree copy_type (tree CXX_MEM_STAT_INFO); extern tree cxx_make_type (enum tree_code); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 59cb315..e895fa7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7372,11 +7372,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) DECL_HAS_VALUE_EXPR_P (first) = 1; } if (processing_template_decl) - { - retrofit_lang_decl (first, 4); - SET_DECL_DECOMPOSITION_P (first); - DECL_DECOMP_BASE (first) = decl; - } + fit_decomposition_lang_decl (first, decl); first = DECL_CHAIN (first); } return; @@ -7388,9 +7384,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d)) { v[count - i - 1] = d; - retrofit_lang_decl (d, 4); - SET_DECL_DECOMPOSITION_P (d); - DECL_DECOMP_BASE (d) = decl; + fit_decomposition_lang_decl (d, decl); } tree type = TREE_TYPE (decl); @@ -12314,10 +12308,8 @@ grokdeclarator (const cp_declarator *declarator, { gcc_assert (declarator && declarator->kind == cdk_decomp); DECL_SOURCE_LOCATION (decl) = declarator->id_loc; - retrofit_lang_decl (decl, 4); DECL_ARTIFICIAL (decl) = 1; - SET_DECL_DECOMPOSITION_P (decl); - DECL_DECOMP_BASE (decl) = NULL_TREE; + fit_decomposition_lang_decl (decl, NULL_TREE); } } diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 1b4eb35..5dc9eee 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -525,53 +525,52 @@ build_lang_decl_loc (location_t loc, enum tree_code code, tree name, tree type) return t; } -/* Add DECL_LANG_SPECIFIC info to T. Called from build_lang_decl - and pushdecl (for functions generated by the back end). */ +/* Maybe add a raw lang_decl to T, a decl. Return true if it needed + one. */ -void -retrofit_lang_decl (tree t, int sel) +static bool +maybe_add_lang_decl_raw (tree t, bool decomp_p) { - struct lang_decl *ld; size_t size; - size_t oldsize = 0; - - if (DECL_LANG_SPECIFIC (t)) - { - if (sel) - { - if (DECL_LANG_SPECIFIC (t)->u.base.selector == sel) - return; - gcc_assert (DECL_LANG_SPECIFIC (t)->u.base.selector == 0); - oldsize = sizeof (struct lang_decl_min); - } - else - return; - } + lang_decl_selector sel; - if (sel == 4) - size = sizeof (struct lang_decl_decomp); + if (decomp_p) + sel = lds_decomp, size = sizeof (struct lang_decl_decomp); else if (TREE_CODE (t) == FUNCTION_DECL) - sel = 1, size = sizeof (struct lang_decl_fn); + sel = lds_fn, size = sizeof (struct lang_decl_fn); else if (TREE_CODE (t) == NAMESPACE_DECL) - sel = 2, size = sizeof (struct lang_decl_ns); + sel = lds_ns, size = sizeof (struct lang_decl_ns); else if (TREE_CODE (t) == PARM_DECL) - sel = 3, size = sizeof (struct lang_decl_parm); + sel = lds_parm, size = sizeof (struct lang_decl_parm); else if (LANG_DECL_HAS_MIN (t)) - sel = 0, size = sizeof (struct lang_decl_min); + sel = lds_min, size = sizeof (struct lang_decl_min); else - gcc_unreachable (); + return false; - ld = (struct lang_decl *) ggc_internal_cleared_alloc (size); - if (oldsize) - memcpy (ld, DECL_LANG_SPECIFIC (t), oldsize); + struct lang_decl *ld + = (struct lang_decl *) ggc_internal_cleared_alloc (size); ld->u.base.selector = sel; DECL_LANG_SPECIFIC (t) = ld; - if (sel == 2) + if (sel == lds_ns) /* Who'd create a namespace, only to put nothing in it? */ ld->u.ns.bindings = hash_map::create_ggc (499); + if (GATHER_STATISTICS) + { + tree_node_counts[(int)lang_decl] += 1; + tree_node_sizes[(int)lang_decl] += size; + } + return true; +} + +/* T has just had a decl_lang_specific added. Initialize its + linkage. */ + +static void +set_decl_linkage (tree t) +{ if (current_lang_name == lang_name_cplusplus || decl_linkage (t) == lk_none) SET_DECL_LANGUAGE (t, lang_cplusplus); @@ -579,37 +578,79 @@ retrofit_lang_decl (tree t, int sel) SET_DECL_LANGUAGE (t, lang_c); else gcc_unreachable (); +} - if (GATHER_STATISTICS) +/* T is a VAR_DECL node that needs to be a decomposition of BASE. */ + +void +fit_decomposition_lang_decl (tree t, tree base) +{ + if (struct lang_decl *orig_ld = DECL_LANG_SPECIFIC (t)) { - tree_node_counts[(int)lang_decl] += 1; - tree_node_sizes[(int)lang_decl] += size; + if (orig_ld->u.base.selector == lds_min) + { + maybe_add_lang_decl_raw (t, true); + memcpy (DECL_LANG_SPECIFIC (t), orig_ld, + sizeof (struct lang_decl_min)); + /* Reset selector, which will have been bashed by the + memcpy. */ + DECL_LANG_SPECIFIC (t)->u.base.selector = lds_decomp; + } + else + gcc_checking_assert (orig_ld->u.base.selector == lds_decomp); + } + else + { + maybe_add_lang_decl_raw (t, true); + set_decl_linkage (t); } + + DECL_DECOMP_BASE (t) = base; +} + +/* Add DECL_LANG_SPECIFIC info to T, if it needs one. Generally + every C++ decl needs one, but C builtins etc do not. */ + +void +retrofit_lang_decl (tree t) +{ + if (DECL_LANG_SPECIFIC (t)) + return; + + if (maybe_add_lang_decl_raw (t, false)) + set_decl_linkage (t); } void cxx_dup_lang_specific_decl (tree node) { int size; - struct lang_decl *ld; if (! DECL_LANG_SPECIFIC (node)) return; - if (TREE_CODE (node) == FUNCTION_DECL) - size = sizeof (struct lang_decl_fn); - else if (TREE_CODE (node) == NAMESPACE_DECL) - size = sizeof (struct lang_decl_ns); - else if (TREE_CODE (node) == PARM_DECL) - size = sizeof (struct lang_decl_parm); - else if (DECL_DECOMPOSITION_P (node)) - size = sizeof (struct lang_decl_decomp); - else if (LANG_DECL_HAS_MIN (node)) - size = sizeof (struct lang_decl_min); - else - gcc_unreachable (); + switch (DECL_LANG_SPECIFIC (node)->u.base.selector) + { + case lds_min: + size = sizeof (struct lang_decl_min); + break; + case lds_fn: + size = sizeof (struct lang_decl_fn); + break; + case lds_ns: + size = sizeof (struct lang_decl_ns); + break; + case lds_parm: + size = sizeof (struct lang_decl_parm); + break; + case lds_decomp: + size = sizeof (struct lang_decl_decomp); + break; + default: + gcc_unreachable (); + } - ld = (struct lang_decl *) ggc_internal_alloc (size); + struct lang_decl *ld = (struct lang_decl *) ggc_internal_alloc (size); memcpy (ld, DECL_LANG_SPECIFIC (node), size); DECL_LANG_SPECIFIC (node) = ld; @@ -670,18 +711,18 @@ copy_type (tree type MEM_STAT_DECL) return copy; } -tree -cxx_make_type (enum tree_code code) -{ - tree t = make_node (code); +/* Add a raw lang_type to T, a type, should it need one. */ - /* Create lang_type structure. */ - if (RECORD_OR_UNION_CODE_P (code) - || code == BOUND_TEMPLATE_TEMPLATE_PARM) +static bool +maybe_add_lang_type_raw (tree t) +{ + bool add = (RECORD_OR_UNION_CODE_P (TREE_CODE (t)) + || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM); + if (add) { struct lang_type *pi - = (struct lang_type *) ggc_internal_cleared_alloc - (sizeof (struct lang_type)); + = (struct lang_type *) ggc_internal_cleared_alloc + (sizeof (struct lang_type)); TYPE_LANG_SPECIFIC (t) = pi; pi->u.c.h.is_lang_type_class = 1; @@ -692,6 +733,15 @@ cxx_make_type (enum tree_code code) tree_node_sizes[(int)lang_type] += sizeof (struct lang_type); } } + return add; +} + +tree +cxx_make_type (enum tree_code code) +{ + tree t = make_node (code); + + maybe_add_lang_type_raw (t); /* Set up some flags that give proper default behavior. */ if (RECORD_OR_UNION_CODE_P (code)) -- 2.7.4