* Make-lang.in (cp/lex.o): Do not depend on cp/lex.h.
(cp/decl.o): Likewise.
(cp/decl2.o): Likewise.
(cp/pt.o): Likewise.
(cp/semantics.o): Likewise.
* config-lang.in (gtfiles): Do not reference cp/lex.h.
* class.c: Do not include lex.h.
(add_implicitly_declared_members): Do not use
adding_implicit_members.
(check_bases_and_members): Do not talk about grok_x_components.
* cp/cp-tree.h (adding_implicit_members): Remove.
(cp_storage_class): New type.
(cp_decl_spec): Likewise.
(cp_decl_specifier_seq): Likewise.
(cp_parameter_declarator): Use it for the decl_specifiers field.
(check_tag_decl): Adjust prototype.
(shadow_tag): Likewise.
(groktypename): Likewise.
(start_decl): Likewise.
(start_function): Likewise.
(start_method): Likewise.
(grok_x_components): Remove.
(grokfield): Adjust prototype.
(grokbitfield): Likewise.
(finish_member_class_template): Remove.
* decl.c: Do not include lex.h.
(adding_implicit_members): Do not define.
(check_tag_decl): Do not use trees to represent decl-specifiers.
(shadow_tag): Likewise.
(groktypename): Likewise.
(start_decl): Likewise.
(grokvardecl): Likewise.
(grokdeclarator): Likewise.
(grokparms): Likewise.
(start_function): Likewise.
(start_method): Likewise.
* decl.h (grokdeclarator): Adjust prototype.
* decl2.c: Do not include lex.h.
(grok_x_components): Remove.
(grokfield): Do not use trees to represent decl-specifiers.
(grokbitfield): Likewise.
* lex.c: Do not include lex.h.
* lex.h: Remove.
* parser.c: Include target.h.
(clear_decl_specs): New function.
(cp_parser_translation_unit): Do not use trees to represent
decl-specifiers.
(cp_parser_postfix_expression): Likewise.
(cp_parser_new_type_id): Likewise.
(cp_parser_condition): Likewise.
(cp_parser_simple_declaration): Likewise.
(cp_parser_decl_specifier_seq): Likewise.
(cp_parser_function_specifier_opt): Likewise.
(cp_parser_conversion_type_id): Likewise.
(cp_parser_template_parameter): Likewise.
(cp_parser_explicit_instantiation): Likewise.
(cp_parser_type_specifier): Likewise.
(cp_parser_simple_type_specifier): Likewise.
(cp_parser_init_declarator): Likewise.
(cp_parser_type_id): Likewise.
(cp_parser_type_specifier_seq): Likewise.
(cp_parser_parameter_declaration): Likewise.
(cp_parser_member_declaration): Likewise.
(cp_parser_exception_declaration): Likewise.
(cp_parser_function_definition_from_specifiers_and_declarator):
Likewise.
(cp_parser_single_declaration): Likewise.
(cp_parser_save_member_function_body): Likewise.
(cp_parser_friend_p): Likewise.
(cp_parser_set_storage_class): New function.
(cp_parser_set_decl_spec_type): Likewise.
* pt.c: Do not include lex.h.
* semantics.c: Likewise.
(finish_member_class_template): Remove.
From-SVN: r83584
+2004-06-23 Mark Mitchell <mark@codesourcery.com>
+
+ * Make-lang.in (cp/lex.o): Do not depend on cp/lex.h.
+ (cp/decl.o): Likewise.
+ (cp/decl2.o): Likewise.
+ (cp/pt.o): Likewise.
+ (cp/semantics.o): Likewise.
+ * config-lang.in (gtfiles): Do not reference cp/lex.h.
+ * class.c: Do not include lex.h.
+ (add_implicitly_declared_members): Do not use
+ adding_implicit_members.
+ (check_bases_and_members): Do not talk about grok_x_components.
+ * cp/cp-tree.h (adding_implicit_members): Remove.
+ (cp_storage_class): New type.
+ (cp_decl_spec): Likewise.
+ (cp_decl_specifier_seq): Likewise.
+ (cp_parameter_declarator): Use it for the decl_specifiers field.
+ (check_tag_decl): Adjust prototype.
+ (shadow_tag): Likewise.
+ (groktypename): Likewise.
+ (start_decl): Likewise.
+ (start_function): Likewise.
+ (start_method): Likewise.
+ (grok_x_components): Remove.
+ (grokfield): Adjust prototype.
+ (grokbitfield): Likewise.
+ (finish_member_class_template): Remove.
+ * decl.c: Do not include lex.h.
+ (adding_implicit_members): Do not define.
+ (check_tag_decl): Do not use trees to represent decl-specifiers.
+ (shadow_tag): Likewise.
+ (groktypename): Likewise.
+ (start_decl): Likewise.
+ (grokvardecl): Likewise.
+ (grokdeclarator): Likewise.
+ (grokparms): Likewise.
+ (start_function): Likewise.
+ (start_method): Likewise.
+ * decl.h (grokdeclarator): Adjust prototype.
+ * decl2.c: Do not include lex.h.
+ (grok_x_components): Remove.
+ (grokfield): Do not use trees to represent decl-specifiers.
+ (grokbitfield): Likewise.
+ * lex.c: Do not include lex.h.
+ * lex.h: Remove.
+ * parser.c: Include target.h.
+ (clear_decl_specs): New function.
+ (cp_parser_translation_unit): Do not use trees to represent
+ decl-specifiers.
+ (cp_parser_postfix_expression): Likewise.
+ (cp_parser_new_type_id): Likewise.
+ (cp_parser_condition): Likewise.
+ (cp_parser_simple_declaration): Likewise.
+ (cp_parser_decl_specifier_seq): Likewise.
+ (cp_parser_function_specifier_opt): Likewise.
+ (cp_parser_conversion_type_id): Likewise.
+ (cp_parser_template_parameter): Likewise.
+ (cp_parser_explicit_instantiation): Likewise.
+ (cp_parser_type_specifier): Likewise.
+ (cp_parser_simple_type_specifier): Likewise.
+ (cp_parser_init_declarator): Likewise.
+ (cp_parser_type_id): Likewise.
+ (cp_parser_type_specifier_seq): Likewise.
+ (cp_parser_parameter_declaration): Likewise.
+ (cp_parser_member_declaration): Likewise.
+ (cp_parser_exception_declaration): Likewise.
+ (cp_parser_function_definition_from_specifiers_and_declarator):
+ Likewise.
+ (cp_parser_single_declaration): Likewise.
+ (cp_parser_save_member_function_body): Likewise.
+ (cp_parser_friend_p): Likewise.
+ (cp_parser_set_storage_class): New function.
+ (cp_parser_set_decl_spec_type): Likewise.
+ * pt.c: Do not include lex.h.
+ * semantics.c: Likewise.
+ (finish_member_class_template): Remove.
+
2004-06-23 Roger Sayle <roger@eyesopen.com>
* call.c (build_cxx_call): Don't call expand_tree_builtin. No
CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
-cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h \
+cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) flags.h \
c-pragma.h toplev.h output.h input.h cp/operators.def $(TM_P_H)
cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h langhooks.h \
$(LANGHOOKS_DEF_H) c-common.h $(CXX_PRETTY_PRINT_H) $(DIAGNOSTIC_H)
-cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h stack.h \
+cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/decl.h stack.h \
output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \
cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \
debug.h gt-cp-decl.h gtype-cp.h timevar.h $(TREE_FLOW_H)
-cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
+cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/decl.h $(EXPR_H) \
output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h cgraph.h
cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \
diagnostic.h
cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h
cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
except.h $(TM_P_H)
-cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/lex.h \
+cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h \
toplev.h $(RTL_H) except.h tree-inline.h gt-cp-pt.h
cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) toplev.h $(DIAGNOSTIC_H) \
flags.h real.h $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H)
cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \
gt-cp-repo.h
-cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) cp/lex.h except.h toplev.h \
+cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) except.h toplev.h \
flags.h debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
tree-inline.h cgraph.h
cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h
#include "rtl.h"
#include "output.h"
#include "toplev.h"
-#include "lex.h"
#include "target.h"
#include "convert.h"
tree virtual_dtor = NULL_TREE;
tree *f;
- ++adding_implicit_members;
-
/* Destructor. */
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
{
*f = TYPE_METHODS (t);
TYPE_METHODS (t) = implicit_fns;
}
-
- --adding_implicit_members;
}
/* Subroutine of finish_struct_1. Recursively count the number of fields
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
- /* Synthesize any needed methods. Note that methods will be synthesized
- for anonymous unions; grok_x_components undoes that. */
+ /* Synthesize any needed methods. */
add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_ctor,
no_const_asn_ref);
target_libs="target-libstdc++-v3 target-gperf"
-gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/lex.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c"
+gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c"
binfo. */
} base_kind;
-/* Set by add_implicitly_declared_members() to keep those members from
- being flagged as deprecated or reported as using deprecated
- types. */
-extern int adding_implicit_members;
-
/* in decl{2}.c */
/* A node that is a list (length 1) of error_mark_nodes. */
extern GTY(()) tree error_mark_list;
extern GTY(()) operator_name_info_t assignment_operator_name_info
[(int) LAST_CPLUS_TREE_CODE];
+/* A storage class. */
+
+typedef enum cp_storage_class {
+ /* sc_none must be zero so that zeroing a cp_decl_specifier_seq
+ sets the storage_class field to sc_none. */
+ sc_none = 0,
+ sc_auto,
+ sc_register,
+ sc_static,
+ sc_extern,
+ sc_mutable,
+} cp_storage_class;
+
+/* An individual decl-specifier. */
+
+typedef enum cp_decl_spec {
+ ds_first,
+ ds_signed = ds_first,
+ ds_unsigned,
+ ds_short,
+ ds_long,
+ ds_const,
+ ds_volatile,
+ ds_restrict,
+ ds_inline,
+ ds_virtual,
+ ds_explicit,
+ ds_friend,
+ ds_typedef,
+ ds_complex,
+ ds_thread,
+ ds_last
+} cp_decl_spec;
+
+/* A decl-specifier-seq. */
+
+typedef struct cp_decl_specifier_seq {
+ /* The number of times each of the keywords has been seen. */
+ unsigned specs[(int) ds_last];
+ /* The primary type, if any, given by the decl-specifier-seq.
+ Modifiers, like "short", "const", and "unsigned" are not
+ reflected here. This field will be a TYPE, unless a typedef-name
+ was used, in which case it will be a TYPE_DECL. */
+ tree type;
+ /* The attributes, if any, provided with the specifier sequence. */
+ tree attributes;
+ /* If non-NULL, a built-in type that the user attempted to redefine
+ to some other type. */
+ tree redefined_builtin_type;
+ /* The storage class specified -- or sc_none if no storage class was
+ explicitly specified. */
+ cp_storage_class storage_class;
+ /* True iff TYPE_SPEC indicates a user-defined type. */
+ BOOL_BITFIELD user_defined_type_p : 1;
+ /* True iff multiple types were (erroneously) specified for this
+ decl-specifier-seq. */
+ BOOL_BITFIELD multiple_types_p : 1;
+ /* True iff multiple storage classes were (erroneously) specified
+ for this decl-specifier-seq. */
+ BOOL_BITFIELD multiple_storage_classes_p : 1;
+ /* True iff at least one decl-specifier was found. */
+ BOOL_BITFIELD any_specifiers_p : 1;
+ /* True iff "int" was explicitly provided. */
+ BOOL_BITFIELD explicit_int_p : 1;
+ /* True iff "char" was explicitly provided. */
+ BOOL_BITFIELD explicit_char_p : 1;
+} cp_decl_specifier_seq;
+
/* The various kinds of declarators. */
typedef enum cp_declarator_kind {
/* The next parameter, or NULL_TREE if none. */
cp_parameter_declarator *next;
/* The decl-specifiers-seq for the parameter. */
- tree decl_specifiers;
+ cp_decl_specifier_seq decl_specifiers;
/* The declarator for the parameter. */
cp_declarator *declarator;
/* The default-argument expression, or NULL_TREE, if none. */
extern tree push_void_library_fn (tree, tree);
extern tree push_throw_library_fn (tree, tree);
extern int init_type_desc (void);
-extern tree check_tag_decl (tree);
-extern tree shadow_tag (tree);
-extern tree groktypename (tree, const cp_declarator *);
-extern tree start_decl (const cp_declarator *, tree, int, tree, tree);
+extern tree check_tag_decl (cp_decl_specifier_seq *);
+extern tree shadow_tag (cp_decl_specifier_seq *);
+extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *);
+extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree);
extern void start_decl_1 (tree);
extern void cp_finish_decl (tree, tree, tree, int);
extern void finish_decl (tree, tree, tree);
extern void finish_enum (tree);
extern void build_enumerator (tree, tree, tree);
extern void start_preparsed_function (tree, tree, int);
-extern int start_function (tree, const cp_declarator *, tree);
+extern int start_function (cp_decl_specifier_seq *, const cp_declarator *, tree);
extern tree begin_function_body (void);
extern void finish_function_body (tree);
extern tree finish_function (int);
-extern tree start_method (tree, const cp_declarator *, tree);
+extern tree start_method (cp_decl_specifier_seq *, const cp_declarator *, tree);
extern tree finish_method (tree);
extern void maybe_register_incomplete_var (tree);
extern void complete_vars (tree);
/* in decl2.c */
extern bool check_java_method (tree);
extern int grok_method_quals (tree, tree, tree);
-extern void grok_x_components (tree);
extern void maybe_retrofit_in_chrg (tree);
extern void maybe_make_one_only (tree);
extern void grokclassfn (tree, tree, enum overload_flags, tree);
extern tree delete_sanity (tree, tree, bool, int);
extern tree check_classfn (tree, tree, tree);
extern void check_member_template (tree);
-extern tree grokfield (const cp_declarator *, tree, tree, tree, tree);
-extern tree grokbitfield (const cp_declarator *, tree, tree);
+extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, tree, tree, tree);
+extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *, tree);
extern tree groktypefield (tree, tree);
extern void cplus_decl_attributes (tree *, tree, int);
extern void finish_anon_union (tree);
extern tree finish_template_template_parm (tree, tree);
extern tree begin_class_definition (tree);
extern void finish_default_args (void);
-extern tree finish_member_class_template (tree);
extern void finish_template_decl (tree);
extern tree finish_template_type (tree, tree, int);
extern tree finish_base_specifier (tree, tree, bool);
#include "cp-tree.h"
#include "tree-inline.h"
#include "decl.h"
-#include "lex.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "timevar.h"
#include "tree-flow.h"
-static tree grokparms (const cp_parameter_declarator *, tree *);
+static tree grokparms (cp_parameter_declarator *, tree *);
static const char *redeclaration_error_message (tree, tree);
static int decl_jump_unsafe (tree);
static tree grokfndecl (tree, tree, tree, tree, tree, int,
enum overload_flags, tree,
tree, int, int, int, int, int, int, tree);
-static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree);
+static tree grokvardecl (tree, tree, cp_decl_specifier_seq *, int, int, tree);
static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (const char *, tree, tree, int,
enum built_in_class, const char *,
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
-/* Set by add_implicitly_declared_members() to keep those members from
- being flagged as deprecated or reported as using deprecated
- types. */
-int adding_implicit_members = 0;
-
/* True if a declaration with an `extern' linkage specifier is being
processed. */
bool have_extern_spec;
Returns the type declared; or NULL_TREE if none. */
tree
-check_tag_decl (tree declspecs)
+check_tag_decl (cp_decl_specifier_seq *declspecs)
{
- int found_type = 0;
- int saw_friend = 0;
- int saw_typedef = 0;
- tree ob_modifier = NULL_TREE;
- tree link;
+ int saw_friend = declspecs->specs[(int)ds_friend] != 0;
+ int saw_typedef = declspecs->specs[(int)ds_typedef] != 0;
/* If a class, struct, or enum type is declared by the DECLSPECS
(i.e, if a class-specifier, enum-specifier, or non-typename
elaborated-type-specifier appears in the DECLSPECS),
tree declared_type = NULL_TREE;
bool error_p = false;
- for (link = declspecs; link; link = TREE_CHAIN (link))
- {
- tree value = TREE_VALUE (link);
-
- if (TYPE_P (value) || TREE_CODE (value) == TYPE_DECL
- || (TREE_CODE (value) == IDENTIFIER_NODE
- && is_typename_at_global_scope (value)))
- {
- ++found_type;
-
- if (found_type == 2 && TREE_CODE (value) == IDENTIFIER_NODE)
- {
- if (! in_system_header)
- pedwarn ("redeclaration of C++ built-in type `%T'", value);
- return NULL_TREE;
- }
-
- if (TYPE_P (value)
- && ((TREE_CODE (value) != TYPENAME_TYPE && IS_AGGR_TYPE (value))
- || TREE_CODE (value) == ENUMERAL_TYPE))
- {
- my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
- declared_type = value;
- }
- }
- else if (value == ridpointers[(int) RID_TYPEDEF])
- saw_typedef = 1;
- else if (value == ridpointers[(int) RID_FRIEND])
- {
- if (current_class_type == NULL_TREE
- || current_scope () != current_class_type)
- ob_modifier = value;
- else
- saw_friend = 1;
- }
- else if (value == ridpointers[(int) RID_STATIC]
- || value == ridpointers[(int) RID_EXTERN]
- || value == ridpointers[(int) RID_AUTO]
- || value == ridpointers[(int) RID_REGISTER]
- || value == ridpointers[(int) RID_INLINE]
- || value == ridpointers[(int) RID_VIRTUAL]
- || value == ridpointers[(int) RID_CONST]
- || value == ridpointers[(int) RID_VOLATILE]
- || value == ridpointers[(int) RID_EXPLICIT]
- || value == ridpointers[(int) RID_THREAD])
- ob_modifier = value;
- else if (value == error_mark_node)
- error_p = true;
- }
-
- if (found_type > 1)
+ if (declspecs->multiple_types_p)
error ("multiple types in one declaration");
+ else if (declspecs->redefined_builtin_type)
+ {
+ if (!in_system_header)
+ pedwarn ("redeclaration of C++ built-in type",
+ declspecs->redefined_builtin_type);
+ return NULL_TREE;
+ }
+ if (TYPE_P (declspecs->type)
+ && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
+ && IS_AGGR_TYPE (declspecs->type))
+ || TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
+ declared_type = declspecs->type;
+ else if (declspecs->type == error_mark_node)
+ error_p = true;
if (declared_type == NULL_TREE && ! saw_friend && !error_p)
pedwarn ("declaration does not declare anything");
/* Check for an anonymous union. */
pedwarn ("ISO C++ prohibits anonymous structs");
}
- else if (ob_modifier)
+ else
{
- if (ob_modifier == ridpointers[(int) RID_INLINE]
- || ob_modifier == ridpointers[(int) RID_VIRTUAL])
- error ("`%D' can only be specified for functions", ob_modifier);
- else if (ob_modifier == ridpointers[(int) RID_FRIEND])
- error ("`%D' can only be specified inside a class", ob_modifier);
- else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
- error ("`%D' can only be specified for constructors",
- ob_modifier);
- else
- error ("`%D' can only be specified for objects and functions",
- ob_modifier);
+ if (declspecs->specs[(int)ds_inline]
+ || declspecs->specs[(int)ds_virtual])
+ error ("`%s' can only be specified for functions",
+ declspecs->specs[(int)ds_inline]
+ ? "inline" : "virtual");
+ else if (saw_friend
+ && (!current_class_type
+ || current_scope () != current_class_type))
+ error ("`friend' can only be specified inside a class");
+ else if (declspecs->specs[(int)ds_explicit])
+ error ("`explicit' can only be specified for constructors");
+ else if (declspecs->storage_class)
+ error ("a storage class can only be specified for objects "
+ "and functions");
+ else if (declspecs->specs[(int)ds_const]
+ || declspecs->specs[(int)ds_volatile]
+ || declspecs->specs[(int)ds_restrict]
+ || declspecs->specs[(int)ds_thread])
+ error ("qualifiers can only be specified for objects "
+ "and functions");
}
return declared_type;
Returns the TYPE declared -- or NULL_TREE if none. */
tree
-shadow_tag (tree declspecs)
+shadow_tag (cp_decl_specifier_seq *declspecs)
{
tree t = check_tag_decl (declspecs);
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
-groktypename (tree type_specifiers, const cp_declarator *declarator)
+groktypename (cp_decl_specifier_seq *type_specifiers,
+ const cp_declarator *declarator)
{
- tree specs, attrs;
+ tree attrs;
tree type;
- split_specs_attrs (type_specifiers, &specs, &attrs);
- type = grokdeclarator (declarator, specs, TYPENAME, 0, &attrs);
+ attrs = type_specifiers->attributes;
+ type_specifiers->attributes = NULL_TREE;
+ type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
if (attrs)
cplus_decl_attributes (&type, attrs, 0);
return type;
tree
start_decl (const cp_declarator *declarator,
- tree declspecs,
+ cp_decl_specifier_seq *declspecs,
int initialized,
tree attributes,
tree prefix_attributes)
/* This should only be done once on the top most decl. */
if (have_extern_spec)
{
- declspecs = tree_cons (NULL_TREE, get_identifier ("extern"),
- declspecs);
+ declspecs->storage_class = sc_extern;
have_extern_spec = false;
}
static tree
grokvardecl (tree type,
tree name,
- RID_BIT_TYPE * specbits_in,
+ cp_decl_specifier_seq *declspecs,
int initialized,
int constp,
tree scope)
{
tree decl;
- RID_BIT_TYPE specbits;
my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE,
20020808);
- specbits = *specbits_in;
-
/* Compute the scope in which to place the variable. */
if (!scope)
{
/* An explicit "extern" specifier indicates a namespace-scope
variable. */
- if (RIDBIT_SETP (RID_EXTERN, specbits))
+ if (declspecs->storage_class == sc_extern)
scope = current_namespace;
else if (!at_function_scope_p ())
{
else
DECL_CONTEXT (decl) = scope;
- if (RIDBIT_SETP (RID_EXTERN, specbits))
+ if (declspecs->storage_class == sc_extern)
{
DECL_THIS_EXTERN (decl) = 1;
DECL_EXTERNAL (decl) = !initialized;
(perhaps tentative), and absence of `static' makes it public. */
else if (toplevel_bindings_p ())
{
- TREE_PUBLIC (decl) = (RIDBIT_NOTSETP (RID_STATIC, specbits)
+ TREE_PUBLIC (decl) = (declspecs->storage_class != sc_static
&& (DECL_THIS_EXTERN (decl) || ! constp));
TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
}
/* Not at top level, only `static' makes a static definition. */
else
{
- TREE_STATIC (decl) = !! RIDBIT_SETP (RID_STATIC, specbits);
+ TREE_STATIC (decl) = declspecs->storage_class == sc_static;
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
- if (RIDBIT_SETP (RID_THREAD, specbits))
+ if (declspecs->specs[(int)ds_thread])
{
if (targetm.have_tls)
DECL_THREAD_LOCAL (decl) = 1;
tree
grokdeclarator (const cp_declarator *declarator,
- tree declspecs,
+ cp_decl_specifier_seq *declspecs,
enum decl_context decl_context,
int initialized,
tree* attrlist)
{
- RID_BIT_TYPE specbits;
- int nclasses = 0;
- tree spec;
tree type = NULL_TREE;
int longlong = 0;
int type_quals;
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
- int extern_langp = 0;
tree dependant_name = NULL_TREE;
tree typedef_decl = NULL_TREE;
this value will be NULL_TREE, even if the entity is located at
namespace scope. */
tree in_namespace = NULL_TREE;
+ cp_decl_spec ds;
- RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
else if (decl_context == MEMFUNCDEF)
if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
&& innermost_code != cdk_function
- && ! (ctype && declspecs == NULL_TREE))
+ && ! (ctype && !declspecs->any_specifiers_p))
{
error ("declaration of `%D' as non-function", dname);
return void_type_node;
if (name == NULL)
name = decl_context == PARM ? "parameter" : "type name";
- /* Look through the decl specs and record which ones appear.
- Some typespecs are defined as built-in typenames.
- Others, the ones that are modifiers of other types,
- are represented by bits in SPECBITS: set the bits for
- the modifiers that appear. Storage class keywords are also in SPECBITS.
-
- If there is a typedef name or a type, store the type in TYPE.
- This includes builtin typedefs such as `int'.
-
- Set EXPLICIT_INT if the type is `int' or `char' and did not
- come from a user typedef.
-
- Set LONGLONG if `long' is mentioned twice.
-
- For C++, constructors and destructors have their own fast treatment. */
-
- for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
+ /* If there were multiple types specified in the decl-specifier-seq,
+ issue an error message. */
+ if (declspecs->multiple_types_p)
+ error ("two or more data types in declaration of `%s'", name);
+ /* Extract the basic type from the decl-specifier-seq. */
+ type = declspecs->type;
+ if (type == error_mark_node)
+ type = NULL_TREE;
+ /* If the entire declaration is itself tagged as deprecated then
+ suppress reports of deprecated items. */
+ if (type && TREE_DEPRECATED (type)
+ && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (type);
+ if (type && TREE_CODE (type) == TYPE_DECL)
{
- int i;
- tree id;
-
- /* Certain parse errors slip through. For example,
- `int class;' is not caught by the parser. Try
- weakly to recover here. */
- if (TREE_CODE (spec) != TREE_LIST)
- return 0;
-
- id = TREE_VALUE (spec);
-
- /* If the entire declaration is itself tagged as deprecated then
- suppress reports of deprecated items. */
- if (!adding_implicit_members && id && TREE_DEPRECATED (id))
- {
- if (deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (id);
- }
-
- if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- if (id == ridpointers[(int) RID_INT]
- || id == ridpointers[(int) RID_CHAR]
- || id == ridpointers[(int) RID_BOOL]
- || id == ridpointers[(int) RID_WCHAR])
- {
- if (type)
- {
- if (id == ridpointers[(int) RID_BOOL])
- error ("`bool' is now a keyword");
- else
- error ("extraneous `%T' ignored", id);
- }
- else
- {
- if (id == ridpointers[(int) RID_INT])
- explicit_int = 1;
- else if (id == ridpointers[(int) RID_CHAR])
- explicit_char = 1;
- type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
- }
- goto found;
- }
- /* C++ aggregate types. */
- if (IDENTIFIER_HAS_TYPE_VALUE (id))
- {
- if (type)
- error ("multiple declarations `%T' and `%T'", type, id);
- else
- type = IDENTIFIER_TYPE_VALUE (id);
- goto found;
- }
-
- for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++)
- {
- if (ridpointers[i] == id)
- {
- if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
- {
- if (pedantic && ! in_system_header && warn_long_long)
- pedwarn ("ISO C++ does not support `long long'");
- if (longlong)
- error ("`long long long' is too long for GCC");
- else
- longlong = 1;
- }
- else if (RIDBIT_SETP (i, specbits))
- pedwarn ("duplicate `%E'", id);
-
- /* Diagnose "__thread extern" or "__thread static". */
- if (RIDBIT_SETP (RID_THREAD, specbits))
- {
- if (i == (int)RID_EXTERN)
- error ("`__thread' before `extern'");
- else if (i == (int)RID_STATIC)
- error ("`__thread' before `static'");
- }
-
- if (i == (int)RID_EXTERN
- && TREE_PURPOSE (spec) == error_mark_node)
- /* This extern was part of a language linkage. */
- extern_langp = 1;
+ typedef_decl = type;
+ type = TREE_TYPE (typedef_decl);
+ }
+ /* No type at all: default to `int', and set DEFAULTED_INT
+ because it was not a user-defined typedef. */
+ if (type == NULL_TREE
+ && (declspecs->specs[(int)ds_signed]
+ || declspecs->specs[(int)ds_unsigned]
+ || declspecs->specs[(int)ds_long]
+ || declspecs->specs[(int)ds_short]))
+ {
+ /* These imply 'int'. */
+ type = integer_type_node;
+ defaulted_int = 1;
+ }
+ /* Gather flags. */
+ explicit_int = declspecs->explicit_int_p;
+ explicit_char = declspecs->explicit_char_p;
- RIDBIT_SET (i, specbits);
- goto found;
- }
- }
- }
- else if (TREE_CODE (id) == TYPE_DECL)
- {
- if (type)
- error ("multiple declarations `%T' and `%T'", type,
- TREE_TYPE (id));
- else
- {
- type = TREE_TYPE (id);
- TREE_VALUE (spec) = type;
- typedef_decl = id;
- }
- goto found;
- }
- if (type)
- error ("two or more data types in declaration of `%s'", name);
- else if (TREE_CODE (id) == IDENTIFIER_NODE)
+ /* Check for repeated decl-specifiers. */
+ for (ds = ds_first; ds != ds_last; ++ds)
+ {
+ unsigned count = declspecs->specs[(int)ds];
+ if (count < 2)
+ continue;
+ /* The "long" specifier is a special case because of
+ "long long". */
+ if (ds == ds_long)
{
- tree t = lookup_name (id, 1);
- if (!t || TREE_CODE (t) != TYPE_DECL)
- error ("`%E' fails to be a typedef or built in type", id);
+ if (count > 2)
+ error ("`long long long' is too long for GCC");
+ else if (pedantic && !in_system_header && warn_long_long)
+ pedwarn ("ISO C++ does not support `long long'");
else
- {
- type = TREE_TYPE (t);
- typedef_decl = t;
- }
- }
- else if (id != error_mark_node)
- /* Can't change CLASS nodes into RECORD nodes here! */
- type = id;
-
- found: ;
+ longlong = 1;
+ }
+ else if (declspecs->specs[(int)ds] > 1)
+ error ("duplicate decl-specifier");
}
#if 0
#endif
typedef_type = type;
- /* No type at all: default to `int', and set DEFAULTED_INT
- because it was not a user-defined typedef. */
-
- if (type == NULL_TREE
- && (RIDBIT_SETP (RID_SIGNED, specbits)
- || RIDBIT_SETP (RID_UNSIGNED, specbits)
- || RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits)))
- {
- /* These imply 'int'. */
- type = integer_type_node;
- defaulted_int = 1;
- }
if (sfk != sfk_none)
type = check_special_function_return_type (sfk, type,
and check for invalid combinations. */
/* Long double is a special combination. */
-
- if (RIDBIT_SETP (RID_LONG, specbits)
+ if (declspecs->specs[(int)ds_long]
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
- RIDBIT_RESET (RID_LONG, specbits);
+ declspecs->specs[(int)ds_long] = 0;
type = build_qualified_type (long_double_type_node,
cp_type_quals (type));
}
/* Check all other uses of type modifiers. */
- if (RIDBIT_SETP (RID_UNSIGNED, specbits)
- || RIDBIT_SETP (RID_SIGNED, specbits)
- || RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits))
+ if (declspecs->specs[(int)ds_unsigned]
+ || declspecs->specs[(int)ds_signed]
+ || declspecs->specs[(int)ds_long]
+ || declspecs->specs[(int)ds_short])
{
int ok = 0;
error ("short, signed or unsigned invalid for `%s'", name);
else if (TREE_CODE (type) != INTEGER_TYPE)
error ("long, short, signed or unsigned invalid for `%s'", name);
- else if (RIDBIT_SETP (RID_LONG, specbits)
- && RIDBIT_SETP (RID_SHORT, specbits))
+ else if (declspecs->specs[(int)ds_long]
+ && declspecs->specs[(int)ds_short])
error ("long and short specified together for `%s'", name);
- else if ((RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits))
+ else if ((declspecs->specs[(int)ds_long]
+ || declspecs->specs[(int)ds_short])
&& explicit_char)
error ("long or short specified with char for `%s'", name);
- else if ((RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits))
+ else if ((declspecs->specs[(int)ds_long]
+ || declspecs->specs[(int)ds_short])
&& TREE_CODE (type) == REAL_TYPE)
error ("long or short specified with floating type for `%s'", name);
- else if (RIDBIT_SETP (RID_SIGNED, specbits)
- && RIDBIT_SETP (RID_UNSIGNED, specbits))
+ else if (declspecs->specs[(int)ds_signed]
+ && declspecs->specs[(int)ds_unsigned])
error ("signed and unsigned given together for `%s'", name);
else
{
/* Discard the type modifiers if they are invalid. */
if (! ok)
{
- RIDBIT_RESET (RID_UNSIGNED, specbits);
- RIDBIT_RESET (RID_SIGNED, specbits);
- RIDBIT_RESET (RID_LONG, specbits);
- RIDBIT_RESET (RID_SHORT, specbits);
+ declspecs->specs[(int)ds_unsigned] = 0;
+ declspecs->specs[(int)ds_signed] = 0;
+ declspecs->specs[(int)ds_long] = 0;
+ declspecs->specs[(int)ds_short] = 0;
longlong = 0;
}
}
- if (RIDBIT_SETP (RID_COMPLEX, specbits)
+ if (declspecs->specs[(int)ds_complex]
&& TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
{
error ("complex invalid for `%s'", name);
- RIDBIT_RESET (RID_COMPLEX, specbits);
+ declspecs->specs[(int)ds_complex] = 0;
}
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
- if (RIDBIT_SETP (RID_UNSIGNED, specbits)
+ if (declspecs->specs[(int)ds_unsigned]
/* [class.bit]
It is implementation-defined whether a plain (neither
Naturally, we extend this to long long as well. Note that
this does not include wchar_t. */
|| (bitfield && !flag_signed_bitfields
- && RIDBIT_NOTSETP (RID_SIGNED, specbits)
+ && !declspecs->specs[(int)ds_signed]
/* A typedef for plain `int' without `signed' can be
controlled just like plain `int', but a typedef for
`signed int' cannot be so controlled. */
{
if (longlong)
type = long_long_unsigned_type_node;
- else if (RIDBIT_SETP (RID_LONG, specbits))
+ else if (declspecs->specs[(int)ds_long])
type = long_unsigned_type_node;
- else if (RIDBIT_SETP (RID_SHORT, specbits))
+ else if (declspecs->specs[(int)ds_short])
type = short_unsigned_type_node;
else if (type == char_type_node)
type = unsigned_char_type_node;
else
type = unsigned_type_node;
}
- else if (RIDBIT_SETP (RID_SIGNED, specbits)
+ else if (declspecs->specs[(int)ds_signed]
&& type == char_type_node)
type = signed_char_type_node;
else if (longlong)
type = long_long_integer_type_node;
- else if (RIDBIT_SETP (RID_LONG, specbits))
+ else if (declspecs->specs[(int)ds_long])
type = long_integer_type_node;
- else if (RIDBIT_SETP (RID_SHORT, specbits))
+ else if (declspecs->specs[(int)ds_short])
type = short_integer_type_node;
- if (RIDBIT_SETP (RID_COMPLEX, specbits))
+ if (declspecs->specs[(int)ds_complex])
{
/* If we just have "complex", it is equivalent to
"complex double", but if any modifiers at all are specified it is
"complex short int". */
if (defaulted_int && ! longlong
- && ! (RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits)
- || RIDBIT_SETP (RID_SIGNED, specbits)
- || RIDBIT_SETP (RID_UNSIGNED, specbits)))
+ && ! (declspecs->specs[(int)ds_long]
+ || declspecs->specs[(int)ds_short]
+ || declspecs->specs[(int)ds_signed]
+ || declspecs->specs[(int)ds_unsigned]))
type = complex_double_type_node;
else if (type == integer_type_node)
type = complex_integer_type_node;
}
type_quals = TYPE_UNQUALIFIED;
- if (RIDBIT_SETP (RID_CONST, specbits))
+ if (declspecs->specs[(int)ds_const])
type_quals |= TYPE_QUAL_CONST;
- if (RIDBIT_SETP (RID_VOLATILE, specbits))
+ if (declspecs->specs[(int)ds_volatile])
type_quals |= TYPE_QUAL_VOLATILE;
- if (RIDBIT_SETP (RID_RESTRICT, specbits))
+ if (declspecs->specs[(int)ds_restrict])
type_quals |= TYPE_QUAL_RESTRICT;
if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
error ("qualifiers are not allowed on declaration of `operator %T'",
type_quals = cp_type_quals (type);
staticp = 0;
- inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
- virtualp = !! RIDBIT_SETP (RID_VIRTUAL, specbits);
- RIDBIT_RESET (RID_VIRTUAL, specbits);
- explicitp = !! RIDBIT_SETP (RID_EXPLICIT, specbits);
- RIDBIT_RESET (RID_EXPLICIT, specbits);
+ inlinep = !! declspecs->specs[(int)ds_inline];
+ virtualp = !! declspecs->specs[(int)ds_virtual];
+ explicitp = !! declspecs->specs[(int)ds_explicit];
- if (RIDBIT_SETP (RID_STATIC, specbits))
+ if (declspecs->storage_class == sc_static)
staticp = 1 + (decl_context == FIELD);
if (virtualp && staticp == 2)
dname);
staticp = 0;
}
- friendp = !! RIDBIT_SETP (RID_FRIEND, specbits);
- RIDBIT_RESET (RID_FRIEND, specbits);
+ friendp = !! declspecs->specs[(int)ds_friend];
if (dependant_name && !friendp)
{
error ("`%T::%D' is not a valid declarator", ctype, dependant_name);
return void_type_node;
}
-
- /* Warn if two storage classes are given. Default to `auto'. */
- if (RIDBIT_ANY_SET (specbits))
+ /* Issue errors about use of storage classes for parameters. */
+ if (decl_context == PARM)
{
- if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
- if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
- if (RIDBIT_SETP (RID_THREAD, specbits)) nclasses++;
- if (decl_context == PARM && nclasses > 0)
+ if (declspecs->specs[(int)ds_typedef])
+ error ("typedef declaration invalid in parameter declaration");
+ else if (declspecs->storage_class == sc_static
+ || declspecs->storage_class == sc_extern
+ || declspecs->specs[(int)ds_thread])
error ("storage class specifiers invalid in parameter declarations");
- if (RIDBIT_SETP (RID_TYPEDEF, specbits))
- {
- if (decl_context == PARM)
- error ("typedef declaration invalid in parameter declaration");
- nclasses++;
- }
- if (RIDBIT_SETP (RID_AUTO, specbits)) nclasses++;
- if (RIDBIT_SETP (RID_REGISTER, specbits)) nclasses++;
- if (!nclasses && !friendp && extern_langp)
- nclasses++;
}
/* Give error if `virtual' is used outside of class declaration. */
/* Static anonymous unions are dealt with here. */
if (staticp && decl_context == TYPENAME
- && TREE_CODE (declspecs) == TREE_LIST
- && ANON_AGGR_TYPE_P (TREE_VALUE (declspecs)))
+ && declspecs->type
+ && ANON_AGGR_TYPE_P (declspecs->type))
decl_context = FIELD;
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
-
- /* "static __thread" and "extern __thread" are allowed. */
- if (nclasses == 2
- && RIDBIT_SETP (RID_THREAD, specbits)
- && (RIDBIT_SETP (RID_EXTERN, specbits)
- || RIDBIT_SETP (RID_STATIC, specbits)))
- nclasses = 1;
-
- if (nclasses > 1)
+ if (declspecs->multiple_storage_classes_p)
error ("multiple storage classes in declaration of `%s'", name);
- else if (decl_context != NORMAL && nclasses > 0)
+ else if (decl_context != NORMAL
+ && declspecs->storage_class != sc_none
+ && declspecs->storage_class != sc_mutable)
{
if ((decl_context == PARM || decl_context == CATCHPARM)
- && (RIDBIT_SETP (RID_REGISTER, specbits)
- || RIDBIT_SETP (RID_AUTO, specbits)))
+ && (declspecs->storage_class == sc_register
+ || declspecs->storage_class == sc_auto))
;
- else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
+ else if (declspecs->specs[(int)ds_typedef])
;
else if (decl_context == FIELD
/* C++ allows static class elements. */
- && RIDBIT_SETP (RID_STATIC, specbits))
+ && declspecs->storage_class == sc_static)
/* C++ also allows inlines and signed and unsigned elements,
but in those cases we don't come in here. */
;
else
error ("storage class specified for typename");
}
- RIDBIT_RESET (RID_REGISTER, specbits);
- RIDBIT_RESET (RID_AUTO, specbits);
- RIDBIT_RESET (RID_EXTERN, specbits);
- RIDBIT_RESET (RID_THREAD, specbits);
+ if (declspecs->storage_class == sc_register
+ || declspecs->storage_class == sc_auto
+ || declspecs->storage_class == sc_extern
+ || declspecs->specs[(int)ds_thread])
+ declspecs->storage_class = sc_none;
}
}
- else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag)
+ else if (declspecs->storage_class == sc_extern && initialized
+ && !funcdef_flag)
{
if (toplevel_bindings_p ())
{
else
error ("`%s' has both `extern' and initializer", name);
}
- else if (RIDBIT_SETP (RID_EXTERN, specbits) && funcdef_flag
+ else if (declspecs->storage_class == sc_extern && funcdef_flag
&& ! toplevel_bindings_p ())
error ("nested function `%s' declared `extern'", name);
else if (toplevel_bindings_p ())
{
- if (RIDBIT_SETP (RID_AUTO, specbits))
+ if (declspecs->storage_class == sc_auto)
error ("top-level declaration of `%s' specifies `auto'", name);
}
- else if (RIDBIT_SETP (RID_THREAD, specbits)
- && !RIDBIT_SETP (RID_EXTERN, specbits)
- && !RIDBIT_SETP (RID_STATIC, specbits))
+ else if (declspecs->specs[(int)ds_thread]
+ && declspecs->storage_class != sc_extern
+ && declspecs->storage_class != sc_static)
{
error ("function-scope `%s' implicitly auto and declared `__thread'",
name);
- RIDBIT_RESET (RID_THREAD, specbits);
+ declspecs->specs[(int)ds_thread] = 0;
}
- if (nclasses > 0 && friendp)
+ if (declspecs->storage_class && friendp)
error ("storage class specifiers invalid in friend function declarations");
if (!id_declarator)
TREE_VALUE (quals));
quals = NULL_TREE;
}
- {
- RID_BIT_TYPE tmp_bits;
- memcpy (&tmp_bits, &specbits, sizeof (RID_BIT_TYPE));
- RIDBIT_RESET (RID_INLINE, tmp_bits);
- RIDBIT_RESET (RID_STATIC, tmp_bits);
- if (RIDBIT_ANY_SET (tmp_bits))
- error ("return value type specifier for constructor ignored");
- }
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
{
/* Cannot be both friend and virtual. */
error ("virtual functions cannot be friends");
- RIDBIT_RESET (RID_FRIEND, specbits);
friendp = 0;
}
if (decl_context == NORMAL)
return error_mark_node;
}
}
- else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
+ else if (declspecs->specs[(int)ds_typedef]
|| COMPLETE_TYPE_P (complete_type (ctype)))
{
/* Have to move this code elsewhere in this function.
explicitp = 0;
}
- if (RIDBIT_SETP (RID_MUTABLE, specbits))
+ if (declspecs->storage_class == sc_mutable)
{
if (decl_context != FIELD || friendp)
{
error ("non-member `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ declspecs->storage_class = sc_none;
}
- else if (decl_context == TYPENAME || RIDBIT_SETP (RID_TYPEDEF, specbits))
+ else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
{
error ("non-object member `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ declspecs->storage_class = sc_none;
}
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
error ("function `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ declspecs->storage_class = sc_none;
}
else if (staticp)
{
error ("static `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ declspecs->storage_class = sc_none;
}
else if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ declspecs->storage_class = sc_none;
}
}
/* If this is declaring a typedef name, return a TYPE_DECL. */
- if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
+ if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME)
{
tree decl;
grok_method_quals (ctype, decl, quals);
}
- if (RIDBIT_SETP (RID_SIGNED, specbits)
+ if (declspecs->specs[(int)ds_signed]
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (current_class_type
&& TYPE_NAME (current_class_type)
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))
- && declspecs && TREE_VALUE (declspecs)
- && TREE_TYPE (TREE_VALUE (declspecs)) == type)
+ && declspecs->type
+ && declspecs->type == type)
error (" in instantiation of template `%T'",
current_class_type);
{
decl = build_decl (FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
- if (RIDBIT_SETP (RID_MUTABLE, specbits))
+ if (declspecs->storage_class == sc_mutable)
{
DECL_MUTABLE_P (decl) = 1;
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ declspecs->storage_class = sc_none;
}
}
else
original_name = unqualified_id;
- if (RIDBIT_SETP (RID_AUTO, specbits))
+ if (declspecs->storage_class == sc_auto)
error ("storage class `auto' invalid for function `%s'", name);
- else if (RIDBIT_SETP (RID_REGISTER, specbits))
+ else if (declspecs->storage_class == sc_register)
error ("storage class `register' invalid for function `%s'", name);
- else if (RIDBIT_SETP (RID_THREAD, specbits))
+ else if (declspecs->specs[(int)ds_thread])
error ("storage class `__thread' invalid for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
if (! toplevel_bindings_p ()
- && (RIDBIT_SETP (RID_STATIC, specbits)
- || RIDBIT_SETP (RID_INLINE, specbits))
+ && (declspecs->storage_class == sc_static
+ || declspecs->specs[(int)ds_inline])
&& pedantic)
{
- if (RIDBIT_SETP (RID_STATIC, specbits))
- pedwarn ("storage class `static' invalid for function `%s' declared out of global scope", name);
+ if (declspecs->storage_class == sc_static)
+ pedwarn ("`static' specified invalid for function `%s' declared out of global scope", name);
else
- pedwarn ("storage class `inline' invalid for function `%s' declared out of global scope", name);
+ pedwarn ("`inline' specifier invalid for function `%s' declared out of global scope", name);
}
if (ctype == NULL_TREE)
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
- || RIDBIT_SETP (RID_EXTERN, specbits)
- || !RIDBIT_SETP (RID_STATIC, specbits));
+ || declspecs->storage_class == sc_extern
+ || declspecs->storage_class != sc_static);
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, quals, raises,
if (invalid_static)
{
staticp = 0;
- RIDBIT_RESET (RID_STATIC, specbits);
+ declspecs->storage_class = sc_none;
}
}
}
/* It's a variable. */
/* An uninitialized decl with `extern' is a reference. */
- decl = grokvardecl (type, unqualified_id, &specbits,
+ decl = grokvardecl (type, unqualified_id,
+ declspecs,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
{
pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
staticp = 0;
- RIDBIT_RESET (RID_STATIC, specbits);
+ declspecs->storage_class = sc_none;
}
- if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl))
+ if (declspecs->storage_class == sc_register && TREE_STATIC (decl))
{
error ("static member `%D' declared `register'", decl);
- RIDBIT_RESET (RID_REGISTER, specbits);
+ declspecs->storage_class = sc_none;
}
- if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic)
+ if (declspecs->storage_class == sc_extern && pedantic)
{
pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
decl);
- RIDBIT_RESET (RID_EXTERN, specbits);
+ declspecs->storage_class = sc_none;
}
}
}
- my_friendly_assert (!RIDBIT_SETP (RID_MUTABLE, specbits), 19990927);
-
/* Record `register' declaration for warnings on &
and in case doing stupid register allocation. */
- if (RIDBIT_SETP (RID_REGISTER, specbits))
+ if (declspecs->storage_class == sc_register)
DECL_REGISTER (decl) = 1;
-
- if (RIDBIT_SETP (RID_EXTERN, specbits))
+ else if (declspecs->storage_class == sc_extern)
DECL_THIS_EXTERN (decl) = 1;
-
- if (RIDBIT_SETP (RID_STATIC, specbits))
+ else if (declspecs->storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. There's no need to do this
*PARMS is set to the chain of PARM_DECLs created. */
static tree
-grokparms (const cp_parameter_declarator *first_parm, tree *parms)
+grokparms (cp_parameter_declarator *first_parm, tree *parms)
{
tree result = NULL_TREE;
tree decls = NULL_TREE;
int ellipsis = !first_parm || first_parm->ellipsis_p;
- const cp_parameter_declarator *parm;
+ cp_parameter_declarator *parm;
int any_error = 0;
for (parm = first_parm; parm != NULL; parm = parm->next)
{
tree type = NULL_TREE;
- tree decl_specifiers = parm->decl_specifiers;
tree init = parm->default_argument;
- tree specs, attrs;
+ tree attrs;
tree decl;
if (parm == no_parameters)
break;
- split_specs_attrs (decl_specifiers, &specs, &attrs);
- decl = grokdeclarator (parm->declarator, specs,
+ attrs = parm->decl_specifiers.attributes;
+ parm->decl_specifiers.attributes = NULL_TREE;
+ decl = grokdeclarator (parm->declarator, &parm->decl_specifiers,
PARM, init != NULL_TREE, &attrs);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
yyparse to report a parse error. */
int
-start_function (tree declspecs, const cp_declarator *declarator,
+start_function (cp_decl_specifier_seq *declspecs,
+ const cp_declarator *declarator,
tree attrs)
{
tree decl1;
if (have_extern_spec)
{
- declspecs = tree_cons (NULL_TREE, get_identifier ("extern"),
- declspecs);
+ declspecs->storage_class = sc_extern;
/* This should only be done once on the outermost decl. */
have_extern_spec = false;
}
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (tree declspecs, const cp_declarator *declarator, tree attrlist)
+start_method (cp_decl_specifier_seq *declspecs,
+ const cp_declarator *declarator, tree attrlist)
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
&attrlist);
};
/* We need this in here to get the decl_context definition. */
-extern tree grokdeclarator (const cp_declarator *, tree, enum decl_context, int, tree*);
+extern tree grokdeclarator (const cp_declarator *,
+ cp_decl_specifier_seq *,
+ enum decl_context, int, tree*);
#ifdef DEBUG_CP_BINDING_LEVELS
/* Purely for debugging purposes. */
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
-#include "lex.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
return this_quals;
}
-/* A subroutine of the parser, to handle a component list. */
-
-void
-grok_x_components (tree specs)
-{
- tree t;
-
- specs = strip_attrs (specs);
-
- check_tag_decl (specs);
- t = groktypename (specs, /*declarator=*/NULL);
-
- /* The only case where we need to do anything additional here is an
- anonymous union field, e.g.: `struct S { union { int i; }; };'. */
- if (t == NULL_TREE || !ANON_AGGR_TYPE_P (t))
- return;
-
- fixup_anonymous_aggr (t);
- finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t));
-}
-
/* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
appropriately. */
CHANGES TO CODE IN `start_method'. */
tree
-grokfield (const cp_declarator *declarator, tree declspecs,
+grokfield (const cp_declarator *declarator,
+ cp_decl_specifier_seq *declspecs,
tree init, tree asmspec_tree,
tree attrlist)
{
const char *asmspec = 0;
int flags = LOOKUP_ONLYCONVERTING;
- if (declspecs == NULL_TREE
+ if (!declspecs->any_specifiers_p
&& declarator->kind == cdk_id
&& TREE_CODE (declarator->u.id.name) == SCOPE_REF
&& (TREE_CODE (TREE_OPERAND (declarator->u.id.name, 1))
WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */
tree
-grokbitfield (const cp_declarator *declarator, tree declspecs, tree width)
+grokbitfield (const cp_declarator *declarator,
+ cp_decl_specifier_seq *declspecs, tree width)
{
tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL);
#include "tree.h"
#include "cp-tree.h"
#include "cpplib.h"
-#include "lex.h"
#include "flags.h"
#include "c-pragma.h"
#include "toplev.h"
+++ /dev/null
-/* Define constants and variables for communication with the parser.
- Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
- Hacked by Michael Tiemann (tiemann@cygnus.com)
- and by Brendan Kehoe (brendan@cygnus.com).
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
-
-
-#ifndef GCC_CP_LEX_H
-#define GCC_CP_LEX_H
-
-#if 0
-/* Formerly, the RID_* values used as mask bits did not fit into a
- single 32-bit word. Now they do, but let's preserve the old logic
- in case they ever stop fitting again. -zw, 8 Aug 2000 */
-
-/* The type that can represent all values of RIDBIT. */
-/* We assume that we can stick in at least 32 bits into this. */
-typedef struct { unsigned long idata[2]; }
- RID_BIT_TYPE;
-
-/* Be careful, all these modify N twice. */
-#define RIDBIT_SETP(N, V) (((unsigned long)1 << (int) ((N)%32)) \
- & (V).idata[(N)/32])
-#define RIDBIT_NOTSETP(NN, VV) (! RIDBIT_SETP (NN, VV))
-#define RIDBIT_SET(N, V) do { \
- (V).idata[(N)/32] \
- |= ((unsigned long)1 << (int) ((N)%32)); \
- } while (0)
-#define RIDBIT_RESET(N, V) do { \
- (V).idata[(N)/32] \
- &= ~((unsigned long)1 << (int) ((N)%32)); \
- } while (0)
-#define RIDBIT_RESET_ALL(V) do { \
- (V).idata[0] = 0; \
- (V).idata[1] = 0; \
- } while (0)
-#define RIDBIT_ANY_SET(V) ((V).idata[0] || (V).idata[1])
-#else
-typedef unsigned long RID_BIT_TYPE; /* assumed at least 32 bits */
-#define RIDBIT_OF(R) ((unsigned long)1 << (int) (R))
-
-#define RIDBIT_SETP(N, V) ((V) & RIDBIT_OF (N))
-#define RIDBIT_NOTSETP(N, V) (! ((V) & RIDBIT_OF (N)))
-#define RIDBIT_ANY_SET(V) (V)
-
-#define RIDBIT_SET(N, V) do { (V) |= RIDBIT_OF (N); } while (0)
-#define RIDBIT_RESET(N, V) do { (V) &= ~RIDBIT_OF (N); } while (0)
-#define RIDBIT_RESET_ALL(V) do { (V) = 0; } while (0)
-#endif
-
-#endif /* ! GCC_CP_LEX_H */
#include "diagnostic.h"
#include "toplev.h"
#include "output.h"
+#include "target.h"
\f
/* The lexer. */
}
\f
+/* Decl-specifiers. */
+
+static void clear_decl_specs
+ (cp_decl_specifier_seq *);
+
+/* Set *DECL_SPECS to represent an empty decl-specifier-seq. */
+
+static void
+clear_decl_specs (cp_decl_specifier_seq *decl_specs)
+{
+ memset (decl_specs, 0, sizeof (cp_decl_specifier_seq));
+}
+
/* Declarators. */
/* Nothing other than the parser should be creating declarators;
static cp_declarator *make_reference_declarator
(tree, cp_declarator *);
static cp_parameter_declarator *make_parameter_declarator
- (tree, cp_declarator *, tree);
+ (cp_decl_specifier_seq *, cp_declarator *, tree);
static cp_declarator *make_ptrmem_declarator
(tree, tree, cp_declarator *);
DECLARATOR and DEFAULT_ARGUMENT. */
cp_parameter_declarator *
-make_parameter_declarator (tree decl_specifiers,
+make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
cp_declarator *declarator,
tree default_argument)
{
parameter = ((cp_parameter_declarator *)
alloc_declarator (sizeof (cp_parameter_declarator)));
parameter->next = NULL;
- parameter->decl_specifiers = decl_specifiers;
+ if (decl_specifiers)
+ parameter->decl_specifiers = *decl_specifiers;
+ else
+ clear_decl_specs (¶meter->decl_specifiers);
parameter->declarator = declarator;
parameter->default_argument = default_argument;
parameter->ellipsis_p = false;
(cp_parser *, bool);
static void cp_parser_simple_declaration
(cp_parser *, bool);
-static tree cp_parser_decl_specifier_seq
- (cp_parser *, cp_parser_flags, tree *, int *);
+static void cp_parser_decl_specifier_seq
+ (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *);
static tree cp_parser_storage_class_specifier_opt
(cp_parser *);
static tree cp_parser_function_specifier_opt
- (cp_parser *);
+ (cp_parser *, cp_decl_specifier_seq *);
static tree cp_parser_type_specifier
- (cp_parser *, cp_parser_flags, bool, bool, int *, bool *);
+ (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, bool,
+ int *, bool *);
static tree cp_parser_simple_type_specifier
- (cp_parser *, cp_parser_flags, bool);
+ (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags);
static tree cp_parser_type_name
(cp_parser *);
static tree cp_parser_elaborated_type_specifier
/* Declarators [gram.dcl.decl] */
static tree cp_parser_init_declarator
- (cp_parser *, tree, tree, bool, bool, int, bool *);
+ (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *);
static cp_declarator *cp_parser_declarator
(cp_parser *, cp_parser_declarator_kind, int *, bool *);
static cp_declarator *cp_parser_direct_declarator
(cp_parser *);
static tree cp_parser_type_id
(cp_parser *);
-static tree cp_parser_type_specifier_seq
- (cp_parser *);
+static void cp_parser_type_specifier_seq
+ (cp_parser *, cp_decl_specifier_seq *);
static cp_parameter_declarator *cp_parser_parameter_declaration_clause
(cp_parser *);
static cp_parameter_declarator *cp_parser_parameter_declaration_list
static bool cp_parser_constructor_declarator_p
(cp_parser *, bool);
static tree cp_parser_function_definition_from_specifiers_and_declarator
- (cp_parser *, tree, tree, const cp_declarator *);
+ (cp_parser *, cp_decl_specifier_seq *, tree, const cp_declarator *);
static tree cp_parser_function_definition_after_declarator
(cp_parser *, bool);
static void cp_parser_template_declaration_after_export
static tree cp_parser_functional_cast
(cp_parser *, tree);
static tree cp_parser_save_member_function_body
- (cp_parser *, tree, cp_declarator *, tree);
+ (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree);
static tree cp_parser_enclosed_template_argument_list
(cp_parser *);
static void cp_parser_save_default_args
(cp_parser *, enum rid);
static bool cp_parser_declares_only_class_p
(cp_parser *);
+static void cp_parser_set_storage_class
+ (cp_decl_specifier_seq *, cp_storage_class);
+static void cp_parser_set_decl_spec_type
+ (cp_decl_specifier_seq *, tree, bool);
static bool cp_parser_friend_p
- (tree);
+ (const cp_decl_specifier_seq *);
static cp_token *cp_parser_require
(cp_parser *, enum cpp_ttype, const char *);
static cp_token *cp_parser_require_keyword
/* Create the error declarator. */
cp_error_declarator = make_declarator (cdk_error);
/* Create the empty parameter list. */
- no_parameters = make_parameter_declarator (NULL_TREE, NULL, NULL_TREE);
+ no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE);
/* Remember where the base of the declarator obstack lies. */
declarator_obstack_base = obstack_next_free (&declarator_obstack);
}
cp_parser_parse_tentatively (parser);
/* Look for the simple-type-specifier. */
type = cp_parser_simple_type_specifier (parser,
- CP_PARSER_FLAGS_NONE,
- /*identifier_p=*/false);
+ /*decl_specs=*/NULL,
+ CP_PARSER_FLAGS_NONE);
/* Parse the cast itself. */
if (!cp_parser_error_occurred (parser))
postfix_expression
static tree
cp_parser_new_type_id (cp_parser* parser, tree *nelts)
{
- tree type_specifier_seq;
+ cp_decl_specifier_seq type_specifier_seq;
cp_declarator *new_declarator;
cp_declarator *declarator;
cp_declarator *outer_declarator;
parser->type_definition_forbidden_message
= "types may not be defined in a new-type-id";
/* Parse the type-specifier-seq. */
- type_specifier_seq = cp_parser_type_specifier_seq (parser);
+ cp_parser_type_specifier_seq (parser, &type_specifier_seq);
/* Restore the old message. */
parser->type_definition_forbidden_message = saved_message;
/* Parse the new-declarator. */
new_declarator = NULL;
}
- type = groktypename (type_specifier_seq, new_declarator);
+ type = groktypename (&type_specifier_seq, new_declarator);
if (TREE_CODE (type) == ARRAY_TYPE && *nelts == NULL_TREE)
{
*nelts = array_type_nelts_top (type);
static tree
cp_parser_condition (cp_parser* parser)
{
- tree type_specifiers;
+ cp_decl_specifier_seq type_specifiers;
const char *saved_message;
/* Try the declaration first. */
parser->type_definition_forbidden_message
= "types may not be defined in conditions";
/* Parse the type-specifier-seq. */
- type_specifiers = cp_parser_type_specifier_seq (parser);
+ cp_parser_type_specifier_seq (parser, &type_specifiers);
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
/* If all is well, we might be looking at a declaration. */
if (cp_parser_parse_definitely (parser))
{
/* Create the declaration. */
- decl = start_decl (declarator, type_specifiers,
+ decl = start_decl (declarator, &type_specifiers,
/*initialized_p=*/true,
attributes, /*prefix_attributes=*/NULL_TREE);
/* Parse the assignment-expression. */
cp_parser_simple_declaration (cp_parser* parser,
bool function_definition_allowed_p)
{
- tree decl_specifiers;
- tree attributes;
+ cp_decl_specifier_seq decl_specifiers;
int declares_class_or_enum;
bool saw_declarator;
omitted only when declaring a class or enumeration, that is when
the decl-specifier-seq contains either a class-specifier, an
elaborated-type-specifier, or an enum-specifier. */
- decl_specifiers
- = cp_parser_decl_specifier_seq (parser,
- CP_PARSER_FLAGS_OPTIONAL,
- &attributes,
- &declares_class_or_enum);
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_OPTIONAL,
+ &decl_specifiers,
+ &declares_class_or_enum);
/* We no longer need to defer access checks. */
stop_deferring_access_checks ();
/* In a block scope, a valid declaration must always have a
decl-specifier-seq. By not trying to parse declarators, we can
resolve the declaration/expression ambiguity more quickly. */
- if (!function_definition_allowed_p && !decl_specifiers)
+ if (!function_definition_allowed_p
+ && !decl_specifiers.any_specifiers_p)
{
cp_parser_error (parser, "expected declaration");
goto done;
saw_declarator = true;
/* Parse the init-declarator. */
- decl = cp_parser_init_declarator (parser, decl_specifiers, attributes,
+ decl = cp_parser_init_declarator (parser, &decl_specifiers,
function_definition_allowed_p,
/*member_p=*/false,
declares_class_or_enum,
if (!saw_declarator)
{
if (cp_parser_declares_only_class_p (parser))
- shadow_tag (decl_specifiers);
+ shadow_tag (&decl_specifiers);
/* Perform any deferred access checks. */
perform_deferred_access_checks ();
}
decl-specifier:
attributes
- Returns a TREE_LIST, giving the decl-specifiers in the order they
- appear in the source code. The TREE_VALUE of each node is the
- decl-specifier. For a keyword (such as `auto' or `friend'), the
- TREE_VALUE is simply the corresponding TREE_IDENTIFIER. For the
- representation of a type-specifier, see cp_parser_type_specifier.
-
- If there are attributes, they will be stored in *ATTRIBUTES,
- represented as described above cp_parser_attributes.
+ Set *DECL_SPECS to a representation of the decl-specifier-seq.
If FRIEND_IS_NOT_CLASS_P is non-NULL, and the `friend' specifier
appears, and the entity that will be a friend is not going to be a
(i.e., a type declaration)
2: one of the decl-specifiers is an enum-specifier or a
class-specifier (i.e., a type definition)
-
+
*/
-static tree
+static void
cp_parser_decl_specifier_seq (cp_parser* parser,
- cp_parser_flags flags,
- tree* attributes,
+ cp_parser_flags flags,
+ cp_decl_specifier_seq *decl_specs,
int* declares_class_or_enum)
{
- tree decl_specs = NULL_TREE;
- bool friend_p = false;
bool constructor_possible_p = !parser->in_declarator_p;
+ /* Clear DECL_SPECS. */
+ clear_decl_specs (decl_specs);
+
/* Assume no class or enumeration type is declared. */
*declares_class_or_enum = 0;
- /* Assume there are no attributes. */
- *attributes = NULL_TREE;
-
/* Keep reading specifiers until there are no more to read. */
while (true)
{
- tree decl_spec = NULL_TREE;
bool constructor_p;
+ bool found_decl_spec;
cp_token *token;
/* Peek at the next token. */
if (token->keyword == RID_ATTRIBUTE)
{
/* Parse the attributes. */
- decl_spec = cp_parser_attributes_opt (parser);
- /* Add them to the list. */
- *attributes = chainon (*attributes, decl_spec);
+ decl_specs->attributes
+ = chainon (decl_specs->attributes,
+ cp_parser_attributes_opt (parser));
continue;
}
+ /* Assume we will find a decl-specifier keyword. */
+ found_decl_spec = true;
/* If the next token is an appropriate keyword, we can simply
add it to the list. */
switch (token->keyword)
{
- case RID_FRIEND:
/* decl-specifier:
friend */
- if (friend_p)
+ case RID_FRIEND:
+ if (decl_specs->specs[(int) ds_friend]++)
error ("duplicate `friend'");
- else
- friend_p = true;
- /* The representation of the specifier is simply the
- appropriate TREE_IDENTIFIER node. */
- decl_spec = token->value;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
break;
case RID_INLINE:
case RID_VIRTUAL:
case RID_EXPLICIT:
- decl_spec = cp_parser_function_specifier_opt (parser);
+ cp_parser_function_specifier_opt (parser, decl_specs);
break;
/* decl-specifier:
typedef */
case RID_TYPEDEF:
- /* The representation of the specifier is simply the
- appropriate TREE_IDENTIFIER node. */
- decl_spec = token->value;
+ ++decl_specs->specs[(int) ds_typedef];
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
/* A constructor declarator cannot appear in a typedef. */
GNU Extension:
thread */
case RID_AUTO:
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_set_storage_class (decl_specs, sc_auto);
+ break;
case RID_REGISTER:
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_set_storage_class (decl_specs, sc_register);
+ break;
case RID_STATIC:
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ if (decl_specs->specs[(int) ds_thread])
+ error ("`__thread' before `static'");
+ else
+ cp_parser_set_storage_class (decl_specs, sc_static);
+ break;
case RID_EXTERN:
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ if (decl_specs->specs[(int) ds_thread])
+ error ("`__thread' before `extern'");
+ else
+ cp_parser_set_storage_class (decl_specs, sc_extern);
+ break;
case RID_MUTABLE:
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_set_storage_class (decl_specs, sc_mutable);
+ break;
case RID_THREAD:
- decl_spec = cp_parser_storage_class_specifier_opt (parser);
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ ++decl_specs->specs[(int) ds_thread];
break;
default:
+ /* We did not yet find a decl-specifier yet. */
+ found_decl_spec = false;
break;
}
/* Constructors are a special case. The `S' in `S()' is not a
decl-specifier; it is the beginning of the declarator. */
- constructor_p = (!decl_spec
- && constructor_possible_p
- && cp_parser_constructor_declarator_p (parser,
- friend_p));
+ constructor_p
+ = (!found_decl_spec
+ && constructor_possible_p
+ && (cp_parser_constructor_declarator_p
+ (parser, decl_specs->specs[(int) ds_friend] != 0)));
/* If we don't have a DECL_SPEC yet, then we must be looking at
a type-specifier. */
- if (!decl_spec && !constructor_p)
+ if (!found_decl_spec && !constructor_p)
{
int decl_spec_declares_class_or_enum;
bool is_cv_qualifier;
+ tree type_spec;
- decl_spec
+ type_spec
= cp_parser_type_specifier (parser, flags,
- friend_p,
+ decl_specs,
/*is_declaration=*/true,
&decl_spec_declares_class_or_enum,
&is_cv_qualifier);
user-defined types. We *do* still allow things like `int
int' to be considered a decl-specifier-seq, and issue the
error message later. */
- if (decl_spec && !is_cv_qualifier)
+ if (type_spec && !is_cv_qualifier)
flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
/* A constructor declarator cannot follow a type-specifier. */
- if (decl_spec)
- constructor_possible_p = false;
- }
-
- /* If we still do not have a DECL_SPEC, then there are no more
- decl-specifiers. */
- if (!decl_spec)
- {
- /* Issue an error message, unless the entire construct was
- optional. */
- if (!(flags & CP_PARSER_FLAGS_OPTIONAL))
+ if (type_spec)
{
- cp_parser_error (parser, "expected decl specifier");
- return error_mark_node;
+ constructor_possible_p = false;
+ found_decl_spec = true;
}
-
- break;
}
- /* Add the DECL_SPEC to the list of specifiers. */
- if (decl_specs == NULL || TREE_VALUE (decl_specs) != error_mark_node)
- decl_specs = tree_cons (NULL_TREE, decl_spec, decl_specs);
+ /* If we still do not have a DECL_SPEC, then there are no more
+ decl-specifiers. */
+ if (!found_decl_spec)
+ break;
+ decl_specs->any_specifiers_p = true;
/* After we see one decl-specifier, further decl-specifiers are
always optional. */
flags |= CP_PARSER_FLAGS_OPTIONAL;
}
/* Don't allow a friend specifier with a class definition. */
- if (friend_p && (*declares_class_or_enum & 2))
+ if (decl_specs->specs[(int) ds_friend] != 0
+ && (*declares_class_or_enum & 2))
error ("class definition may not be declared a friend");
-
- /* We have built up the DECL_SPECS in reverse order. Return them in
- the correct order. */
- return nreverse (decl_specs);
}
/* Parse an (optional) storage-class-specifier.
virtual
explicit
- Returns an IDENTIFIER_NODE corresponding to the keyword used. */
+ Returns an IDENTIFIER_NODE corresponding to the keyword used.
+ Updates DECL_SPECS, if it is non-NULL. */
static tree
-cp_parser_function_specifier_opt (cp_parser* parser)
+cp_parser_function_specifier_opt (cp_parser* parser,
+ cp_decl_specifier_seq *decl_specs)
{
switch (cp_lexer_peek_token (parser->lexer)->keyword)
{
case RID_INLINE:
+ if (decl_specs)
+ ++decl_specs->specs[(int) ds_inline];
+ break;
+
case RID_VIRTUAL:
+ if (decl_specs)
+ ++decl_specs->specs[(int) ds_virtual];
+ break;
+
case RID_EXPLICIT:
- /* Consume the token. */
- return cp_lexer_consume_token (parser->lexer)->value;
+ if (decl_specs)
+ ++decl_specs->specs[(int) ds_explicit];
+ break;
default:
return NULL_TREE;
}
+
+ /* Consume the token. */
+ return cp_lexer_consume_token (parser->lexer)->value;
}
/* Parse a linkage-specification.
cp_parser_conversion_type_id (cp_parser* parser)
{
tree attributes;
- tree type_specifiers;
+ cp_decl_specifier_seq type_specifiers;
cp_declarator *declarator;
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
/* Parse the type-specifiers. */
- type_specifiers = cp_parser_type_specifier_seq (parser);
+ cp_parser_type_specifier_seq (parser, &type_specifiers);
/* If that didn't work, stop. */
- if (type_specifiers == error_mark_node)
+ if (type_specifiers.type == error_mark_node)
return error_mark_node;
/* Parse the conversion-declarator. */
declarator = cp_parser_conversion_declarator_opt (parser);
- return grokdeclarator (declarator, type_specifiers, TYPENAME,
+ return grokdeclarator (declarator, &type_specifiers, TYPENAME,
/*initialized=*/0, &attributes);
}
cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
{
cp_token *token;
- const cp_parameter_declarator *parameter_declarator;
+ cp_parameter_declarator *parameter_declarator;
/* Assume it is a type parameter or a template parameter. */
*is_non_type = false;
return (build_tree_list
(parameter_declarator->default_argument,
grokdeclarator (parameter_declarator->declarator,
- parameter_declarator->decl_specifiers,
+ ¶meter_declarator->decl_specifiers,
PARM, /*initialized=*/0,
/*attrlist=*/NULL)));
}
cp_parser_explicit_instantiation (cp_parser* parser)
{
int declares_class_or_enum;
- tree decl_specifiers;
- tree attributes;
+ cp_decl_specifier_seq decl_specifiers;
tree extension_specifier = NULL_TREE;
/* Look for an (optional) storage-class-specifier or
extension_specifier
= cp_parser_storage_class_specifier_opt (parser);
if (!extension_specifier)
- extension_specifier = cp_parser_function_specifier_opt (parser);
+ extension_specifier
+ = cp_parser_function_specifier_opt (parser,
+ /*decl_specs=*/NULL);
}
/* Look for the `template' keyword. */
control while processing explicit instantiation directives. */
push_deferring_access_checks (dk_no_check);
/* Parse a decl-specifier-seq. */
- decl_specifiers
- = cp_parser_decl_specifier_seq (parser,
- CP_PARSER_FLAGS_OPTIONAL,
- &attributes,
- &declares_class_or_enum);
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_OPTIONAL,
+ &decl_specifiers,
+ &declares_class_or_enum);
/* If there was exactly one decl-specifier, and it declared a class,
and there's no declarator, then we have an explicit type
instantiation. */
{
tree type;
- type = check_tag_decl (decl_specifiers);
+ type = check_tag_decl (&decl_specifiers);
/* Turn access control back on for names used during
template instantiation. */
pop_deferring_access_checks ();
declares_class_or_enum);
if (declarator != cp_error_declarator)
{
- decl = grokdeclarator (declarator, decl_specifiers,
+ decl = grokdeclarator (declarator, &decl_specifiers,
NORMAL, 0, NULL);
/* Turn access control back on for names used during
template instantiation. */
type-specifier:
__complex__
- Returns a representation of the type-specifier. If the
- type-specifier is a keyword (like `int' or `const', or
- `__complex__') then the corresponding IDENTIFIER_NODE is returned.
- For a class-specifier, enum-specifier, or elaborated-type-specifier
- a TREE_TYPE is returned; otherwise, a TYPE_DECL is returned.
+ Returns a representation of the type-specifier. For a
+ class-specifier, enum-specifier, or elaborated-type-specifier, a
+ TREE_TYPE is returned; otherwise, a TYPE_DECL is returned.
If IS_FRIEND is TRUE then this type-specifier is being declared a
`friend'. If IS_DECLARATION is TRUE, then this type-specifier is
static tree
cp_parser_type_specifier (cp_parser* parser,
cp_parser_flags flags,
- bool is_friend,
+ cp_decl_specifier_seq *decl_specs,
bool is_declaration,
int* declares_class_or_enum,
bool* is_cv_qualifier)
tree type_spec = NULL_TREE;
cp_token *token;
enum rid keyword;
+ cp_decl_spec ds = ds_last;
/* Assume this type-specifier does not declare a new type. */
if (declares_class_or_enum)
{
if (declares_class_or_enum)
*declares_class_or_enum = 2;
+ if (decl_specs)
+ cp_parser_set_decl_spec_type (decl_specs,
+ type_spec,
+ /*user_defined_p=*/true);
return type_spec;
}
case RID_TYPENAME:
/* Look for an elaborated-type-specifier. */
- type_spec = cp_parser_elaborated_type_specifier (parser,
- is_friend,
- is_declaration);
+ type_spec
+ = (cp_parser_elaborated_type_specifier
+ (parser,
+ decl_specs && decl_specs->specs[(int) ds_friend],
+ is_declaration));
/* We're declaring a class or enum -- unless we're using
`typename'. */
if (declares_class_or_enum && keyword != RID_TYPENAME)
*declares_class_or_enum = 1;
+ if (decl_specs)
+ cp_parser_set_decl_spec_type (decl_specs,
+ type_spec,
+ /*user_defined_p=*/true);
return type_spec;
case RID_CONST:
+ ds = ds_const;
+ if (is_cv_qualifier)
+ *is_cv_qualifier = true;
+ break;
+
case RID_VOLATILE:
- case RID_RESTRICT:
- type_spec = cp_parser_cv_qualifier_opt (parser);
- /* Even though we call a routine that looks for an optional
- qualifier, we know that there should be one. */
- my_friendly_assert (type_spec != NULL, 20000328);
- /* This type-specifier was a cv-qualified. */
+ ds = ds_volatile;
if (is_cv_qualifier)
*is_cv_qualifier = true;
+ break;
- return type_spec;
+ case RID_RESTRICT:
+ ds = ds_restrict;
+ if (is_cv_qualifier)
+ *is_cv_qualifier = true;
+ break;
case RID_COMPLEX:
/* The `__complex__' keyword is a GNU extension. */
- return cp_lexer_consume_token (parser->lexer)->value;
+ ds = ds_complex;
+ break;
default:
break;
}
+ /* Handle simple keywords. */
+ if (ds != ds_last)
+ {
+ if (decl_specs)
+ {
+ ++decl_specs->specs[(int)ds];
+ decl_specs->any_specifiers_p = true;
+ }
+ return cp_lexer_consume_token (parser->lexer)->value;
+ }
+
/* If we do not already have a type-specifier, assume we are looking
at a simple-type-specifier. */
- type_spec = cp_parser_simple_type_specifier (parser, flags,
- /*identifier_p=*/true);
+ type_spec = cp_parser_simple_type_specifier (parser,
+ decl_specs,
+ flags);
/* If we didn't find a type-specifier, and a type-specifier was not
optional in this context, issue an error message. */
__typeof__ unary-expression
__typeof__ ( type-id )
- For the various keywords, the value returned is simply the
- TREE_IDENTIFIER representing the keyword if IDENTIFIER_P is true.
- For the first two productions, and if IDENTIFIER_P is false, the
- value returned is the indicated TYPE_DECL. */
+ Returns the indicated TYPE_DECL. If DECL_SPECS is not NULL, it is
+ appropriately updated. */
static tree
-cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
- bool identifier_p)
+cp_parser_simple_type_specifier (cp_parser* parser,
+ cp_decl_specifier_seq *decl_specs,
+ cp_parser_flags flags)
{
tree type = NULL_TREE;
cp_token *token;
switch (token->keyword)
{
case RID_CHAR:
+ if (decl_specs)
+ decl_specs->explicit_char_p = true;
type = char_type_node;
break;
case RID_WCHAR:
type = boolean_type_node;
break;
case RID_SHORT:
+ if (decl_specs)
+ ++decl_specs->specs[(int) ds_short];
type = short_integer_type_node;
break;
case RID_INT:
+ if (decl_specs)
+ decl_specs->explicit_int_p = true;
type = integer_type_node;
break;
case RID_LONG:
+ if (decl_specs)
+ ++decl_specs->specs[(int) ds_long];
type = long_integer_type_node;
break;
case RID_SIGNED:
+ if (decl_specs)
+ ++decl_specs->specs[(int) ds_signed];
type = integer_type_node;
break;
case RID_UNSIGNED:
+ if (decl_specs)
+ ++decl_specs->specs[(int) ds_unsigned];
type = unsigned_type_node;
break;
case RID_FLOAT:
break;
case RID_TYPEOF:
- {
- tree operand;
-
- /* Consume the `typeof' token. */
- cp_lexer_consume_token (parser->lexer);
- /* Parse the operand to `typeof'. */
- operand = cp_parser_sizeof_operand (parser, RID_TYPEOF);
- /* If it is not already a TYPE, take its type. */
- if (!TYPE_P (operand))
- operand = finish_typeof (operand);
-
- return operand;
- }
+ /* Consume the `typeof' token. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the operand to `typeof'. */
+ type = cp_parser_sizeof_operand (parser, RID_TYPEOF);
+ /* If it is not already a TYPE, take its type. */
+ if (!TYPE_P (type))
+ type = finish_typeof (type);
+
+ if (decl_specs)
+ cp_parser_set_decl_spec_type (decl_specs, type,
+ /*user_defined_p=*/true);
+
+ return type;
default:
break;
{
tree id;
+ /* Record the type. */
+ if (decl_specs
+ && (token->keyword != RID_SIGNED
+ && token->keyword != RID_UNSIGNED
+ && token->keyword != RID_SHORT
+ && token->keyword != RID_LONG))
+ cp_parser_set_decl_spec_type (decl_specs,
+ type,
+ /*user_defined=*/false);
+ if (decl_specs)
+ decl_specs->any_specifiers_p = true;
+
/* Consume the token. */
id = cp_lexer_consume_token (parser->lexer)->value;
that the type was a template. */
cp_parser_check_for_invalid_template_id (parser, type);
- return identifier_p ? id : TYPE_NAME (type);
+ return TYPE_NAME (type);
}
/* The type-specifier must be a user-defined type. */
if ((flags & CP_PARSER_FLAGS_OPTIONAL)
&& !cp_parser_parse_definitely (parser))
type = NULL_TREE;
+ if (type && decl_specs)
+ cp_parser_set_decl_spec_type (decl_specs, type,
+ /*user_defined=*/true);
}
/* If we didn't get a type-name, issue an error message. */
static tree
cp_parser_init_declarator (cp_parser* parser,
- tree decl_specifiers,
- tree prefix_attributes,
+ cp_decl_specifier_seq *decl_specifiers,
bool function_definition_allowed_p,
bool member_p,
int declares_class_or_enum,
{
cp_token *token;
cp_declarator *declarator;
+ tree prefix_attributes;
tree attributes;
tree asm_specification;
tree initializer;
bool friend_p;
bool pop_p = false;
+ /* Gather the attributes that were provided with the
+ decl-specifiers. */
+ prefix_attributes = decl_specifiers->attributes;
+ decl_specifiers->attributes = NULL_TREE;
+
/* Assume that this is not the declarator for a function
definition. */
if (function_definition_p)
We explicitly postpone this check past the point where we handle
function-definitions because we tolerate function-definitions
that are missing their return types in some modes. */
- if (!decl_specifiers && ctor_dtor_or_conv_p <= 0)
+ if (!decl_specifiers->any_specifiers_p && ctor_dtor_or_conv_p <= 0)
{
cp_parser_error (parser,
"expected constructor, destructor, or type conversion");
sure this was intended to be a declarator. Then continue
declaring the variable(s), as int, to try to cut down on further
errors. */
- if (decl_specifiers != NULL
- && TREE_VALUE (decl_specifiers) == error_mark_node)
+ if (decl_specifiers->any_specifiers_p
+ && decl_specifiers->type == error_mark_node)
{
cp_parser_error (parser, "invalid type in declaration");
- TREE_VALUE (decl_specifiers) = integer_type_node;
+ decl_specifiers->type = integer_type_node;
}
/* Check to see whether or not this declaration is a friend. */
{
if (parser->in_unbraced_linkage_specification_p)
{
- decl_specifiers = tree_cons (error_mark_node,
- get_identifier ("extern"),
- decl_specifiers);
+ decl_specifiers->storage_class = sc_extern;
have_extern_spec = false;
}
decl = start_decl (declarator, decl_specifiers,
static tree
cp_parser_type_id (cp_parser* parser)
{
- tree type_specifier_seq;
+ cp_decl_specifier_seq type_specifier_seq;
cp_declarator *abstract_declarator;
/* Parse the type-specifier-seq. */
- type_specifier_seq
- = cp_parser_type_specifier_seq (parser);
- if (type_specifier_seq == error_mark_node)
+ cp_parser_type_specifier_seq (parser, &type_specifier_seq);
+ if (type_specifier_seq.type == error_mark_node)
return error_mark_node;
/* There might or might not be an abstract declarator. */
if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL;
- return groktypename (type_specifier_seq, abstract_declarator);
+ return groktypename (&type_specifier_seq, abstract_declarator);
}
/* Parse a type-specifier-seq.
type-specifier-seq:
attributes type-specifier-seq [opt]
- Returns a TREE_LIST. Either the TREE_VALUE of each node is a
- type-specifier, or the TREE_PURPOSE is a list of attributes. */
+ Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */
-static tree
-cp_parser_type_specifier_seq (cp_parser* parser)
+static void
+cp_parser_type_specifier_seq (cp_parser* parser,
+ cp_decl_specifier_seq *type_specifier_seq)
{
bool seen_type_specifier = false;
- tree type_specifier_seq = NULL_TREE;
+
+ /* Clear the TYPE_SPECIFIER_SEQ. */
+ clear_decl_specs (type_specifier_seq);
/* Parse the type-specifiers and attributes. */
while (true)
/* Check for attributes first. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
{
- type_specifier_seq = tree_cons (cp_parser_attributes_opt (parser),
- NULL_TREE,
- type_specifier_seq);
+ type_specifier_seq->attributes =
+ chainon (type_specifier_seq->attributes,
+ cp_parser_attributes_opt (parser));
continue;
}
- /* After the first type-specifier, others are optional. */
- if (seen_type_specifier)
- cp_parser_parse_tentatively (parser);
/* Look for the type-specifier. */
type_specifier = cp_parser_type_specifier (parser,
- CP_PARSER_FLAGS_NONE,
- /*is_friend=*/false,
+ CP_PARSER_FLAGS_OPTIONAL,
+ type_specifier_seq,
/*is_declaration=*/false,
NULL,
NULL);
/* If the first type-specifier could not be found, this is not a
type-specifier-seq at all. */
- if (!seen_type_specifier && type_specifier == error_mark_node)
- return error_mark_node;
+ if (!seen_type_specifier && !type_specifier)
+ {
+ cp_parser_error (parser, "expected type-specifier");
+ type_specifier_seq->type = error_mark_node;
+ return;
+ }
/* If subsequent type-specifiers could not be found, the
type-specifier-seq is complete. */
- else if (seen_type_specifier && !cp_parser_parse_definitely (parser))
+ else if (seen_type_specifier && !type_specifier)
break;
- /* Add the new type-specifier to the list. */
- type_specifier_seq
- = tree_cons (NULL_TREE, type_specifier, type_specifier_seq);
seen_type_specifier = true;
}
- /* We built up the list in reverse order. */
- return nreverse (type_specifier_seq);
+ return;
}
/* Parse a parameter-declaration-clause.
{
int declares_class_or_enum;
bool greater_than_is_operator_p;
- tree decl_specifiers;
- tree attributes;
+ cp_decl_specifier_seq decl_specifiers;
cp_declarator *declarator;
tree default_argument;
cp_token *token;
= "types may not be defined in parameter types";
/* Parse the declaration-specifiers. */
- decl_specifiers
- = cp_parser_decl_specifier_seq (parser,
- CP_PARSER_FLAGS_NONE,
- &attributes,
- &declares_class_or_enum);
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_NONE,
+ &decl_specifiers,
+ &declares_class_or_enum);
/* If an error occurred, there's no reason to attempt to parse the
rest of the declaration. */
if (cp_parser_error_occurred (parser))
parenthesized_p);
parser->default_arg_ok_p = saved_default_arg_ok_p;
/* After the declarator, allow more attributes. */
- attributes = chainon (attributes, cp_parser_attributes_opt (parser));
+ decl_specifiers.attributes
+ = chainon (decl_specifiers.attributes,
+ cp_parser_attributes_opt (parser));
}
/* The restriction on defining new types applies only to the type
else
default_argument = NULL_TREE;
- /* Create the representation of the parameter. */
- if (attributes)
- decl_specifiers = tree_cons (attributes, NULL_TREE, decl_specifiers);
-
- return make_parameter_declarator (decl_specifiers,
+ return make_parameter_declarator (&decl_specifiers,
declarator,
default_argument);
}
static void
cp_parser_member_declaration (cp_parser* parser)
{
- tree decl_specifiers;
+ cp_decl_specifier_seq decl_specifiers;
tree prefix_attributes;
tree decl;
int declares_class_or_enum;
}
/* Parse the decl-specifier-seq. */
- decl_specifiers
- = cp_parser_decl_specifier_seq (parser,
- CP_PARSER_FLAGS_OPTIONAL,
- &prefix_attributes,
- &declares_class_or_enum);
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_OPTIONAL,
+ &decl_specifiers,
+ &declares_class_or_enum);
+ prefix_attributes = decl_specifiers.attributes;
+ decl_specifiers.attributes = NULL_TREE;
/* Check for an invalid type-name. */
if (cp_parser_parse_and_diagnose_invalid_type_name (parser))
return;
Each member-declaration shall declare at least one member
name of the class. */
- if (!decl_specifiers)
+ if (!decl_specifiers.any_specifiers_p)
{
if (pedantic)
pedwarn ("extra semicolon");
tree type;
/* See if this declaration is a friend. */
- friend_p = cp_parser_friend_p (decl_specifiers);
+ friend_p = cp_parser_friend_p (&decl_specifiers);
/* If there were decl-specifiers, check to see if there was
a class-declaration. */
- type = check_tag_decl (decl_specifiers);
+ type = check_tag_decl (&decl_specifiers);
/* Nested classes have already been added to the class, but
a `friend' needs to be explicitly registered. */
if (friend_p)
A<T>::B will be represented by a TYPENAME_TYPE, and
therefore not recognized by check_tag_decl. */
- if (!type)
- {
- tree specifier;
-
- for (specifier = decl_specifiers;
- specifier;
- specifier = TREE_CHAIN (specifier))
- {
- tree s = TREE_VALUE (specifier);
-
- if (TREE_CODE (s) == IDENTIFIER_NODE)
- get_global_value_if_present (s, &type);
- if (TREE_CODE (s) == TYPE_DECL)
- s = TREE_TYPE (s);
- if (TYPE_P (s))
- {
- type = s;
- break;
- }
- }
- }
+ if (!type
+ && decl_specifiers.type
+ && TYPE_P (decl_specifiers.type))
+ type = decl_specifiers.type;
if (!type || !TYPE_P (type))
error ("friend declaration does not name a class or "
"function");
}
/* If there is no TYPE, an error message will already have
been issued. */
- else if (!type)
+ else if (!type || type == error_mark_node)
;
/* An anonymous aggregate has to be handled specially; such
a declaration really declares a data member (with a
else
{
/* See if these declarations will be friends. */
- friend_p = cp_parser_friend_p (decl_specifiers);
+ friend_p = cp_parser_friend_p (&decl_specifiers);
/* Keep going until we hit the `;' at the end of the
declaration. */
decl = grokbitfield (identifier
? make_id_declarator (identifier)
: NULL,
- decl_specifiers,
+ &decl_specifiers,
width);
/* Apply the attributes. */
cplus_decl_attributes (&decl, attributes, /*flags=*/0);
if (initializer)
error ("pure-specifier on function-definition");
decl = cp_parser_save_member_function_body (parser,
- decl_specifiers,
+ &decl_specifiers,
declarator,
attributes);
/* If the member was not a friend, declare it here. */
else
{
/* Create the declaration. */
- decl = grokfield (declarator, decl_specifiers,
+ decl = grokfield (declarator, &decl_specifiers,
initializer, asm_specification,
attributes);
/* Any initialization must have been from a
cp_parser_exception_declaration (cp_parser* parser)
{
tree decl;
- tree type_specifiers;
+ cp_decl_specifier_seq type_specifiers;
cp_declarator *declarator;
const char *saved_message;
= "types may not be defined in exception-declarations";
/* Parse the type-specifier-seq. */
- type_specifiers = cp_parser_type_specifier_seq (parser);
+ cp_parser_type_specifier_seq (parser, &type_specifiers);
/* If it's a `)', then there is no declarator. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
declarator = NULL;
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
- if (type_specifiers)
+ if (type_specifiers.any_specifiers_p)
{
- decl = grokdeclarator (declarator, type_specifiers, CATCHPARM, 1, NULL);
+ decl = grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL);
if (decl == NULL_TREE)
error ("invalid catch parameter");
}
/* Look for the type-specifier. */
cp_parser_type_specifier (parser,
CP_PARSER_FLAGS_NONE,
- /*is_friend=*/false,
+ /*decl_specs=*/NULL,
/*is_declarator=*/true,
/*declares_class_or_enum=*/NULL,
/*is_cv_qualifier=*/NULL);
static tree
cp_parser_function_definition_from_specifiers_and_declarator
(cp_parser* parser,
- tree decl_specifiers,
+ cp_decl_specifier_seq *decl_specifiers,
tree attributes,
const cp_declarator *declarator)
{
{
int declares_class_or_enum;
tree decl = NULL_TREE;
- tree decl_specifiers;
- tree attributes;
+ cp_decl_specifier_seq decl_specifiers;
bool function_definition_p = false;
/* Defer access checks until we know what is being declared. */
/* Try the `decl-specifier-seq [opt] init-declarator [opt]'
alternative. */
- decl_specifiers
- = cp_parser_decl_specifier_seq (parser,
- CP_PARSER_FLAGS_OPTIONAL,
- &attributes,
- &declares_class_or_enum);
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_OPTIONAL,
+ &decl_specifiers,
+ &declares_class_or_enum);
if (friend_p)
- *friend_p = cp_parser_friend_p (decl_specifiers);
+ *friend_p = cp_parser_friend_p (&decl_specifiers);
/* Gather up the access checks that occurred the
decl-specifier-seq. */
stop_deferring_access_checks ();
{
if (cp_parser_declares_only_class_p (parser))
{
- decl = shadow_tag (decl_specifiers);
- if (decl)
+ decl = shadow_tag (&decl_specifiers);
+ if (decl && decl != error_mark_node)
decl = TYPE_NAME (decl);
else
decl = error_mark_node;
In that case, there's no need to warn about a missing declarator. */
if (!decl
&& (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
- || !value_member (error_mark_node, decl_specifiers)))
+ || decl_specifiers.type != error_mark_node))
decl = cp_parser_init_declarator (parser,
- decl_specifiers,
- attributes,
+ &decl_specifiers,
/*function_definition_allowed_p=*/true,
member_p,
declares_class_or_enum,
static tree
cp_parser_save_member_function_body (cp_parser* parser,
- tree decl_specifiers,
+ cp_decl_specifier_seq *decl_specifiers,
cp_declarator *declarator,
tree attributes)
{
/* If all went well, then we're done. */
if (cp_parser_parse_definitely (parser))
{
- /* Build a list of decl-specifiers; right now, we have only
- a single type-specifier. */
- type = build_tree_list (NULL_TREE,
- type);
+ cp_decl_specifier_seq decl_specs;
+
+ /* Build a trivial decl-specifier-seq. */
+ clear_decl_specs (&decl_specs);
+ decl_specs.type = type;
/* Call grokdeclarator to figure out what type this is. */
expr = grokdeclarator (NULL,
- type,
+ &decl_specs,
TYPENAME,
/*initialized=*/0,
/*attrlist=*/NULL);
|| cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
}
-/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
- Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */
+/* Update the DECL_SPECS to reflect the STORAGE_CLASS. */
-static bool
-cp_parser_friend_p (tree decl_specifiers)
+static void
+cp_parser_set_storage_class (cp_decl_specifier_seq *decl_specs,
+ cp_storage_class storage_class)
{
- while (decl_specifiers)
- {
- /* See if this decl-specifier is `friend'. */
- if (TREE_CODE (TREE_VALUE (decl_specifiers)) == IDENTIFIER_NODE
- && C_RID_CODE (TREE_VALUE (decl_specifiers)) == RID_FRIEND)
- return true;
+ if (decl_specs->storage_class != sc_none)
+ decl_specs->multiple_storage_classes_p = true;
+ else
+ decl_specs->storage_class = storage_class;
+}
+
+/* Update the DECL_SPECS to reflect the TYPE_SPEC. If USER_DEFINED_P
+ is true, the type is a user-defined type; otherwise it is a
+ built-in type specified by a keyword. */
- /* Go on to the next decl-specifier. */
- decl_specifiers = TREE_CHAIN (decl_specifiers);
+static void
+cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
+ tree type_spec,
+ bool user_defined_p)
+{
+ decl_specs->any_specifiers_p = true;
+ if (decl_specs->type)
+ {
+ if (decl_specs->specs[(int)ds_typedef] && !user_defined_p)
+ decl_specs->redefined_builtin_type = type_spec;
+ else
+ decl_specs->multiple_types_p = true;
+ }
+ else
+ {
+ decl_specs->type = type_spec;
+ decl_specs->user_defined_type_p = user_defined_p;
}
+}
- return false;
+/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
+ Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */
+
+static bool
+cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers)
+{
+ return decl_specifiers->specs[(int) ds_friend] != 0;
}
/* If the next token is of the indicated TYPE, consume it. Otherwise,
#include "cp-tree.h"
#include "tree-inline.h"
#include "decl.h"
-#include "lex.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "tree-inline.h"
#include "tree-mudflap.h"
#include "except.h"
-#include "lex.h"
#include "toplev.h"
#include "flags.h"
#include "rtl.h"
}
}
-/* Finish processing the declaration of a member class template
- TYPES whose template parameters are given by PARMS. */
-
-tree
-finish_member_class_template (tree types)
-{
- tree t;
-
- /* If there are declared, but undefined, partial specializations
- mixed in with the typespecs they will not yet have passed through
- maybe_process_partial_specialization, so we do that here. */
- for (t = types; t != NULL_TREE; t = TREE_CHAIN (t))
- if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t))))
- maybe_process_partial_specialization (TREE_VALUE (t));
-
- grok_x_components (types);
- if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
- /* The component was in fact a friend declaration. We avoid
- finish_member_template_decl performing certain checks by
- unsetting TYPES. */
- types = NULL_TREE;
-
- finish_member_template_decl (types);
-
- /* As with other component type declarations, we do
- not store the new DECL on the list of
- component_decls. */
- return NULL_TREE;
-}
-
/* Finish processing a complete template declaration. The PARMS are
the template parameters. */