error ("an anonymous union cannot have function members");
}
-/* Called when a declaration is seen that contains no names to declare.
- If its type is a reference to a structure, union or enum inherited
- from a containing scope, shadow that tag name for the current scope
- with a forward reference.
- If its type defines a new named structure or union
- or defines an enum, it is valid but we need not do anything here.
- Otherwise, it is an error.
+/* Make sure that a declaration with no declarator is well-formed, i.e.
+ just defines a tagged type or anonymous union.
- C++: may have to grok the declspecs to learn about static,
- complain for anonymous unions. */
+ Returns the type defined, if any. */
-void
-shadow_tag (declspecs)
+tree
+check_tag_decl (declspecs)
tree declspecs;
{
- int found_tag = 0;
+ int found_type = 0;
tree ob_modifier = NULL_TREE;
register tree link;
- register enum tree_code code, ok_code = ERROR_MARK;
register tree t = NULL_TREE;
for (link = declspecs; link; link = TREE_CHAIN (link))
{
register tree value = TREE_VALUE (link);
- code = TREE_CODE (value);
- if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
+ if (TYPE_P (value))
{
- my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
-
- maybe_process_partial_specialization (value);
+ ++found_type;
- t = value;
- ok_code = code;
- found_tag++;
+ if (IS_AGGR_TYPE (value) || TREE_CODE (value) == ENUMERAL_TYPE)
+ {
+ my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+ t = value;
+ }
}
else if (value == ridpointers[(int) RID_STATIC]
|| value == ridpointers[(int) RID_EXTERN]
|| value == ridpointers[(int) RID_REGISTER]
|| value == ridpointers[(int) RID_INLINE]
|| value == ridpointers[(int) RID_VIRTUAL]
+ || (value == ridpointers[(int) RID_FRIEND]
+ && (current_class_type == NULL_TREE
+ || current_scope () != current_class_type))
+ || value == ridpointers[(int) RID_CONST]
+ || value == ridpointers[(int) RID_VOLATILE]
|| value == ridpointers[(int) RID_EXPLICIT])
ob_modifier = value;
}
- /* This is where the variables in an anonymous union are
- declared. An anonymous union declaration looks like:
- union { ... } ;
- because there is no declarator after the union, the parser
- sends that declaration here. */
- if (ok_code == UNION_TYPE
- && t != NULL_TREE
- && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (TYPE_NAME (t)))
- || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
- {
- fixup_anonymous_union (t);
-
- if (TYPE_FIELDS (t))
- {
- tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
- NULL_TREE);
- finish_anon_union (decl);
- }
- }
+ if (found_type > 1)
+ error ("multiple types in one declaration");
+
+ if (t == NULL_TREE)
+ pedwarn ("declaration does not declare anything");
+ else if (ANON_UNION_TYPE_P (t))
+ return t;
else
{
/* Anonymous unions are objects, that's why we only check for
if (ob_modifier == ridpointers[(int) RID_INLINE]
|| ob_modifier == ridpointers[(int) RID_VIRTUAL])
cp_error ("`%D' can only be specified for functions", ob_modifier);
+ else if (ob_modifier == ridpointers[(int) RID_FRIEND])
+ cp_error ("`%D' can only be specified inside a class", ob_modifier);
else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
cp_error ("`%D' can only be specified for constructors",
ob_modifier);
cp_error ("`%D' can only be specified for objects and functions",
ob_modifier);
}
+ }
- if (found_tag == 0)
- cp_error ("abstract declarator used as declaration");
- else if (found_tag > 1)
- pedwarn ("multiple types in one declaration");
+ return t;
+}
+
+/* Called when a declaration is seen that contains no names to declare.
+ If its type is a reference to a structure, union or enum inherited
+ from a containing scope, shadow that tag name for the current scope
+ with a forward reference.
+ If its type defines a new named structure or union
+ or defines an enum, it is valid but we need not do anything here.
+ Otherwise, it is an error.
+
+ C++: may have to grok the declspecs to learn about static,
+ complain for anonymous unions. */
+
+void
+shadow_tag (declspecs)
+ tree declspecs;
+{
+ tree t = check_tag_decl (declspecs);
+
+ if (t)
+ maybe_process_partial_specialization (t);
+
+ /* This is where the variables in an anonymous union are
+ declared. An anonymous union declaration looks like:
+ union { ... } ;
+ because there is no declarator after the union, the parser
+ sends that declaration here. */
+ if (t && ANON_UNION_TYPE_P (t))
+ {
+ fixup_anonymous_union (t);
+
+ if (TYPE_FIELDS (t))
+ {
+ tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
+ NULL_TREE);
+ finish_anon_union (decl);
+ }
}
}
\f
type))
/* If we just return the declaration, crashes
will sometimes occur. We therefore return
- void_type_node, as if this was a friend
- declaration, to cause callers to completely
- ignore this declaration. */
+ void_type_node, as if this was a friend
+ declaration, to cause callers to completely
+ ignore this declaration. */
return void_type_node;
}