Previously, finish_member_declaration prepended non-type members and
appended TYPE_DECLs to TYPE_FIELDS separately, so that the TYPE_DECLs
always appeared after all non-type members regardless of their decleration
order.
Store all members in declaration order instead and update the places,
that relied on the old layout.
gcc/analyzer/ChangeLog:
* region-model.cc (struct_or_union_with_inheritance_p): Skip
leading TYPE_DECL nodes before checking for base class field.
gcc/cp/ChangeLog:
* class.cc (unreverse_member_declarations): Use nreverse for both
CLASSTYPE_DECL_LIST and TYPE_FIELDS.
* decl.cc (reshape_init_class): Guard anonymous aggregate field
search with FIELD_DECL check.
* name-lookup.cc (fields_linear_search): Return first non-type
match immediately; fall back to TYPE_DECL if no non-type is found.
* parser.cc (remove_dummy_lambda_op): Search chain for dummy
operator instead of assuming it is the TYPE_FIELDS head.
* semantics.cc (finish_member_declaration): Always prepend to
FIELD_DECL; remove separate handling for TYPE_DECL.
Signed-off-by: Thomas Berger <[email protected]>
---
gcc/analyzer/region-model.cc | 5 +++++
gcc/cp/class.cc | 26 +-------------------------
gcc/cp/decl.cc | 3 ++-
gcc/cp/name-lookup.cc | 17 +++++++++++++++--
gcc/cp/parser.cc | 20 +++++++++++---------
gcc/cp/semantics.cc | 20 ++------------------
6 files changed, 36 insertions(+), 55 deletions(-)
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 4a6f5b4800c..1935b3a45fa 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -4116,6 +4116,11 @@ static bool
struct_or_union_with_inheritance_p (tree struc)
{
tree iter = TYPE_FIELDS (struc);
+
+ // look for the first non type member
+ while (iter && TREE_CODE (iter) == TYPE_DECL)
+ iter = DECL_CHAIN (iter);
+
if (iter == NULL_TREE)
return false;
if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (iter)))
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 8beeb797a08..399fbdc136b 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -8180,32 +8180,8 @@ finish_struct_1 (tree t)
void
unreverse_member_declarations (tree t)
{
- tree next;
- tree prev;
- tree x;
-
- /* The following lists are all in reverse order. Put them in
- declaration order now. */
CLASSTYPE_DECL_LIST (t) = nreverse (CLASSTYPE_DECL_LIST (t));
-
- /* For the TYPE_FIELDS, only the non TYPE_DECLs are in reverse
- order, so we can't just use nreverse. Due to stat_hack
- chicanery in finish_member_declaration. */
- prev = NULL_TREE;
- for (x = TYPE_FIELDS (t);
- x && TREE_CODE (x) != TYPE_DECL;
- x = next)
- {
- next = DECL_CHAIN (x);
- DECL_CHAIN (x) = prev;
- prev = x;
- }
-
- if (prev)
- {
- DECL_CHAIN (TYPE_FIELDS (t)) = x;
- TYPE_FIELDS (t) = prev;
- }
+ TYPE_FIELDS(t) = nreverse (TYPE_FIELDS(t));
}
/* Classes, structs or unions T marked with hotness attributes propagate
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 49056d94857..0700df77f85 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -7901,7 +7901,8 @@ reshape_init_class (tree type, reshape_iter *d, bool
first_initializer_p,
/* Now find the TYPE member with that anon aggr type. */
tree aafield = TYPE_FIELDS (type);
for (; aafield; aafield = TREE_CHAIN (aafield))
- if (TREE_TYPE (aafield) == ictx)
+ if (TREE_TYPE (aafield) == ictx
+ && TREE_CODE(aafield) == FIELD_DECL)
break;
gcc_assert (aafield);
field = aafield;
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 13aafab4e68..8addd3b29ca 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -1848,6 +1848,7 @@ member_vec_linear_search (vec<tree, va_gc> *member_vec,
tree name)
static tree
fields_linear_search (tree klass, tree name, bool want_type)
{
+ tree found = NULL_TREE;
for (tree fields = TYPE_FIELDS (klass); fields; fields = DECL_CHAIN (fields))
{
tree decl = fields;
@@ -1878,11 +1879,23 @@ fields_linear_search (tree klass, tree name, bool
want_type)
/* Functions are found separately. */
continue;
- if (!want_type || DECL_DECLARES_TYPE_P (decl))
+ if (DECL_DECLARES_TYPE_P (decl))
+ {
+ if (want_type)
+ return decl;
+
+ /* This decl may be hidden through a non-TYPE_DECL member later on.
+ We store the type and return it in the case no other matching
+ member was found. */
+ found = decl;
+ continue;
+ }
+
+ if (!want_type)
return decl;
}
- return NULL_TREE;
+ return found;
}
/* Like fields_linear_search, but specific for "_" name. There can be multiple
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index ffb22aa776f..e18a740a918 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -13673,15 +13673,17 @@ void
remove_dummy_lambda_op (tree dummy_fco, tree lambda_expr)
{
tree type = TREE_TYPE (lambda_expr);
- if (TYPE_FIELDS (type) == dummy_fco)
- {
- /* Stitch out the dummy operator(). */
- TYPE_FIELDS (type) = DECL_CHAIN (TYPE_FIELDS (type));
- /* And clear the member vector as well. */
- auto *member_vec = CLASSTYPE_MEMBER_VEC (type);
- gcc_assert (member_vec->length () == 1);
- member_vec->truncate (0);
- }
+ for (tree *prev_p = &TYPE_FIELDS (type); *prev_p;
+ prev_p = &DECL_CHAIN (*prev_p))
+ if (*prev_p == dummy_fco)
+ {
+ *prev_p = DECL_CHAIN (*prev_p);
+ auto *member_vec = CLASSTYPE_MEMBER_VEC (type);
+ gcc_assert (member_vec->length () == 1);
+ member_vec->truncate (0);
+ break;
+ }
+
/* Class templates will have the dummy operator() stashed here too. */
tree &list = CLASSTYPE_DECL_LIST (type);
if (list && TREE_VALUE (list) == dummy_fco)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index ac08b598f3d..a0dcc14c3fe 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4323,24 +4323,8 @@ finish_member_declaration (tree decl)
if (add)
{
- /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
- go at the beginning. The reason is that
- legacy_nonfn_member_lookup searches the list in order, and we
- want a field name to override a type name so that the "struct
- stat hack" will work. In particular:
-
- struct S { enum E { }; static const int E = 5; int ary[S::E]; } s;
-
- is valid. */
-
- if (TREE_CODE (decl) == TYPE_DECL)
- TYPE_FIELDS (current_class_type)
- = chainon (TYPE_FIELDS (current_class_type), decl);
- else
- {
- DECL_CHAIN (decl) = TYPE_FIELDS (current_class_type);
- TYPE_FIELDS (current_class_type) = decl;
- }
+ DECL_CHAIN (decl) = TYPE_FIELDS (current_class_type);
+ TYPE_FIELDS (current_class_type) = decl;
maybe_add_class_template_decl_list (current_class_type, decl,
/*friend_p=*/0);
--
2.52.0