Commit 91e920c9 by Nathan Sidwell Committed by Nathan Sidwell

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
parent 3909991c
2017-05-31 Nathan Sidwell <nathan@acm.org>
* 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 <jason@redhat.com> 2017-05-30 Jason Merrill <jason@redhat.com>
PR c++/80856 - ICE with local extern in template PR c++/80856 - ICE with local extern in template
......
...@@ -2423,13 +2423,25 @@ struct GTY(()) lang_type { ...@@ -2423,13 +2423,25 @@ struct GTY(()) lang_type {
#define NAMESPACE_LEVEL(NODE) \ #define NAMESPACE_LEVEL(NODE) \
(LANG_DECL_NS_CHECK (NODE)->level) (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. /* Flags shared by all forms of DECL_LANG_SPECIFIC.
Some of the flags live here only to make lang_decl_min/fn smaller. Do 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. */ not make this struct larger than 32 bits; instead, make sel smaller. */
struct GTY(()) lang_decl_base { 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; ENUM_BITFIELD(languages) language : 1;
unsigned use_template : 2; unsigned use_template : 2;
unsigned not_really_extern : 1; /* var or fn */ unsigned not_really_extern : 1; /* var or fn */
...@@ -2444,8 +2456,7 @@ struct GTY(()) lang_decl_base { ...@@ -2444,8 +2456,7 @@ struct GTY(()) lang_decl_base {
unsigned u2sel : 1; unsigned u2sel : 1;
unsigned concept_p : 1; /* applies to vars and functions */ unsigned concept_p : 1; /* applies to vars and functions */
unsigned var_declared_inline_p : 1; /* var */ unsigned var_declared_inline_p : 1; /* var */
unsigned decomposition_p : 1; /* var */ /* 2 spare bits */
/* 1 spare bit */
}; };
/* True for DECL codes which have template info and access. */ /* True for DECL codes which have template info and access. */
...@@ -2577,12 +2588,13 @@ struct GTY(()) lang_decl_decomp { ...@@ -2577,12 +2588,13 @@ struct GTY(()) lang_decl_decomp {
struct GTY(()) lang_decl { struct GTY(()) lang_decl {
union GTY((desc ("%h.base.selector"))) lang_decl_u { 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_base GTY ((default)) base;
struct lang_decl_min GTY((tag ("0"))) min; struct lang_decl_min GTY((tag ("lds_min"))) min;
struct lang_decl_fn GTY ((tag ("1"))) fn; struct lang_decl_fn GTY ((tag ("lds_fn"))) fn;
struct lang_decl_ns GTY((tag ("2"))) ns; struct lang_decl_ns GTY((tag ("lds_ns"))) ns;
struct lang_decl_parm GTY((tag ("3"))) parm; struct lang_decl_parm GTY((tag ("lds_parm"))) parm;
struct lang_decl_decomp GTY((tag ("4"))) decomp; struct lang_decl_decomp GTY((tag ("lds_decomp"))) decomp;
} u; } u;
}; };
...@@ -2603,26 +2615,29 @@ struct GTY(()) lang_decl { ...@@ -2603,26 +2615,29 @@ struct GTY(()) lang_decl {
lang_decl_fn, look down through a TEMPLATE_DECL into its result. */ lang_decl_fn, look down through a TEMPLATE_DECL into its result. */
#define LANG_DECL_FN_CHECK(NODE) __extension__ \ #define LANG_DECL_FN_CHECK(NODE) __extension__ \
({ struct lang_decl *lt = DECL_LANG_SPECIFIC (STRIP_TEMPLATE (NODE)); \ ({ 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__); \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
&lt->u.fn; }) &lt->u.fn; })
#define LANG_DECL_NS_CHECK(NODE) __extension__ \ #define LANG_DECL_NS_CHECK(NODE) __extension__ \
({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ ({ 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__); \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
&lt->u.ns; }) &lt->u.ns; })
#define LANG_DECL_PARM_CHECK(NODE) __extension__ \ #define LANG_DECL_PARM_CHECK(NODE) __extension__ \
({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ ({ 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__); \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
&lt->u.parm; }) &lt->u.parm; })
#define LANG_DECL_DECOMP_CHECK(NODE) __extension__ \ #define LANG_DECL_DECOMP_CHECK(NODE) __extension__ \
({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (!VAR_P (NODE) \ if (!VAR_P (NODE) \
|| lt->u.base.selector != 4) \ || lt->u.base.selector != lds_decomp) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
&lt->u.decomp; }) &lt->u.decomp; })
...@@ -3893,11 +3908,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -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. */ declaration or one of VAR_DECLs for the user identifiers in it. */
#define DECL_DECOMPOSITION_P(NODE) \ #define DECL_DECOMPOSITION_P(NODE) \
(VAR_P (NODE) && DECL_LANG_SPECIFIC (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) : 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. */ /* The underlying artificial VAR_DECL for structured binding. */
#define DECL_DECOMP_BASE(NODE) \ #define DECL_DECOMP_BASE(NODE) \
...@@ -6338,7 +6350,8 @@ extern tree unqualified_name_lookup_error (tree, ...@@ -6338,7 +6350,8 @@ extern tree unqualified_name_lookup_error (tree,
extern tree unqualified_fn_lookup_error (cp_expr); extern tree unqualified_fn_lookup_error (cp_expr);
extern tree build_lang_decl (enum tree_code, tree, tree); extern tree build_lang_decl (enum tree_code, tree, tree);
extern tree build_lang_decl_loc (location_t, 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_decl (tree CXX_MEM_STAT_INFO);
extern tree copy_type (tree CXX_MEM_STAT_INFO); extern tree copy_type (tree CXX_MEM_STAT_INFO);
extern tree cxx_make_type (enum tree_code); extern tree cxx_make_type (enum tree_code);
......
...@@ -7372,11 +7372,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) ...@@ -7372,11 +7372,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
DECL_HAS_VALUE_EXPR_P (first) = 1; DECL_HAS_VALUE_EXPR_P (first) = 1;
} }
if (processing_template_decl) if (processing_template_decl)
{ fit_decomposition_lang_decl (first, decl);
retrofit_lang_decl (first, 4);
SET_DECL_DECOMPOSITION_P (first);
DECL_DECOMP_BASE (first) = decl;
}
first = DECL_CHAIN (first); first = DECL_CHAIN (first);
} }
return; return;
...@@ -7388,9 +7384,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) ...@@ -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)) for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
{ {
v[count - i - 1] = d; v[count - i - 1] = d;
retrofit_lang_decl (d, 4); fit_decomposition_lang_decl (d, decl);
SET_DECL_DECOMPOSITION_P (d);
DECL_DECOMP_BASE (d) = decl;
} }
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (decl);
...@@ -12314,10 +12308,8 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -12314,10 +12308,8 @@ grokdeclarator (const cp_declarator *declarator,
{ {
gcc_assert (declarator && declarator->kind == cdk_decomp); gcc_assert (declarator && declarator->kind == cdk_decomp);
DECL_SOURCE_LOCATION (decl) = declarator->id_loc; DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
retrofit_lang_decl (decl, 4);
DECL_ARTIFICIAL (decl) = 1; DECL_ARTIFICIAL (decl) = 1;
SET_DECL_DECOMPOSITION_P (decl); fit_decomposition_lang_decl (decl, NULL_TREE);
DECL_DECOMP_BASE (decl) = NULL_TREE;
} }
} }
......
...@@ -525,53 +525,52 @@ build_lang_decl_loc (location_t loc, enum tree_code code, tree name, tree type) ...@@ -525,53 +525,52 @@ build_lang_decl_loc (location_t loc, enum tree_code code, tree name, tree type)
return t; return t;
} }
/* Add DECL_LANG_SPECIFIC info to T. Called from build_lang_decl /* Maybe add a raw lang_decl to T, a decl. Return true if it needed
and pushdecl (for functions generated by the back end). */ one. */
void static bool
retrofit_lang_decl (tree t, int sel) maybe_add_lang_decl_raw (tree t, bool decomp_p)
{ {
struct lang_decl *ld;
size_t size; size_t size;
size_t oldsize = 0; lang_decl_selector sel;
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;
}
if (sel == 4) if (decomp_p)
size = sizeof (struct lang_decl_decomp); sel = lds_decomp, size = sizeof (struct lang_decl_decomp);
else if (TREE_CODE (t) == FUNCTION_DECL) 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) 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) 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)) 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 else
gcc_unreachable (); return false;
ld = (struct lang_decl *) ggc_internal_cleared_alloc (size); struct lang_decl *ld
if (oldsize) = (struct lang_decl *) ggc_internal_cleared_alloc (size);
memcpy (ld, DECL_LANG_SPECIFIC (t), oldsize);
ld->u.base.selector = sel; ld->u.base.selector = sel;
DECL_LANG_SPECIFIC (t) = ld; DECL_LANG_SPECIFIC (t) = ld;
if (sel == 2) if (sel == lds_ns)
/* Who'd create a namespace, only to put nothing in it? */ /* Who'd create a namespace, only to put nothing in it? */
ld->u.ns.bindings = hash_map<lang_identifier *, tree>::create_ggc (499); ld->u.ns.bindings = hash_map<lang_identifier *, tree>::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 if (current_lang_name == lang_name_cplusplus
|| decl_linkage (t) == lk_none) || decl_linkage (t) == lk_none)
SET_DECL_LANGUAGE (t, lang_cplusplus); SET_DECL_LANGUAGE (t, lang_cplusplus);
...@@ -579,37 +578,79 @@ retrofit_lang_decl (tree t, int sel) ...@@ -579,37 +578,79 @@ retrofit_lang_decl (tree t, int sel)
SET_DECL_LANGUAGE (t, lang_c); SET_DECL_LANGUAGE (t, lang_c);
else else
gcc_unreachable (); 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; if (orig_ld->u.base.selector == lds_min)
tree_node_sizes[(int)lang_decl] += size; {
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 void
cxx_dup_lang_specific_decl (tree node) cxx_dup_lang_specific_decl (tree node)
{ {
int size; int size;
struct lang_decl *ld;
if (! DECL_LANG_SPECIFIC (node)) if (! DECL_LANG_SPECIFIC (node))
return; return;
if (TREE_CODE (node) == FUNCTION_DECL) switch (DECL_LANG_SPECIFIC (node)->u.base.selector)
size = sizeof (struct lang_decl_fn); {
else if (TREE_CODE (node) == NAMESPACE_DECL) case lds_min:
size = sizeof (struct lang_decl_ns); size = sizeof (struct lang_decl_min);
else if (TREE_CODE (node) == PARM_DECL) break;
size = sizeof (struct lang_decl_parm); case lds_fn:
else if (DECL_DECOMPOSITION_P (node)) size = sizeof (struct lang_decl_fn);
size = sizeof (struct lang_decl_decomp); break;
else if (LANG_DECL_HAS_MIN (node)) case lds_ns:
size = sizeof (struct lang_decl_min); size = sizeof (struct lang_decl_ns);
else break;
gcc_unreachable (); 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); memcpy (ld, DECL_LANG_SPECIFIC (node), size);
DECL_LANG_SPECIFIC (node) = ld; DECL_LANG_SPECIFIC (node) = ld;
...@@ -670,18 +711,18 @@ copy_type (tree type MEM_STAT_DECL) ...@@ -670,18 +711,18 @@ copy_type (tree type MEM_STAT_DECL)
return copy; return copy;
} }
tree /* Add a raw lang_type to T, a type, should it need one. */
cxx_make_type (enum tree_code code)
{
tree t = make_node (code);
/* Create lang_type structure. */ static bool
if (RECORD_OR_UNION_CODE_P (code) maybe_add_lang_type_raw (tree t)
|| code == BOUND_TEMPLATE_TEMPLATE_PARM) {
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 *pi
= (struct lang_type *) ggc_internal_cleared_alloc = (struct lang_type *) ggc_internal_cleared_alloc
(sizeof (struct lang_type)); (sizeof (struct lang_type));
TYPE_LANG_SPECIFIC (t) = pi; TYPE_LANG_SPECIFIC (t) = pi;
pi->u.c.h.is_lang_type_class = 1; pi->u.c.h.is_lang_type_class = 1;
...@@ -692,6 +733,15 @@ cxx_make_type (enum tree_code code) ...@@ -692,6 +733,15 @@ cxx_make_type (enum tree_code code)
tree_node_sizes[(int)lang_type] += sizeof (struct lang_type); 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. */ /* Set up some flags that give proper default behavior. */
if (RECORD_OR_UNION_CODE_P (code)) if (RECORD_OR_UNION_CODE_P (code))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment