This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Do not build TREE_LISTs of cv-qualifiers
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 26 Jun 2004 20:09:23 -0700
- Subject: C++ PATCH: Do not build TREE_LISTs of cv-qualifiers
- Reply-to: mark at codesourcery dot com
Here's another little memory-saving patch. We were building a
TREE_LIST node for every cv-qualifier appearing in the input program,
which is totally pointless. We could have at least reused the same
TREE_LISTs (there are only a few combinations of "const", "volatile",
and "restrict") but even better is just to use a bitmask. Not a
terribly big win, but I could do it while I was tired, and the code
becomes a bit simpler to boot. :-)
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-06-26 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (cp_cv_quals): New type.
(cp_declarator): Use it instead of "tree" as appropriate.
(grok_method_quals): Adjust prototype.
(grokclassfn): Likewise.
(do_friend): Likewise.
* decl.c (grokfndecl): Use cp_cv_quals, not tree.
(grokdeclarator): Likewise.
* decl2.c (grok_method_quals): Likewise.
(grokclassfn): Likewise.
* friend.c (do_friend): Likewise.
* method.c (implicitly_declare_fn): Adjust call to grokclassfn.
* parser.c (make_call_declarator): Use cp_cv_quals, not tree.
(make_pointer_declarator): Likewise.
(make_reference_declarator): Likewise.
(make_ptrmem_declarator): Likewise.
(cp_parser_ptr_operator): Likewise.
(cp_parser_cv_qualifier_seq_opt): Likewise.
(cp_parser_cv_qualifier_opt): Remove.
(cp_parser_new_declarator_opt): Adjust call to
cp_parser_ptr_operator.
(cp_parser_conversion_declaration_opt): Likewise.
(cp_parser_declarator): Use cp_cv_quals, not tree.
(cp_parser_direct_declarator): Likewise.
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.989
diff -c -5 -p -r1.989 cp-tree.h
*** cp-tree.h 26 Jun 2004 21:11:17 -0000 1.989
--- cp-tree.h 27 Jun 2004 02:10:42 -0000
*************** extern GTY(()) operator_name_info_t oper
*** 3501,3510 ****
--- 3501,3515 ----
[(int) LAST_CPLUS_TREE_CODE];
/* Similar, but for assignment operators. */
extern GTY(()) operator_name_info_t assignment_operator_name_info
[(int) LAST_CPLUS_TREE_CODE];
+ /* A type-qualifier, or bitmask therefore, using the TYPE_QUAL
+ constants. */
+
+ typedef int cp_cv_quals;
+
/* 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. */
*************** struct cp_declarator {
*** 3626,3636 ****
/* For functions. */
struct {
/* The parameters to the function. */
cp_parameter_declarator *parameters;
/* The cv-qualifiers for the function. */
! tree qualifiers;
/* The exception-specification for the function. */
tree exception_specification;
} function;
/* For arrays. */
struct {
--- 3631,3641 ----
/* For functions. */
struct {
/* The parameters to the function. */
cp_parameter_declarator *parameters;
/* The cv-qualifiers for the function. */
! cp_cv_quals qualifiers;
/* The exception-specification for the function. */
tree exception_specification;
} function;
/* For arrays. */
struct {
*************** struct cp_declarator {
*** 3638,3648 ****
tree bounds;
} array;
/* For cdk_pointer, cdk_reference, and cdk_ptrmem. */
struct {
/* The cv-qualifiers for the pointer. */
! tree qualifiers;
/* For cdk_ptrmem, the class type containing the member. */
tree class_type;
} pointer;
} u;
};
--- 3643,3653 ----
tree bounds;
} array;
/* For cdk_pointer, cdk_reference, and cdk_ptrmem. */
struct {
/* The cv-qualifiers for the pointer. */
! cp_cv_quals qualifiers;
/* For cdk_ptrmem, the class type containing the member. */
tree class_type;
} pointer;
} u;
};
*************** extern bool cp_missing_noreturn_ok_p (t
*** 3864,3877 ****
extern bool have_extern_spec;
/* in decl2.c */
extern bool check_java_method (tree);
! extern int grok_method_quals (tree, tree, 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 grok_array_decl (tree, 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 *, cp_decl_specifier_seq *, tree, tree, tree);
--- 3869,3882 ----
extern bool have_extern_spec;
/* in decl2.c */
extern bool check_java_method (tree);
! extern cp_cv_quals grok_method_quals (tree, tree, cp_cv_quals);
extern void maybe_retrofit_in_chrg (tree);
extern void maybe_make_one_only (tree);
! extern void grokclassfn (tree, tree, enum overload_flags, cp_cv_quals);
extern tree grok_array_decl (tree, 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 *, cp_decl_specifier_seq *, tree, tree, tree);
*************** extern tree cplus_expand_constant
*** 3939,3949 ****
/* friend.c */
extern int is_friend (tree, tree);
extern void make_friend_class (tree, tree, bool);
extern void add_friend (tree, tree, bool);
! extern tree do_friend (tree, tree, tree, tree, enum overload_flags, tree, int);
/* in init.c */
extern tree expand_member_init (tree);
extern void emit_mem_initializers (tree);
extern tree build_aggr_init (tree, tree, int);
--- 3944,3954 ----
/* friend.c */
extern int is_friend (tree, tree);
extern void make_friend_class (tree, tree, bool);
extern void add_friend (tree, tree, bool);
! extern tree do_friend (tree, tree, tree, tree, enum overload_flags, cp_cv_quals, int);
/* in init.c */
extern tree expand_member_init (tree);
extern void emit_mem_initializers (tree);
extern tree build_aggr_init (tree, tree, int);
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1228
diff -c -5 -p -r1.1228 decl.c
*** decl.c 26 Jun 2004 21:11:17 -0000 1.1228
--- decl.c 27 Jun 2004 02:10:42 -0000
*************** static void require_complete_types_for_p
*** 60,70 ****
static int ambi_op_p (enum tree_code);
static int unary_op_p (enum tree_code);
static void push_local_name (tree);
static tree grok_reference_init (tree, tree, tree, 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, 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 *,
--- 60,70 ----
static int ambi_op_p (enum tree_code);
static int unary_op_p (enum tree_code);
static void push_local_name (tree);
static tree grok_reference_init (tree, tree, tree, tree *);
static tree grokfndecl (tree, tree, tree, tree, tree, int,
! enum overload_flags, cp_cv_quals,
tree, int, int, int, int, 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 *,
*************** grokfndecl (tree ctype,
*** 5422,5432 ****
tree declarator,
tree parms,
tree orig_declarator,
int virtualp,
enum overload_flags flags,
! tree quals,
tree raises,
int check,
int friendp,
int publicp,
int inlinep,
--- 5422,5432 ----
tree declarator,
tree parms,
tree orig_declarator,
int virtualp,
enum overload_flags flags,
! cp_cv_quals quals,
tree raises,
int check,
int friendp,
int publicp,
int inlinep,
*************** grokfndecl (tree ctype,
*** 5542,5556 ****
if (DECL_DECLARED_INLINE_P (decl)
|| (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag))
DECL_INLINE (decl) = 1;
DECL_EXTERNAL (decl) = 1;
! if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
{
! error ("%smember function `%D' cannot have `%T' method qualifier",
! (ctype ? "static " : "non-"), decl, TREE_VALUE (quals));
! quals = NULL_TREE;
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
grok_op_properties (decl, friendp, /*complain=*/true);
--- 5542,5556 ----
if (DECL_DECLARED_INLINE_P (decl)
|| (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag))
DECL_INLINE (decl) = 1;
DECL_EXTERNAL (decl) = 1;
! if (quals && TREE_CODE (type) == FUNCTION_TYPE)
{
! error ("%smember function `%D' cannot have cv-qualifier",
! (ctype ? "static " : "non-"), decl);
! quals = TYPE_UNQUALIFIED;
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
grok_op_properties (decl, friendp, /*complain=*/true);
*************** grokdeclarator (const cp_declarator *dec
*** 6285,6295 ****
special_function_kind sfk = sfk_none;
tree dname = NULL_TREE;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
! tree quals = NULL_TREE;
tree raises = NULL_TREE;
int template_count = 0;
tree returned_attrs = NULL_TREE;
tree parms = NULL_TREE;
const cp_declarator *id_declarator;
--- 6285,6295 ----
special_function_kind sfk = sfk_none;
tree dname = NULL_TREE;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
! cp_cv_quals quals = TYPE_UNQUALIFIED;
tree raises = NULL_TREE;
int template_count = 0;
tree returned_attrs = NULL_TREE;
tree parms = NULL_TREE;
const cp_declarator *id_declarator;
*************** grokdeclarator (const cp_declarator *dec
*** 7047,7059 ****
not be static. */
if (staticp == 2)
error ("destructor cannot be static member function");
if (quals)
{
! error ("destructors may not be `%E'",
! TREE_VALUE (quals));
! quals = NULL_TREE;
}
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
current_class_type,
--- 7047,7058 ----
not be static. */
if (staticp == 2)
error ("destructor cannot be static member function");
if (quals)
{
! error ("destructors may not be cv-qualified");
! quals = TYPE_UNQUALIFIED;
}
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
current_class_type,
*************** grokdeclarator (const cp_declarator *dec
*** 7076,7088 ****
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
if (quals)
{
! error ("constructors may not be `%E'",
! TREE_VALUE (quals));
! quals = NULL_TREE;
}
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
current_class_type,
--- 7075,7086 ----
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
if (quals)
{
! error ("constructors may not be cv-qualified");
! quals = TYPE_UNQUALIFIED;
}
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
current_class_type,
*************** grokdeclarator (const cp_declarator *dec
*** 7161,7171 ****
{
tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
grok_method_quals (declarator->u.pointer.class_type,
dummy, quals);
type = TREE_TYPE (dummy);
! quals = NULL_TREE;
}
if (declarator->kind == cdk_reference)
{
if (!VOID_TYPE_P (type))
--- 7159,7169 ----
{
tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
grok_method_quals (declarator->u.pointer.class_type,
dummy, quals);
type = TREE_TYPE (dummy);
! quals = TYPE_UNQUALIFIED;
}
if (declarator->kind == cdk_reference)
{
if (!VOID_TYPE_P (type))
*************** grokdeclarator (const cp_declarator *dec
*** 7182,7230 ****
/* Process a list of type modifier keywords (such as
const or volatile) that were given inside the `*' or `&'. */
if (declarator->u.pointer.qualifiers)
{
! tree typemodlist;
! int erred = 0;
! int constp = 0;
! int volatilep = 0;
! int restrictp = 0;
!
! for (typemodlist = declarator->u.pointer.qualifiers; typemodlist;
! typemodlist = TREE_CHAIN (typemodlist))
! {
! tree qualifier = TREE_VALUE (typemodlist);
!
! if (qualifier == ridpointers[(int) RID_CONST])
! {
! constp++;
! type_quals |= TYPE_QUAL_CONST;
! }
! else if (qualifier == ridpointers[(int) RID_VOLATILE])
! {
! volatilep++;
! type_quals |= TYPE_QUAL_VOLATILE;
! }
! else if (qualifier == ridpointers[(int) RID_RESTRICT])
! {
! restrictp++;
! type_quals |= TYPE_QUAL_RESTRICT;
! }
! else if (!erred)
! {
! erred = 1;
! error ("invalid type modifier within pointer declarator");
! }
! }
! if (constp > 1)
! pedwarn ("duplicate `const'");
! if (volatilep > 1)
! pedwarn ("duplicate `volatile'");
! if (restrictp > 1)
! pedwarn ("duplicate `restrict'");
! type = cp_build_qualified_type (type, type_quals);
type_quals = cp_type_quals (type);
}
ctype = NULL_TREE;
break;
--- 7180,7192 ----
/* Process a list of type modifier keywords (such as
const or volatile) that were given inside the `*' or `&'. */
if (declarator->u.pointer.qualifiers)
{
! type
! = cp_build_qualified_type (type,
! declarator->u.pointer.qualifiers);
type_quals = cp_type_quals (type);
}
ctype = NULL_TREE;
break;
*************** grokdeclarator (const cp_declarator *dec
*** 7486,7496 ****
if (declspecs->specs[(int)ds_signed]
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
! bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
return decl;
}
--- 7448,7458 ----
if (declspecs->specs[(int)ds_signed]
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
! bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
return decl;
}
*************** grokdeclarator (const cp_declarator *dec
*** 7652,7662 ****
if (decl_context == PARM)
{
decl = cp_build_parm_decl (unqualified_id, type);
! bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
}
else if (decl_context == FIELD)
{
/* The C99 flexible array extension. */
--- 7614,7624 ----
if (decl_context == PARM)
{
decl = cp_build_parm_decl (unqualified_id, type);
! bad_specifiers (decl, "parameter", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
else if (decl_context == FIELD)
{
/* The C99 flexible array extension. */
*************** grokdeclarator (const cp_declarator *dec
*** 7906,7916 ****
DECL_MUTABLE_P (decl) = 1;
declspecs->storage_class = sc_none;
}
}
! bad_specifiers (decl, "field", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
}
}
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
--- 7868,7878 ----
DECL_MUTABLE_P (decl) = 1;
declspecs->storage_class = sc_none;
}
}
! bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
}
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
*************** grokdeclarator (const cp_declarator *dec
*** 8007,8017 ****
decl = grokvardecl (type, unqualified_id,
declspecs,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
! bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
if (ctype)
{
DECL_CONTEXT (decl) = ctype;
--- 7969,7979 ----
decl = grokvardecl (type, unqualified_id,
declspecs,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
! bad_specifiers (decl, "variable", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
if (ctype)
{
DECL_CONTEXT (decl) = ctype;
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.722
diff -c -5 -p -r1.722 decl2.c
*** decl2.c 26 Jun 2004 21:11:18 -0000 1.722
--- decl2.c 27 Jun 2004 02:10:42 -0000
*************** tree static_dtors;
*** 116,150 ****
QUALS is a list of qualifiers. Returns any explicit
top-level qualifiers of the method's this pointer, anything other than
TYPE_UNQUALIFIED will be an extension. */
int
! grok_method_quals (tree ctype, tree function, tree quals)
{
tree fntype = TREE_TYPE (function);
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
int type_quals = TYPE_UNQUALIFIED;
- int dup_quals = TYPE_UNQUALIFIED;
int this_quals = TYPE_UNQUALIFIED;
! while (quals)
! {
! int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
!
! if ((type_quals | this_quals) & tq)
! dup_quals |= tq;
! else if (tq & TYPE_QUAL_RESTRICT)
! this_quals |= tq;
! else
! type_quals |= tq;
! quals = TREE_CHAIN (quals);
! }
!
! if (dup_quals != TYPE_UNQUALIFIED)
! error ("duplicate type qualifiers in %s declaration",
! TREE_CODE (function) == FUNCTION_DECL
! ? "member function" : "type");
ctype = cp_build_qualified_type (ctype, type_quals);
fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
(TREE_CODE (fntype) == METHOD_TYPE
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
--- 116,134 ----
QUALS is a list of qualifiers. Returns any explicit
top-level qualifiers of the method's this pointer, anything other than
TYPE_UNQUALIFIED will be an extension. */
int
! grok_method_quals (tree ctype, tree function, cp_cv_quals quals)
{
tree fntype = TREE_TYPE (function);
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
int type_quals = TYPE_UNQUALIFIED;
int this_quals = TYPE_UNQUALIFIED;
! type_quals = quals & ~TYPE_QUAL_RESTRICT;
! this_quals = quals & TYPE_QUAL_RESTRICT;
ctype = cp_build_qualified_type (ctype, type_quals);
fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
(TREE_CODE (fntype) == METHOD_TYPE
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
*************** maybe_retrofit_in_chrg (tree fn)
*** 279,292 ****
way the rest of the arguments were declared.
QUALS are the qualifiers for the this pointer. */
void
! grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
{
tree fn_name = DECL_NAME (function);
! int this_quals = TYPE_UNQUALIFIED;
/* Even within an `extern "C"' block, members get C++ linkage. See
[dcl.link] for details. */
SET_DECL_LANGUAGE (function, lang_cplusplus);
--- 263,277 ----
way the rest of the arguments were declared.
QUALS are the qualifiers for the this pointer. */
void
! grokclassfn (tree ctype, tree function, enum overload_flags flags,
! cp_cv_quals quals)
{
tree fn_name = DECL_NAME (function);
! cp_cv_quals this_quals = TYPE_UNQUALIFIED;
/* Even within an `extern "C"' block, members get C++ linkage. See
[dcl.link] for details. */
SET_DECL_LANGUAGE (function, lang_cplusplus);
Index: friend.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/friend.c,v
retrieving revision 1.97
diff -c -5 -p -r1.97 friend.c
*** friend.c 31 May 2004 22:47:56 -0000 1.97
--- friend.c 27 Jun 2004 02:10:42 -0000
*************** make_friend_class (tree type, tree frien
*** 323,333 ****
QUALS say what special qualifies should apply to the object
pointed to by `this'. */
tree
do_friend (tree ctype, tree declarator, tree decl,
! tree attrlist, enum overload_flags flags, tree quals,
int funcdef_flag)
{
/* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1;
--- 323,334 ----
QUALS say what special qualifies should apply to the object
pointed to by `this'. */
tree
do_friend (tree ctype, tree declarator, tree decl,
! tree attrlist, enum overload_flags flags,
! cp_cv_quals quals,
int funcdef_flag)
{
/* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1;
Index: method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.288
diff -c -5 -p -r1.288 method.c
*** method.c 22 Jun 2004 07:18:36 -0000 1.288
--- method.c 27 Jun 2004 02:10:42 -0000
*************** implicitly_declare_fn (special_function_
*** 1018,1028 ****
DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
}
grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
! /*quals=*/NULL_TREE);
grok_special_member_properties (fn);
cp_finish_decl (fn, /*init=*/NULL_TREE, /*asmspec_tree=*/NULL_TREE,
/*flags=*/LOOKUP_ONLYCONVERTING);
DECL_IN_AGGR_P (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
--- 1018,1028 ----
DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
}
grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
! TYPE_UNQUALIFIED);
grok_special_member_properties (fn);
cp_finish_decl (fn, /*init=*/NULL_TREE, /*asmspec_tree=*/NULL_TREE,
/*flags=*/LOOKUP_ONLYCONVERTING);
DECL_IN_AGGR_P (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.217
diff -c -5 -p -r1.217 parser.c
*** parser.c 26 Jun 2004 21:11:19 -0000 1.217
--- parser.c 27 Jun 2004 02:10:43 -0000
*************** clear_decl_specs (cp_decl_specifier_seq
*** 1017,1037 ****
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
static cp_declarator *make_id_declarator
(tree);
static cp_declarator *make_call_declarator
! (cp_declarator *, cp_parameter_declarator *, tree, tree);
static cp_declarator *make_array_declarator
(cp_declarator *, tree);
static cp_declarator *make_pointer_declarator
! (tree, cp_declarator *);
static cp_declarator *make_reference_declarator
! (tree, cp_declarator *);
static cp_parameter_declarator *make_parameter_declarator
(cp_decl_specifier_seq *, cp_declarator *, tree);
static cp_declarator *make_ptrmem_declarator
! (tree, tree, cp_declarator *);
cp_declarator *cp_error_declarator;
/* The obstack on which declarators and related data structures are
allocated. */
--- 1017,1037 ----
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
static cp_declarator *make_id_declarator
(tree);
static cp_declarator *make_call_declarator
! (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree);
static cp_declarator *make_array_declarator
(cp_declarator *, tree);
static cp_declarator *make_pointer_declarator
! (cp_cv_quals, cp_declarator *);
static cp_declarator *make_reference_declarator
! (cp_cv_quals, cp_declarator *);
static cp_parameter_declarator *make_parameter_declarator
(cp_decl_specifier_seq *, cp_declarator *, tree);
static cp_declarator *make_ptrmem_declarator
! (cp_cv_quals, tree, cp_declarator *);
cp_declarator *cp_error_declarator;
/* The obstack on which declarators and related data structures are
allocated. */
*************** make_id_declarator (tree id)
*** 1078,1088 ****
/* Make a declarator for a pointer to TARGET. CV_QUALIFIERS is a list
of modifiers such as const or volatile to apply to the pointer
type, represented as identifiers. */
cp_declarator *
! make_pointer_declarator (tree cv_qualifiers, cp_declarator *target)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_pointer);
declarator->declarator = target;
--- 1078,1088 ----
/* Make a declarator for a pointer to TARGET. CV_QUALIFIERS is a list
of modifiers such as const or volatile to apply to the pointer
type, represented as identifiers. */
cp_declarator *
! make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_pointer);
declarator->declarator = target;
*************** make_pointer_declarator (tree cv_qualifi
*** 1093,1103 ****
}
/* Like make_pointer_declarator -- but for references. */
cp_declarator *
! make_reference_declarator (tree cv_qualifiers, cp_declarator *target)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_reference);
declarator->declarator = target;
--- 1093,1103 ----
}
/* Like make_pointer_declarator -- but for references. */
cp_declarator *
! make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_reference);
declarator->declarator = target;
*************** make_reference_declarator (tree cv_quali
*** 1109,1119 ****
/* Like make_pointer_declarator -- but for a pointer to a non-static
member of CLASS_TYPE. */
cp_declarator *
! make_ptrmem_declarator (tree cv_qualifiers, tree class_type,
cp_declarator *pointee)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_ptrmem);
--- 1109,1119 ----
/* Like make_pointer_declarator -- but for a pointer to a non-static
member of CLASS_TYPE. */
cp_declarator *
! make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
cp_declarator *pointee)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_ptrmem);
*************** make_ptrmem_declarator (tree cv_qualifie
*** 1130,1140 ****
indicates what exceptions can be thrown. */
cp_declarator *
make_call_declarator (cp_declarator *target,
cp_parameter_declarator *parms,
! tree cv_qualifiers,
tree exception_specification)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_function);
--- 1130,1140 ----
indicates what exceptions can be thrown. */
cp_declarator *
make_call_declarator (cp_declarator *target,
cp_parameter_declarator *parms,
! cp_cv_quals cv_qualifiers,
tree exception_specification)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_function);
*************** static tree cp_parser_init_declarator
*** 1691,1704 ****
static cp_declarator *cp_parser_declarator
(cp_parser *, cp_parser_declarator_kind, int *, bool *);
static cp_declarator *cp_parser_direct_declarator
(cp_parser *, cp_parser_declarator_kind, int *);
static enum tree_code cp_parser_ptr_operator
! (cp_parser *, tree *, tree *);
! static tree cp_parser_cv_qualifier_seq_opt
! (cp_parser *);
! static tree cp_parser_cv_qualifier_opt
(cp_parser *);
static tree cp_parser_declarator_id
(cp_parser *);
static tree cp_parser_type_id
(cp_parser *);
--- 1691,1702 ----
static cp_declarator *cp_parser_declarator
(cp_parser *, cp_parser_declarator_kind, int *, bool *);
static cp_declarator *cp_parser_direct_declarator
(cp_parser *, cp_parser_declarator_kind, int *);
static enum tree_code cp_parser_ptr_operator
! (cp_parser *, tree *, cp_cv_quals *);
! static cp_cv_quals cp_parser_cv_qualifier_seq_opt
(cp_parser *);
static tree cp_parser_declarator_id
(cp_parser *);
static tree cp_parser_type_id
(cp_parser *);
*************** cp_parser_new_type_id (cp_parser* parser
*** 4954,4988 ****
static cp_declarator *
cp_parser_new_declarator_opt (cp_parser* parser)
{
enum tree_code code;
tree type;
! tree cv_qualifier_seq;
/* We don't know if there's a ptr-operator next, or not. */
cp_parser_parse_tentatively (parser);
/* Look for a ptr-operator. */
! code = cp_parser_ptr_operator (parser, &type, &cv_qualifier_seq);
/* If that worked, look for more new-declarators. */
if (cp_parser_parse_definitely (parser))
{
cp_declarator *declarator;
/* Parse another optional declarator. */
declarator = cp_parser_new_declarator_opt (parser);
/* Create the representation of the declarator. */
if (type)
! declarator = make_ptrmem_declarator (cv_qualifier_seq,
! type,
! declarator);
else if (code == INDIRECT_REF)
! declarator = make_pointer_declarator (cv_qualifier_seq,
! declarator);
else
! declarator = make_reference_declarator (cv_qualifier_seq,
! declarator);
return declarator;
}
/* If the next token is a `[', there is a direct-new-declarator. */
--- 4952,4982 ----
static cp_declarator *
cp_parser_new_declarator_opt (cp_parser* parser)
{
enum tree_code code;
tree type;
! cp_cv_quals cv_quals;
/* We don't know if there's a ptr-operator next, or not. */
cp_parser_parse_tentatively (parser);
/* Look for a ptr-operator. */
! code = cp_parser_ptr_operator (parser, &type, &cv_quals);
/* If that worked, look for more new-declarators. */
if (cp_parser_parse_definitely (parser))
{
cp_declarator *declarator;
/* Parse another optional declarator. */
declarator = cp_parser_new_declarator_opt (parser);
/* Create the representation of the declarator. */
if (type)
! declarator = make_ptrmem_declarator (cv_quals, type, declarator);
else if (code == INDIRECT_REF)
! declarator = make_pointer_declarator (cv_quals, declarator);
else
! declarator = make_reference_declarator (cv_quals, declarator);
return declarator;
}
/* If the next token is a `[', there is a direct-new-declarator. */
*************** cp_parser_conversion_type_id (cp_parser*
*** 7568,7603 ****
static cp_declarator *
cp_parser_conversion_declarator_opt (cp_parser* parser)
{
enum tree_code code;
tree class_type;
! tree cv_qualifier_seq;
/* We don't know if there's a ptr-operator next, or not. */
cp_parser_parse_tentatively (parser);
/* Try the ptr-operator. */
! code = cp_parser_ptr_operator (parser, &class_type,
! &cv_qualifier_seq);
/* If it worked, look for more conversion-declarators. */
if (cp_parser_parse_definitely (parser))
{
cp_declarator *declarator;
/* Parse another optional declarator. */
declarator = cp_parser_conversion_declarator_opt (parser);
/* Create the representation of the declarator. */
if (class_type)
! declarator = make_ptrmem_declarator (cv_qualifier_seq,
! class_type,
declarator);
else if (code == INDIRECT_REF)
! declarator = make_pointer_declarator (cv_qualifier_seq,
! declarator);
else
! declarator = make_reference_declarator (cv_qualifier_seq,
! declarator);
return declarator;
}
return NULL;
--- 7562,7593 ----
static cp_declarator *
cp_parser_conversion_declarator_opt (cp_parser* parser)
{
enum tree_code code;
tree class_type;
! cp_cv_quals cv_quals;
/* We don't know if there's a ptr-operator next, or not. */
cp_parser_parse_tentatively (parser);
/* Try the ptr-operator. */
! code = cp_parser_ptr_operator (parser, &class_type, &cv_quals);
/* If it worked, look for more conversion-declarators. */
if (cp_parser_parse_definitely (parser))
{
cp_declarator *declarator;
/* Parse another optional declarator. */
declarator = cp_parser_conversion_declarator_opt (parser);
/* Create the representation of the declarator. */
if (class_type)
! declarator = make_ptrmem_declarator (cv_quals, class_type,
declarator);
else if (code == INDIRECT_REF)
! declarator = make_pointer_declarator (cv_quals, declarator);
else
! declarator = make_reference_declarator (cv_quals, declarator);
return declarator;
}
return NULL;
*************** cp_parser_declarator (cp_parser* parser,
*** 10777,10787 ****
bool* parenthesized_p)
{
cp_token *token;
cp_declarator *declarator;
enum tree_code code;
! tree cv_qualifier_seq;
tree class_type;
tree attributes = NULL_TREE;
/* Assume this is not a constructor, destructor, or type-conversion
operator. */
--- 10767,10777 ----
bool* parenthesized_p)
{
cp_token *token;
cp_declarator *declarator;
enum tree_code code;
! cp_cv_quals cv_quals;
tree class_type;
tree attributes = NULL_TREE;
/* Assume this is not a constructor, destructor, or type-conversion
operator. */
*************** cp_parser_declarator (cp_parser* parser,
*** 10797,10807 ****
/* Check for the ptr-operator production. */
cp_parser_parse_tentatively (parser);
/* Parse the ptr-operator. */
code = cp_parser_ptr_operator (parser,
&class_type,
! &cv_qualifier_seq);
/* If that worked, then we have a ptr-operator. */
if (cp_parser_parse_definitely (parser))
{
/* If a ptr-operator was found, then this declarator was not
parenthesized. */
--- 10787,10797 ----
/* Check for the ptr-operator production. */
cp_parser_parse_tentatively (parser);
/* Parse the ptr-operator. */
code = cp_parser_ptr_operator (parser,
&class_type,
! &cv_quals);
/* If that worked, then we have a ptr-operator. */
if (cp_parser_parse_definitely (parser))
{
/* If a ptr-operator was found, then this declarator was not
parenthesized. */
*************** cp_parser_declarator (cp_parser* parser,
*** 10823,10841 ****
&& !cp_parser_parse_definitely (parser))
declarator = NULL;
/* Build the representation of the ptr-operator. */
if (class_type)
! declarator = make_ptrmem_declarator (cv_qualifier_seq,
class_type,
declarator);
else if (code == INDIRECT_REF)
! declarator = make_pointer_declarator (cv_qualifier_seq,
! declarator);
else
! declarator = make_reference_declarator (cv_qualifier_seq,
! declarator);
}
/* Everything else is a direct-declarator. */
else
{
if (parenthesized_p)
--- 10813,10829 ----
&& !cp_parser_parse_definitely (parser))
declarator = NULL;
/* Build the representation of the ptr-operator. */
if (class_type)
! declarator = make_ptrmem_declarator (cv_quals,
class_type,
declarator);
else if (code == INDIRECT_REF)
! declarator = make_pointer_declarator (cv_quals, declarator);
else
! declarator = make_reference_declarator (cv_quals, declarator);
}
/* Everything else is a direct-declarator. */
else
{
if (parenthesized_p)
*************** cp_parser_direct_declarator (cp_parser*
*** 10966,10994 ****
/* If all went well, parse the cv-qualifier-seq and the
exception-specification. */
if (cp_parser_parse_definitely (parser))
{
! tree cv_qualifiers;
tree exception_specification;
if (ctor_dtor_or_conv_p)
*ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
first = false;
/* Consume the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
/* Parse the cv-qualifier-seq. */
! cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser);
/* And the exception-specification. */
exception_specification
= cp_parser_exception_specification_opt (parser);
/* Create the function-declarator. */
declarator = make_call_declarator (declarator,
params,
! cv_qualifiers,
exception_specification);
/* Any subsequent parameter lists are to do with
return type, so are not those of the declared
function. */
parser->default_arg_ok_p = false;
--- 10954,10982 ----
/* If all went well, parse the cv-qualifier-seq and the
exception-specification. */
if (cp_parser_parse_definitely (parser))
{
! cp_cv_quals cv_quals;
tree exception_specification;
if (ctor_dtor_or_conv_p)
*ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
first = false;
/* Consume the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
/* Parse the cv-qualifier-seq. */
! cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
/* And the exception-specification. */
exception_specification
= cp_parser_exception_specification_opt (parser);
/* Create the function-declarator. */
declarator = make_call_declarator (declarator,
params,
! cv_quals,
exception_specification);
/* Any subsequent parameter lists are to do with
return type, so are not those of the declared
function. */
parser->default_arg_ok_p = false;
*************** cp_parser_direct_declarator (cp_parser*
*** 11224,11252 ****
GNU Extension:
ptr-operator:
& cv-qualifier-seq [opt]
! Returns INDIRECT_REF if a pointer, or pointer-to-member, was
! used. Returns ADDR_EXPR if a reference was used. In the
! case of a pointer-to-member, *TYPE is filled in with the
! TYPE containing the member. *CV_QUALIFIER_SEQ is filled in
! with the cv-qualifier-seq, or NULL_TREE, if there are no
! cv-qualifiers. Returns ERROR_MARK if an error occurred. */
static enum tree_code
cp_parser_ptr_operator (cp_parser* parser,
tree* type,
! tree* cv_qualifier_seq)
{
enum tree_code code = ERROR_MARK;
cp_token *token;
/* Assume that it's not a pointer-to-member. */
*type = NULL_TREE;
/* And that there are no cv-qualifiers. */
! *cv_qualifier_seq = NULL_TREE;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* If it's a `*' or `&' we have a pointer or reference. */
if (token->type == CPP_MULT || token->type == CPP_AND)
--- 11212,11240 ----
GNU Extension:
ptr-operator:
& cv-qualifier-seq [opt]
! Returns INDIRECT_REF if a pointer, or pointer-to-member, was used.
! Returns ADDR_EXPR if a reference was used. In the case of a
! pointer-to-member, *TYPE is filled in with the TYPE containing the
! member. *CV_QUALS is filled in with the cv-qualifier-seq, or
! TYPE_UNQUALIFIED, if there are no cv-qualifiers. Returns
! ERROR_MARK if an error occurred. */
static enum tree_code
cp_parser_ptr_operator (cp_parser* parser,
tree* type,
! cp_cv_quals *cv_quals)
{
enum tree_code code = ERROR_MARK;
cp_token *token;
/* Assume that it's not a pointer-to-member. */
*type = NULL_TREE;
/* And that there are no cv-qualifiers. */
! *cv_quals = TYPE_UNQUALIFIED;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* If it's a `*' or `&' we have a pointer or reference. */
if (token->type == CPP_MULT || token->type == CPP_AND)
*************** cp_parser_ptr_operator (cp_parser* parse
*** 11261,11271 ****
`&', if we are allowing GNU extensions. (The only qualifier
that can legally appear after `&' is `restrict', but that is
enforced during semantic analysis. */
if (code == INDIRECT_REF
|| cp_parser_allow_gnu_extensions_p (parser))
! *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser);
}
else
{
/* Try the pointer-to-member case. */
cp_parser_parse_tentatively (parser);
--- 11249,11259 ----
`&', if we are allowing GNU extensions. (The only qualifier
that can legally appear after `&' is `restrict', but that is
enforced during semantic analysis. */
if (code == INDIRECT_REF
|| cp_parser_allow_gnu_extensions_p (parser))
! *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
}
else
{
/* Try the pointer-to-member case. */
cp_parser_parse_tentatively (parser);
*************** cp_parser_ptr_operator (cp_parser* parse
*** 11291,11301 ****
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
/* Indicate that the `*' operator was used. */
code = INDIRECT_REF;
/* Look for the optional cv-qualifier-seq. */
! *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser);
}
/* If that didn't work we don't have a ptr-operator. */
if (!cp_parser_parse_definitely (parser))
cp_parser_error (parser, "expected ptr-operator");
}
--- 11279,11289 ----
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
/* Indicate that the `*' operator was used. */
code = INDIRECT_REF;
/* Look for the optional cv-qualifier-seq. */
! *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
}
/* If that didn't work we don't have a ptr-operator. */
if (!cp_parser_parse_definitely (parser))
cp_parser_error (parser, "expected ptr-operator");
}
*************** cp_parser_ptr_operator (cp_parser* parse
*** 11306,11378 ****
/* Parse an (optional) cv-qualifier-seq.
cv-qualifier-seq:
cv-qualifier cv-qualifier-seq [opt]
- Returns a TREE_LIST. The TREE_VALUE of each node is the
- representation of a cv-qualifier. */
-
- static tree
- cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
- {
- tree cv_qualifiers = NULL_TREE;
-
- while (true)
- {
- tree cv_qualifier;
-
- /* Look for the next cv-qualifier. */
- cv_qualifier = cp_parser_cv_qualifier_opt (parser);
- /* If we didn't find one, we're done. */
- if (!cv_qualifier)
- break;
-
- /* Add this cv-qualifier to the list. */
- cv_qualifiers
- = tree_cons (NULL_TREE, cv_qualifier, cv_qualifiers);
- }
-
- /* We built up the list in reverse order. */
- return nreverse (cv_qualifiers);
- }
-
- /* Parse an (optional) cv-qualifier.
-
cv-qualifier:
const
volatile
GNU Extension:
cv-qualifier:
! __restrict__ */
! static tree
! cp_parser_cv_qualifier_opt (cp_parser* parser)
{
! cp_token *token;
! tree cv_qualifier = NULL_TREE;
! /* Peek at the next token. */
! token = cp_lexer_peek_token (parser->lexer);
! /* See if it's a cv-qualifier. */
! switch (token->keyword)
{
! case RID_CONST:
! case RID_VOLATILE:
! case RID_RESTRICT:
! /* Save the value of the token. */
! cv_qualifier = token->value;
! /* Consume the token. */
! cp_lexer_consume_token (parser->lexer);
! break;
! default:
! break;
}
! return cv_qualifier;
}
/* Parse a declarator-id.
declarator-id:
--- 11294,11362 ----
/* Parse an (optional) cv-qualifier-seq.
cv-qualifier-seq:
cv-qualifier cv-qualifier-seq [opt]
cv-qualifier:
const
volatile
GNU Extension:
cv-qualifier:
! __restrict__
! Returns a bitmask representing the cv-qualifiers. */
!
! static cp_cv_quals
! cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
{
! cp_cv_quals cv_quals = TYPE_UNQUALIFIED;
! while (true)
{
! cp_token *token;
! cp_cv_quals cv_qualifier;
!
! /* Peek at the next token. */
! token = cp_lexer_peek_token (parser->lexer);
! /* See if it's a cv-qualifier. */
! switch (token->keyword)
! {
! case RID_CONST:
! cv_qualifier = TYPE_QUAL_CONST;
! break;
!
! case RID_VOLATILE:
! cv_qualifier = TYPE_QUAL_VOLATILE;
! break;
!
! case RID_RESTRICT:
! cv_qualifier = TYPE_QUAL_RESTRICT;
! break;
!
! default:
! cv_qualifier = TYPE_UNQUALIFIED;
! break;
! }
!
! if (!cv_qualifier)
! break;
! if (cv_quals & cv_qualifier)
! {
! error ("duplicate cv-qualifier");
! cp_lexer_purge_token (parser->lexer);
! }
! else
! {
! cp_lexer_consume_token (parser->lexer);
! cv_quals |= cv_qualifier;
! }
}
! return cv_quals;
}
/* Parse a declarator-id.
declarator-id: