1996-09-18 05:35:50 +00:00
|
|
|
|
/* YACC parser for C++ syntax.
|
1999-10-16 06:09:09 +00:00
|
|
|
|
Copyright (C) 1988, 89, 93-98, 1999 Free Software Foundation, Inc.
|
1996-09-18 05:35:50 +00:00
|
|
|
|
Hacked by Michael Tiemann (tiemann@cygnus.com)
|
|
|
|
|
|
|
|
|
|
This file is part of GNU CC.
|
|
|
|
|
|
|
|
|
|
GNU CC 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.
|
|
|
|
|
|
|
|
|
|
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
|
|
|
|
the Free Software Foundation, 59 Temple Place - Suite 330,
|
|
|
|
|
Boston, MA 02111-1307, USA. */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This grammar is based on the GNU CC grammar. */
|
|
|
|
|
|
|
|
|
|
/* Note: Bison automatically applies a default action of "$$ = $1" for
|
|
|
|
|
all derivations; this is applied before the explicit action, if one
|
|
|
|
|
is given. Keep this in mind when reading the actions. */
|
|
|
|
|
|
|
|
|
|
%{
|
|
|
|
|
/* Cause the `yydebug' variable to be defined. */
|
|
|
|
|
#define YYDEBUG 1
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
#include "system.h"
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
#include "tree.h"
|
|
|
|
|
#include "input.h"
|
|
|
|
|
#include "flags.h"
|
|
|
|
|
#include "lex.h"
|
|
|
|
|
#include "cp-tree.h"
|
|
|
|
|
#include "output.h"
|
1999-08-26 09:30:50 +00:00
|
|
|
|
#include "except.h"
|
|
|
|
|
#include "toplev.h"
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
/* Since parsers are distinct for each language, put the language string
|
|
|
|
|
definition here. (fnf) */
|
|
|
|
|
char *language_string = "GNU C++";
|
|
|
|
|
|
|
|
|
|
extern tree void_list_node;
|
|
|
|
|
extern struct obstack permanent_obstack;
|
|
|
|
|
|
|
|
|
|
extern int end_of_file;
|
|
|
|
|
|
|
|
|
|
/* Like YYERROR but do call yyerror. */
|
|
|
|
|
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
|
|
|
|
|
|
|
|
|
|
#define OP0(NODE) (TREE_OPERAND (NODE, 0))
|
|
|
|
|
#define OP1(NODE) (TREE_OPERAND (NODE, 1))
|
|
|
|
|
|
|
|
|
|
/* Contains the statement keyword (if/while/do) to include in an
|
|
|
|
|
error message if the user supplies an empty conditional expression. */
|
1999-10-16 06:09:09 +00:00
|
|
|
|
static const char *cond_stmt_keyword;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
static tree empty_parms PROTO((void));
|
1999-10-16 06:09:09 +00:00
|
|
|
|
static int parse_decl PROTO((tree, tree, tree, int, tree *));
|
1999-08-26 09:30:50 +00:00
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
|
|
|
|
|
int have_extern_spec;
|
|
|
|
|
int used_extern_spec;
|
|
|
|
|
|
|
|
|
|
/* Cons up an empty parameter list. */
|
|
|
|
|
#ifdef __GNUC__
|
|
|
|
|
__inline
|
|
|
|
|
#endif
|
|
|
|
|
static tree
|
|
|
|
|
empty_parms ()
|
|
|
|
|
{
|
|
|
|
|
tree parms;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (strict_prototype
|
|
|
|
|
|| current_class_type != NULL)
|
1996-09-18 05:35:50 +00:00
|
|
|
|
parms = void_list_node;
|
|
|
|
|
else
|
|
|
|
|
parms = NULL_TREE;
|
|
|
|
|
return parms;
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
%start program
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%union {long itype; tree ttype; char *strtype; enum tree_code code; flagged_type_tree ftype; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
/* All identifiers that are not reserved words
|
|
|
|
|
and are not declared typedefs in the current block */
|
|
|
|
|
%token IDENTIFIER
|
|
|
|
|
|
|
|
|
|
/* All identifiers that are declared typedefs in the current block.
|
|
|
|
|
In some contexts, they are treated just like IDENTIFIER,
|
|
|
|
|
but they can also serve as typespecs in declarations. */
|
|
|
|
|
%token TYPENAME
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%token SELFNAME
|
|
|
|
|
|
|
|
|
|
/* A template function. */
|
|
|
|
|
%token PFUNCNAME
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
/* Reserved words that specify storage class.
|
|
|
|
|
yylval contains an IDENTIFIER_NODE which indicates which one. */
|
|
|
|
|
%token SCSPEC
|
|
|
|
|
|
|
|
|
|
/* Reserved words that specify type.
|
|
|
|
|
yylval contains an IDENTIFIER_NODE which indicates which one. */
|
|
|
|
|
%token TYPESPEC
|
|
|
|
|
|
|
|
|
|
/* Reserved words that qualify type: "const" or "volatile".
|
|
|
|
|
yylval contains an IDENTIFIER_NODE which indicates which one. */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%token CV_QUALIFIER
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
/* Character or numeric constants.
|
|
|
|
|
yylval is the node for the constant. */
|
|
|
|
|
%token CONSTANT
|
|
|
|
|
|
|
|
|
|
/* String constants in raw form.
|
|
|
|
|
yylval is a STRING_CST node. */
|
|
|
|
|
%token STRING
|
|
|
|
|
|
|
|
|
|
/* "...", used for functions with variable arglists. */
|
|
|
|
|
%token ELLIPSIS
|
|
|
|
|
|
|
|
|
|
/* the reserved words */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* SCO include files test "ASM", so use something else. */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%token SIZEOF ENUM /* STRUCT UNION */ IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
|
1999-10-16 06:09:09 +00:00
|
|
|
|
%token BREAK CONTINUE RETURN_KEYWORD GOTO ASM_KEYWORD TYPEOF ALIGNOF
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%token SIGOF
|
|
|
|
|
%token ATTRIBUTE EXTENSION LABEL
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%token REALPART IMAGPART
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
/* the reserved words... C++ extensions */
|
|
|
|
|
%token <ttype> AGGR
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%token <ttype> VISSPEC
|
|
|
|
|
%token DELETE NEW THIS OPERATOR CXX_TRUE CXX_FALSE
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%token NAMESPACE TYPENAME_KEYWORD USING
|
|
|
|
|
%token LEFT_RIGHT TEMPLATE
|
|
|
|
|
%token TYPEID DYNAMIC_CAST STATIC_CAST REINTERPRET_CAST CONST_CAST
|
|
|
|
|
%token <itype> SCOPE
|
|
|
|
|
|
|
|
|
|
/* Define the operator tokens and their precedences.
|
|
|
|
|
The value is an integer because, if used, it is the tree code
|
|
|
|
|
to use in the expression made from the operator. */
|
|
|
|
|
|
|
|
|
|
%left EMPTY /* used to resolve s/r with epsilon */
|
|
|
|
|
|
|
|
|
|
%left error
|
|
|
|
|
|
|
|
|
|
/* Add precedence rules to solve dangling else s/r conflict */
|
|
|
|
|
%nonassoc IF
|
|
|
|
|
%nonassoc ELSE
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%left IDENTIFIER PFUNCNAME TYPENAME SELFNAME PTYPENAME SCSPEC TYPESPEC CV_QUALIFIER ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR NSNAME TYPENAME_KEYWORD
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
%left '{' ',' ';'
|
|
|
|
|
|
|
|
|
|
%nonassoc THROW
|
|
|
|
|
%right <code> ':'
|
|
|
|
|
%right <code> ASSIGN '='
|
|
|
|
|
%right <code> '?'
|
|
|
|
|
%left <code> OROR
|
|
|
|
|
%left <code> ANDAND
|
|
|
|
|
%left <code> '|'
|
|
|
|
|
%left <code> '^'
|
|
|
|
|
%left <code> '&'
|
|
|
|
|
%left <code> MIN_MAX
|
|
|
|
|
%left <code> EQCOMPARE
|
|
|
|
|
%left <code> ARITHCOMPARE '<' '>'
|
|
|
|
|
%left <code> LSHIFT RSHIFT
|
|
|
|
|
%left <code> '+' '-'
|
|
|
|
|
%left <code> '*' '/' '%'
|
|
|
|
|
%left <code> POINTSAT_STAR DOT_STAR
|
|
|
|
|
%right <code> UNARY PLUSPLUS MINUSMINUS '~'
|
|
|
|
|
%left HYPERUNARY
|
|
|
|
|
%left <ttype> PAREN_STAR_PAREN LEFT_RIGHT
|
|
|
|
|
%left <code> POINTSAT '.' '(' '['
|
|
|
|
|
|
|
|
|
|
%right SCOPE /* C++ extension */
|
|
|
|
|
%nonassoc NEW DELETE TRY CATCH
|
|
|
|
|
|
|
|
|
|
%type <code> unop
|
|
|
|
|
|
|
|
|
|
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> PFUNCNAME maybe_identifier
|
|
|
|
|
%type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> reserved_declspecs boolean.literal
|
|
|
|
|
%type <ttype> reserved_typespecquals
|
|
|
|
|
%type <ttype> declmods
|
|
|
|
|
%type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <itype> initdecls notype_initdecls initdcl /* C++ modification */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> init initlist maybeasm maybe_init defarg defarg1
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
|
|
|
|
|
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
|
|
|
|
|
%type <ttype> any_word
|
|
|
|
|
|
|
|
|
|
%type <ttype> compstmt implicitly_scoped_stmt
|
|
|
|
|
|
|
|
|
|
%type <ttype> declarator notype_declarator after_type_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
%type <ttype> notype_declarator_intern absdcl_intern
|
|
|
|
|
%type <ttype> after_type_declarator_intern
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> direct_notype_declarator direct_after_type_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
%type <itype> components notype_components
|
|
|
|
|
%type <ttype> component_decl component_decl_1
|
|
|
|
|
%type <ttype> component_declarator component_declarator0
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> notype_component_declarator notype_component_declarator0
|
|
|
|
|
%type <ttype> after_type_component_declarator after_type_component_declarator0
|
|
|
|
|
%type <ttype> enumlist enumerator
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> absdcl cv_qualifiers
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> direct_abstract_declarator conversion_declarator
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> new_declarator direct_new_declarator
|
|
|
|
|
%type <ttype> xexpr parmlist parms bad_parm
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> identifiers_or_typenames
|
|
|
|
|
%type <ttype> fcast_or_absdcl regcast_or_absdcl
|
1999-10-16 06:09:09 +00:00
|
|
|
|
%type <ttype> expr_or_declarator expr_or_declarator_intern
|
|
|
|
|
%type <ttype> complex_notype_declarator
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> notype_unqualified_id unqualified_id qualified_id
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> template_id do_id object_template_id notype_template_declarator
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> overqualified_id notype_qualified_id any_id
|
|
|
|
|
%type <ttype> complex_direct_notype_declarator functional_cast
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> complex_parmlist parms_comma
|
|
|
|
|
%type <ttype> namespace_qualifier namespace_using_decl
|
|
|
|
|
|
|
|
|
|
%type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs
|
|
|
|
|
%type <ftype> typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers
|
|
|
|
|
%type <ftype> structsp typespecqual_reserved parm named_parm full_parm
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
/* C++ extensions */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%token <ttype> PTYPENAME
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
|
|
|
|
|
%type <ttype> component_constructor_declarator
|
|
|
|
|
%type <ttype> fn.def2 return_id fn.defpen constructor_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
%type <itype> ctor_initializer_opt function_try_block
|
|
|
|
|
%type <ttype> named_class_head_sans_basetype
|
|
|
|
|
%type <ftype> class_head named_class_head
|
|
|
|
|
%type <ftype> named_complex_class_head_sans_basetype
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> unnamed_class_head
|
1999-10-16 06:09:09 +00:00
|
|
|
|
%type <ttype> base_class_list
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> base_class_access_list
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> base_class maybe_base_class_list base_class.1
|
|
|
|
|
%type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
|
|
|
|
|
%type <ttype> operator_name
|
|
|
|
|
%type <ttype> object aggr
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <itype> new delete .begin_new_placement
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* %type <ttype> primary_no_id */
|
|
|
|
|
%type <ttype> nonmomentary_expr maybe_parmlist
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <itype> initdcl0 notype_initdcl0 member_init_list initdcl0_innards
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> template_header template_parm_list template_parm
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> template_type_parm template_template_parm
|
|
|
|
|
%type <code> template_close_bracket
|
1999-10-16 06:09:09 +00:00
|
|
|
|
%type <ttype> apparent_template_type
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> template_type template_arg_list template_arg_list_opt
|
|
|
|
|
%type <ttype> template_arg
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> condition xcond paren_cond_or_null
|
|
|
|
|
%type <ttype> type_name nested_name_specifier nested_type ptr_to_mem
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> complete_type_name notype_identifier nonnested_type
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> complex_type_name nested_name_specifier_1
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> new_initializer new_placement
|
|
|
|
|
%type <ttype> using_decl
|
|
|
|
|
%type <ttype> typename_sub typename_sub0 typename_sub1 typename_sub2
|
|
|
|
|
%type <ttype> explicit_template_type
|
|
|
|
|
/* in order to recognize aggr tags as defining and thus shadowing. */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
|
1999-08-26 09:30:50 +00:00
|
|
|
|
%type <ttype> named_class_head_sans_basetype_defn
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
%type <ttype> self_template_type .finish_template_type
|
1999-08-26 09:30:50 +00:00
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%token NSNAME
|
|
|
|
|
%type <ttype> NSNAME
|
|
|
|
|
|
|
|
|
|
/* Used in lex.c for parsing pragmas. */
|
|
|
|
|
%token END_OF_LINE
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* lex.c and pt.c depend on this being the last token. Define
|
1996-09-18 05:35:50 +00:00
|
|
|
|
any new tokens before this one! */
|
|
|
|
|
%token END_OF_SAVED_INPUT
|
|
|
|
|
|
|
|
|
|
%{
|
|
|
|
|
/* List of types and structure classes of the current declaration. */
|
|
|
|
|
static tree current_declspecs;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* List of prefix attributes in effect.
|
|
|
|
|
Prefix attributes are parsed by the reserved_declspecs and declmods
|
|
|
|
|
rules. They create a list that contains *both* declspecs and attrs. */
|
|
|
|
|
/* ??? It is not clear yet that all cases where an attribute can now appear in
|
|
|
|
|
a declspec list have been updated. */
|
|
|
|
|
static tree prefix_attributes;
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
/* When defining an aggregate, this is the kind of the most recent one
|
|
|
|
|
being defined. (For example, this might be class_type_node.) */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
static tree current_aggr;
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
/* When defining an enumeration, this is the type of the enumeration. */
|
|
|
|
|
static tree current_enum_type;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* Tell yyparse how to print a token's value, if yydebug is set. */
|
|
|
|
|
|
|
|
|
|
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
|
1999-08-26 09:30:50 +00:00
|
|
|
|
extern void yyprint PROTO((FILE *, int, YYSTYPE));
|
1996-09-18 05:35:50 +00:00
|
|
|
|
extern tree combine_strings PROTO((tree));
|
1999-08-26 09:30:50 +00:00
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
parse_decl(declarator, specs_attrs, attributes, initialized, decl)
|
|
|
|
|
tree declarator;
|
|
|
|
|
tree specs_attrs;
|
|
|
|
|
tree attributes;
|
|
|
|
|
int initialized;
|
|
|
|
|
tree* decl;
|
|
|
|
|
{
|
|
|
|
|
int sm;
|
|
|
|
|
|
|
|
|
|
split_specs_attrs (specs_attrs, ¤t_declspecs, &prefix_attributes);
|
|
|
|
|
if (current_declspecs
|
|
|
|
|
&& TREE_CODE (current_declspecs) != TREE_LIST)
|
1999-10-16 06:09:09 +00:00
|
|
|
|
current_declspecs = build_decl_list (NULL_TREE, current_declspecs);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (have_extern_spec && !used_extern_spec)
|
|
|
|
|
{
|
|
|
|
|
current_declspecs = decl_tree_cons (NULL_TREE,
|
|
|
|
|
get_identifier ("extern"),
|
|
|
|
|
current_declspecs);
|
|
|
|
|
used_extern_spec = 1;
|
|
|
|
|
}
|
|
|
|
|
sm = suspend_momentary ();
|
|
|
|
|
*decl = start_decl (declarator, current_declspecs, initialized,
|
|
|
|
|
attributes, prefix_attributes);
|
|
|
|
|
return sm;
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
%%
|
1999-08-26 09:30:50 +00:00
|
|
|
|
program:
|
|
|
|
|
/* empty */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| extdefs
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_translation_unit (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* the reason for the strange actions in this rule
|
|
|
|
|
is so that notype_initdecls when reached via datadef
|
1999-08-26 09:30:50 +00:00
|
|
|
|
can find a valid list of type and sc specs in $0. */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
extdefs:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $<ttype>$ = NULL_TREE; }
|
|
|
|
|
lang_extdef
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $<ttype>$ = NULL_TREE; }
|
|
|
|
|
| extdefs lang_extdef
|
|
|
|
|
{ $<ttype>$ = NULL_TREE; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
extdefs_opt:
|
|
|
|
|
extdefs
|
|
|
|
|
| /* empty */
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
.hush_warning:
|
|
|
|
|
{ have_extern_spec = 1;
|
|
|
|
|
used_extern_spec = 0;
|
|
|
|
|
$<ttype>$ = NULL_TREE; }
|
|
|
|
|
;
|
|
|
|
|
.warning_ok:
|
|
|
|
|
{ have_extern_spec = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
extension:
|
|
|
|
|
EXTENSION
|
|
|
|
|
{ $<itype>$ = pedantic;
|
|
|
|
|
pedantic = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
asm_keyword:
|
|
|
|
|
ASM_KEYWORD
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
lang_extdef:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ if (pending_lang_change) do_pending_lang_change(); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
extdef
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ if (! toplevel_bindings_p () && ! pseudo_global_level_p())
|
|
|
|
|
pop_everything (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
extdef:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
fndef eat_saved_input
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ if (pending_inlines) do_pending_inlines (); }
|
|
|
|
|
| datadef
|
|
|
|
|
{ if (pending_inlines) do_pending_inlines (); }
|
|
|
|
|
| template_def
|
|
|
|
|
{ if (pending_inlines) do_pending_inlines (); }
|
|
|
|
|
| asm_keyword '(' string ')' ';'
|
|
|
|
|
{ if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
|
|
|
|
|
assemble_asm ($3); }
|
|
|
|
|
| extern_lang_string '{' extdefs_opt '}'
|
|
|
|
|
{ pop_lang_context (); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| extern_lang_string .hush_warning fndef .warning_ok eat_saved_input
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ if (pending_inlines) do_pending_inlines ();
|
|
|
|
|
pop_lang_context (); }
|
|
|
|
|
| extern_lang_string .hush_warning datadef .warning_ok
|
|
|
|
|
{ if (pending_inlines) do_pending_inlines ();
|
|
|
|
|
pop_lang_context (); }
|
|
|
|
|
| NAMESPACE identifier '{'
|
|
|
|
|
{ push_namespace ($2); }
|
|
|
|
|
extdefs_opt '}'
|
|
|
|
|
{ pop_namespace (); }
|
|
|
|
|
| NAMESPACE '{'
|
|
|
|
|
{ push_namespace (NULL_TREE); }
|
|
|
|
|
extdefs_opt '}'
|
|
|
|
|
{ pop_namespace (); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| namespace_alias
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| using_decl ';'
|
|
|
|
|
{ do_toplevel_using_decl ($1); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| using_directive
|
|
|
|
|
| extension extdef
|
|
|
|
|
{ pedantic = $<itype>1; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
namespace_alias:
|
|
|
|
|
NAMESPACE identifier '='
|
|
|
|
|
{ begin_only_namespace_names (); }
|
|
|
|
|
any_id ';'
|
|
|
|
|
{
|
|
|
|
|
end_only_namespace_names ();
|
|
|
|
|
if (lastiddecl)
|
|
|
|
|
$5 = lastiddecl;
|
|
|
|
|
do_namespace_alias ($2, $5);
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
using_decl:
|
|
|
|
|
USING qualified_id
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
| USING global_scope qualified_id
|
|
|
|
|
{ $$ = $3; }
|
|
|
|
|
| USING global_scope unqualified_id
|
|
|
|
|
{ $$ = $3; }
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
namespace_using_decl:
|
|
|
|
|
USING namespace_qualifier identifier
|
|
|
|
|
{ $$ = build_parse_node (SCOPE_REF, $2, $3); }
|
|
|
|
|
| USING global_scope identifier
|
|
|
|
|
{ $$ = build_parse_node (SCOPE_REF, global_namespace, $3); }
|
|
|
|
|
| USING global_scope namespace_qualifier identifier
|
|
|
|
|
{ $$ = build_parse_node (SCOPE_REF, $3, $4); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
using_directive:
|
|
|
|
|
USING NAMESPACE
|
|
|
|
|
{ begin_only_namespace_names (); }
|
|
|
|
|
any_id ';'
|
|
|
|
|
{
|
|
|
|
|
end_only_namespace_names ();
|
|
|
|
|
/* If no declaration was found, the using-directive is
|
|
|
|
|
invalid. Since that was not reported, we need the
|
|
|
|
|
identifier for the error message. */
|
|
|
|
|
if (TREE_CODE ($4) == IDENTIFIER_NODE && lastiddecl)
|
|
|
|
|
$4 = lastiddecl;
|
|
|
|
|
do_using_directive ($4);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
namespace_qualifier:
|
|
|
|
|
NSNAME SCOPE
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($$) == IDENTIFIER_NODE)
|
|
|
|
|
$$ = lastiddecl;
|
|
|
|
|
got_scope = $$;
|
|
|
|
|
}
|
|
|
|
|
| namespace_qualifier NSNAME SCOPE
|
|
|
|
|
{
|
|
|
|
|
$$ = $2;
|
|
|
|
|
if (TREE_CODE ($$) == IDENTIFIER_NODE)
|
|
|
|
|
$$ = lastiddecl;
|
|
|
|
|
got_scope = $$;
|
|
|
|
|
}
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
any_id:
|
|
|
|
|
unqualified_id
|
|
|
|
|
| qualified_id
|
|
|
|
|
| global_scope qualified_id
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
| global_scope unqualified_id
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
extern_lang_string:
|
|
|
|
|
EXTERN_LANG_STRING
|
|
|
|
|
{ push_lang_context ($1); }
|
|
|
|
|
| extern_lang_string EXTERN_LANG_STRING
|
|
|
|
|
{ if (current_lang_name != $2)
|
|
|
|
|
cp_error ("use of linkage spec `%D' is different from previous spec `%D'", $2, current_lang_name);
|
|
|
|
|
pop_lang_context (); push_lang_context ($2); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
template_header:
|
|
|
|
|
TEMPLATE '<'
|
|
|
|
|
{ begin_template_parm_list (); }
|
|
|
|
|
template_parm_list '>'
|
|
|
|
|
{ $$ = end_template_parm_list ($4); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| TEMPLATE '<' '>'
|
|
|
|
|
{ begin_specialization();
|
|
|
|
|
$$ = NULL_TREE; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
template_parm_list:
|
|
|
|
|
template_parm
|
|
|
|
|
{ $$ = process_template_parm (NULL_TREE, $1); }
|
|
|
|
|
| template_parm_list ',' template_parm
|
|
|
|
|
{ $$ = process_template_parm ($1, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
maybe_identifier:
|
|
|
|
|
identifier
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| /* empty */
|
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
template_type_parm:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
aggr maybe_identifier
|
|
|
|
|
{ $$ = finish_template_type_parm ($1, $2); }
|
|
|
|
|
| TYPENAME_KEYWORD maybe_identifier
|
|
|
|
|
{ $$ = finish_template_type_parm (class_type_node, $2); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
template_template_parm:
|
|
|
|
|
template_header aggr maybe_identifier
|
|
|
|
|
{ $$ = finish_template_template_parm ($2, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
template_parm:
|
|
|
|
|
/* The following rules introduce a new reduce/reduce
|
|
|
|
|
conflict on the ',' and '>' input tokens: they are valid
|
|
|
|
|
prefixes for a `structsp', which means they could match a
|
|
|
|
|
nameless parameter. See 14.6, paragraph 3.
|
|
|
|
|
By putting them before the `parm' rule, we get
|
|
|
|
|
their match before considering them nameless parameter
|
|
|
|
|
declarations. */
|
|
|
|
|
template_type_parm
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_tree_list (NULL_TREE, $1); }
|
|
|
|
|
| template_type_parm '=' type_id
|
|
|
|
|
{ $$ = build_tree_list (groktypename ($3.t), $1); }
|
|
|
|
|
| parm
|
|
|
|
|
{ $$ = build_tree_list (NULL_TREE, $1.t); }
|
|
|
|
|
| parm '=' expr_no_commas %prec ARITHCOMPARE
|
|
|
|
|
{ $$ = build_tree_list ($3, $1.t); }
|
|
|
|
|
| template_template_parm
|
|
|
|
|
{ $$ = build_tree_list (NULL_TREE, $1); }
|
|
|
|
|
| template_template_parm '=' template_arg
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (TREE_CODE ($3) != TEMPLATE_DECL
|
|
|
|
|
&& TREE_CODE ($3) != TEMPLATE_TEMPLATE_PARM
|
|
|
|
|
&& TREE_CODE ($3) != TYPE_DECL)
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
error ("invalid default template argument");
|
|
|
|
|
$3 = error_mark_node;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = build_tree_list ($3, $1);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
template_def:
|
1999-10-16 06:09:09 +00:00
|
|
|
|
template_header template_extdef
|
|
|
|
|
{ finish_template_decl ($1); }
|
|
|
|
|
| template_header error %prec EMPTY
|
|
|
|
|
{ finish_template_decl ($1); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
template_extdef:
|
|
|
|
|
fndef eat_saved_input
|
|
|
|
|
{ if (pending_inlines) do_pending_inlines (); }
|
|
|
|
|
| template_datadef
|
|
|
|
|
{ if (pending_inlines) do_pending_inlines (); }
|
|
|
|
|
| template_def
|
|
|
|
|
{ if (pending_inlines) do_pending_inlines (); }
|
|
|
|
|
| extern_lang_string .hush_warning fndef .warning_ok eat_saved_input
|
|
|
|
|
{ if (pending_inlines) do_pending_inlines ();
|
|
|
|
|
pop_lang_context (); }
|
|
|
|
|
| extern_lang_string .hush_warning template_datadef .warning_ok
|
|
|
|
|
{ if (pending_inlines) do_pending_inlines ();
|
|
|
|
|
pop_lang_context (); }
|
|
|
|
|
| extension template_extdef
|
|
|
|
|
{ pedantic = $<itype>1; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
template_datadef:
|
|
|
|
|
nomods_initdecls ';'
|
|
|
|
|
| declmods notype_initdecls ';'
|
|
|
|
|
{}
|
|
|
|
|
| typed_declspecs initdecls ';'
|
|
|
|
|
{ note_list_got_semicolon ($1.t); }
|
|
|
|
|
| structsp ';'
|
|
|
|
|
{ maybe_process_partial_specialization ($1.t);
|
|
|
|
|
note_got_semicolon ($1.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
datadef:
|
|
|
|
|
nomods_initdecls ';'
|
|
|
|
|
| declmods notype_initdecls ';'
|
|
|
|
|
{}
|
|
|
|
|
| typed_declspecs initdecls ';'
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ note_list_got_semicolon ($1.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| declmods ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ pedwarn ("empty declaration"); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| explicit_instantiation ';'
|
|
|
|
|
| typed_declspecs ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
tree t, attrs;
|
|
|
|
|
split_specs_attrs ($1.t, &t, &attrs);
|
|
|
|
|
shadow_tag (t);
|
|
|
|
|
note_list_got_semicolon ($1.t);
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| error ';'
|
|
|
|
|
| error '}'
|
|
|
|
|
| ';'
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
ctor_initializer_opt:
|
|
|
|
|
nodecls
|
|
|
|
|
{ $$ = 0; }
|
|
|
|
|
| base_init
|
|
|
|
|
{ $$ = 1; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
maybe_return_init:
|
|
|
|
|
/* empty */
|
|
|
|
|
| return_init
|
|
|
|
|
| return_init ';'
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
eat_saved_input:
|
|
|
|
|
/* empty */
|
|
|
|
|
| END_OF_SAVED_INPUT
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
fndef:
|
|
|
|
|
fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_function (lineno, (int)$3, 0); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| fn.def1 maybe_return_init function_try_block
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
int nested = (hack_decl_function_context
|
|
|
|
|
(current_function_decl) != NULL_TREE);
|
|
|
|
|
finish_function (lineno, (int)$3, nested);
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| fn.def1 maybe_return_init error
|
|
|
|
|
{ }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
constructor_declarator:
|
|
|
|
|
nested_name_specifier SELFNAME '('
|
|
|
|
|
{ $$ = begin_constructor_declarator ($1, $2); }
|
|
|
|
|
parmlist ')' cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = make_call_declarator ($<ttype>4, $5, $7, $8); }
|
|
|
|
|
| nested_name_specifier SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = begin_constructor_declarator ($1, $2);
|
|
|
|
|
$$ = make_call_declarator ($$, empty_parms (), $4, $5);
|
|
|
|
|
}
|
|
|
|
|
| global_scope nested_name_specifier SELFNAME '('
|
|
|
|
|
{ $$ = begin_constructor_declarator ($2, $3); }
|
|
|
|
|
parmlist ')' cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = make_call_declarator ($<ttype>5, $6, $8, $9); }
|
|
|
|
|
| global_scope nested_name_specifier SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = begin_constructor_declarator ($2, $3);
|
|
|
|
|
$$ = make_call_declarator ($$, empty_parms (), $5, $6);
|
|
|
|
|
}
|
|
|
|
|
| nested_name_specifier self_template_type '('
|
|
|
|
|
{ $$ = begin_constructor_declarator ($1, $2); }
|
|
|
|
|
parmlist ')' cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = make_call_declarator ($<ttype>4, $5, $7, $8); }
|
|
|
|
|
| nested_name_specifier self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = begin_constructor_declarator ($1, $2);
|
|
|
|
|
$$ = make_call_declarator ($$, empty_parms (), $4, $5);
|
|
|
|
|
}
|
|
|
|
|
| global_scope nested_name_specifier self_template_type '('
|
|
|
|
|
{ $$ = begin_constructor_declarator ($2, $3); }
|
|
|
|
|
parmlist ')' cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = make_call_declarator ($<ttype>5, $6, $8, $9); }
|
|
|
|
|
| global_scope nested_name_specifier self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = begin_constructor_declarator ($2, $3);
|
|
|
|
|
$$ = make_call_declarator ($$, empty_parms (), $5, $6);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
fn.def1:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
typed_declspecs declarator
|
|
|
|
|
{ if (!begin_function_definition ($1.t, $2))
|
|
|
|
|
YYERROR1; }
|
|
|
|
|
| declmods notype_declarator
|
|
|
|
|
{ if (!begin_function_definition ($1, $2))
|
|
|
|
|
YYERROR1; }
|
|
|
|
|
| notype_declarator
|
|
|
|
|
{ if (!begin_function_definition (NULL_TREE, $1))
|
|
|
|
|
YYERROR1; }
|
|
|
|
|
| declmods constructor_declarator
|
|
|
|
|
{ if (!begin_function_definition ($1, $2))
|
|
|
|
|
YYERROR1; }
|
|
|
|
|
| constructor_declarator
|
|
|
|
|
{ if (!begin_function_definition (NULL_TREE, $1))
|
|
|
|
|
YYERROR1; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
component_constructor_declarator:
|
|
|
|
|
SELFNAME '(' parmlist ')' cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = make_call_declarator ($1, $3, $5, $6); }
|
|
|
|
|
| SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = make_call_declarator ($1, empty_parms (), $3, $4); }
|
|
|
|
|
| self_template_type '(' parmlist ')' cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = make_call_declarator ($1, $3, $5, $6); }
|
|
|
|
|
| self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt
|
|
|
|
|
{ $$ = make_call_declarator ($1, empty_parms (), $3, $4); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* more C++ complexity. See component_decl for a comment on the
|
|
|
|
|
reduce/reduce conflict introduced by these rules. */
|
|
|
|
|
fn.def2:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
declmods component_constructor_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ tree specs, attrs;
|
|
|
|
|
split_specs_attrs ($1, &specs, &attrs);
|
|
|
|
|
attrs = build_tree_list (attrs, NULL_TREE);
|
|
|
|
|
$$ = start_method (specs, $2, attrs);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
rest_of_mdef:
|
|
|
|
|
if (! $$)
|
|
|
|
|
YYERROR1;
|
|
|
|
|
if (yychar == YYEMPTY)
|
|
|
|
|
yychar = YYLEX;
|
|
|
|
|
reinit_parse_for_method (yychar, $$); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| component_constructor_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = start_method (NULL_TREE, $1, NULL_TREE);
|
|
|
|
|
goto rest_of_mdef; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| typed_declspecs declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ tree specs, attrs;
|
|
|
|
|
split_specs_attrs ($1.t, &specs, &attrs);
|
|
|
|
|
attrs = build_tree_list (attrs, NULL_TREE);
|
|
|
|
|
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| declmods notype_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ tree specs, attrs;
|
|
|
|
|
split_specs_attrs ($1, &specs, &attrs);
|
|
|
|
|
attrs = build_tree_list (attrs, NULL_TREE);
|
|
|
|
|
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| notype_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = start_method (NULL_TREE, $$, NULL_TREE);
|
|
|
|
|
goto rest_of_mdef; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| declmods constructor_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ tree specs, attrs;
|
|
|
|
|
split_specs_attrs ($1, &specs, &attrs);
|
|
|
|
|
attrs = build_tree_list (attrs, NULL_TREE);
|
|
|
|
|
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| constructor_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = start_method (NULL_TREE, $$, NULL_TREE);
|
|
|
|
|
goto rest_of_mdef; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
return_id:
|
1999-10-16 06:09:09 +00:00
|
|
|
|
RETURN_KEYWORD IDENTIFIER
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
|
|
|
|
if (! current_function_parms_stored)
|
|
|
|
|
store_parm_decls ();
|
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
return_init:
|
|
|
|
|
return_id maybe_init
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ store_return_init ($<ttype>$, $2); }
|
|
|
|
|
| return_id '(' nonnull_exprlist ')'
|
|
|
|
|
{ store_return_init ($<ttype>$, $3); }
|
|
|
|
|
| return_id LEFT_RIGHT
|
|
|
|
|
{ store_return_init ($<ttype>$, NULL_TREE); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
base_init:
|
|
|
|
|
':' .set_base_init member_init_list
|
|
|
|
|
{
|
|
|
|
|
if ($3 == 0)
|
|
|
|
|
error ("no base initializers given following ':'");
|
|
|
|
|
setup_vtbl_ptr ();
|
|
|
|
|
/* Always keep the BLOCK node associated with the outermost
|
|
|
|
|
pair of curley braces of a function. These are needed
|
|
|
|
|
for correct operation of dwarfout.c. */
|
|
|
|
|
keep_next_level ();
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
.set_base_init:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
|
|
|
|
if (! current_function_parms_stored)
|
|
|
|
|
store_parm_decls ();
|
|
|
|
|
|
|
|
|
|
if (DECL_CONSTRUCTOR_P (current_function_decl))
|
|
|
|
|
{
|
|
|
|
|
/* Make a contour for the initializer list. */
|
|
|
|
|
pushlevel (0);
|
|
|
|
|
clear_last_expr ();
|
|
|
|
|
expand_start_bindings (0);
|
|
|
|
|
}
|
|
|
|
|
else if (current_class_type == NULL_TREE)
|
|
|
|
|
error ("base initializers not allowed for non-member functions");
|
|
|
|
|
else if (! DECL_CONSTRUCTOR_P (current_function_decl))
|
|
|
|
|
error ("only constructors take base initializers");
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
member_init_list:
|
|
|
|
|
/* empty */
|
|
|
|
|
{ $$ = 0; }
|
|
|
|
|
| member_init
|
|
|
|
|
{ $$ = 1; }
|
|
|
|
|
| member_init_list ',' member_init
|
|
|
|
|
| member_init_list error
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
member_init:
|
|
|
|
|
'(' nonnull_exprlist ')'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (current_class_name)
|
1996-09-18 05:35:50 +00:00
|
|
|
|
pedwarn ("anachronistic old style base class initializer");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
expand_member_init (current_class_ref, NULL_TREE, $2);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| LEFT_RIGHT
|
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (current_class_name)
|
1996-09-18 05:35:50 +00:00
|
|
|
|
pedwarn ("anachronistic old style base class initializer");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
expand_member_init (current_class_ref, NULL_TREE, void_type_node);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| notype_identifier '(' nonnull_exprlist ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ expand_member_init (current_class_ref, $1, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| notype_identifier LEFT_RIGHT
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ expand_member_init (current_class_ref, $1, void_type_node); }
|
|
|
|
|
| nonnested_type '(' nonnull_exprlist ')'
|
|
|
|
|
{ expand_member_init (current_class_ref, $1, $3); }
|
|
|
|
|
| nonnested_type LEFT_RIGHT
|
|
|
|
|
{ expand_member_init (current_class_ref, $1, void_type_node); }
|
|
|
|
|
| typename_sub '(' nonnull_exprlist ')'
|
|
|
|
|
{ expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
|
|
|
|
|
$3); }
|
|
|
|
|
| typename_sub LEFT_RIGHT
|
|
|
|
|
{ expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
|
|
|
|
|
void_type_node); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
identifier:
|
|
|
|
|
IDENTIFIER
|
|
|
|
|
| TYPENAME
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| SELFNAME
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| PTYPENAME
|
|
|
|
|
| NSNAME
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_identifier:
|
|
|
|
|
IDENTIFIER
|
|
|
|
|
| PTYPENAME
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| NSNAME %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
identifier_defn:
|
|
|
|
|
IDENTIFIER_DEFN
|
|
|
|
|
| TYPENAME_DEFN
|
|
|
|
|
| PTYPENAME_DEFN
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
explicit_instantiation:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
TEMPLATE begin_explicit_instantiation typespec ';'
|
|
|
|
|
{ do_type_instantiation ($3.t, NULL_TREE);
|
|
|
|
|
yyungetc (';', 1); }
|
|
|
|
|
end_explicit_instantiation
|
|
|
|
|
| TEMPLATE begin_explicit_instantiation typed_declspecs declarator
|
|
|
|
|
{ tree specs = strip_attrs ($3.t);
|
|
|
|
|
do_decl_instantiation (specs, $4, NULL_TREE); }
|
|
|
|
|
end_explicit_instantiation
|
|
|
|
|
| TEMPLATE begin_explicit_instantiation notype_declarator
|
|
|
|
|
{ do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
|
|
|
|
|
end_explicit_instantiation
|
|
|
|
|
| TEMPLATE begin_explicit_instantiation constructor_declarator
|
|
|
|
|
{ do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
|
|
|
|
|
end_explicit_instantiation
|
|
|
|
|
| SCSPEC TEMPLATE begin_explicit_instantiation typespec ';'
|
|
|
|
|
{ do_type_instantiation ($4.t, $1);
|
|
|
|
|
yyungetc (';', 1); }
|
|
|
|
|
end_explicit_instantiation
|
|
|
|
|
| SCSPEC TEMPLATE begin_explicit_instantiation typed_declspecs
|
|
|
|
|
declarator
|
|
|
|
|
{ tree specs = strip_attrs ($4.t);
|
|
|
|
|
do_decl_instantiation (specs, $5, $1); }
|
|
|
|
|
end_explicit_instantiation
|
|
|
|
|
| SCSPEC TEMPLATE begin_explicit_instantiation notype_declarator
|
|
|
|
|
{ do_decl_instantiation (NULL_TREE, $4, $1); }
|
|
|
|
|
end_explicit_instantiation
|
|
|
|
|
| SCSPEC TEMPLATE begin_explicit_instantiation constructor_declarator
|
|
|
|
|
{ do_decl_instantiation (NULL_TREE, $4, $1); }
|
|
|
|
|
end_explicit_instantiation
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
begin_explicit_instantiation:
|
|
|
|
|
{ begin_explicit_instantiation(); }
|
|
|
|
|
|
|
|
|
|
end_explicit_instantiation:
|
|
|
|
|
{ end_explicit_instantiation(); }
|
|
|
|
|
|
|
|
|
|
/* The TYPENAME expansions are to deal with use of a template class name as
|
|
|
|
|
a template within the class itself, where the template decl is hidden by
|
|
|
|
|
a type decl. Got all that? */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
template_type:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
PTYPENAME '<' template_arg_list_opt template_close_bracket
|
1999-10-16 06:09:09 +00:00
|
|
|
|
.finish_template_type
|
|
|
|
|
{ $$ = $5; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| TYPENAME '<' template_arg_list_opt template_close_bracket
|
1999-10-16 06:09:09 +00:00
|
|
|
|
.finish_template_type
|
|
|
|
|
{ $$ = $5; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| self_template_type
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
apparent_template_type:
|
|
|
|
|
template_type
|
|
|
|
|
| identifier '<' template_arg_list_opt '>'
|
|
|
|
|
.finish_template_type
|
|
|
|
|
{ $$ = $5; }
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
self_template_type:
|
|
|
|
|
SELFNAME '<' template_arg_list_opt template_close_bracket
|
1999-10-16 06:09:09 +00:00
|
|
|
|
.finish_template_type
|
|
|
|
|
{ $$ = $5; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
.finish_template_type:
|
|
|
|
|
{
|
|
|
|
|
if (yychar == YYEMPTY)
|
|
|
|
|
yychar = YYLEX;
|
|
|
|
|
|
|
|
|
|
$$ = finish_template_type ($<ttype>-3, $<ttype>-1,
|
|
|
|
|
yychar == SCOPE);
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
template_close_bracket:
|
|
|
|
|
'>'
|
|
|
|
|
| RSHIFT
|
|
|
|
|
{
|
|
|
|
|
/* Handle `Class<Class<Type>>' without space in the `>>' */
|
|
|
|
|
pedwarn ("`>>' should be `> >' in template class name");
|
|
|
|
|
yyungetc ('>', 1);
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
template_arg_list_opt:
|
|
|
|
|
/* empty */
|
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
| template_arg_list
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
template_arg_list:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
template_arg
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = build_tree_list (NULL_TREE, $$); }
|
|
|
|
|
| template_arg_list ',' template_arg
|
|
|
|
|
{ $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
template_arg:
|
|
|
|
|
type_id
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = groktypename ($1.t); }
|
|
|
|
|
| PTYPENAME
|
|
|
|
|
{ $$ = lastiddecl; }
|
|
|
|
|
| expr_no_commas %prec ARITHCOMPARE
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
unop:
|
|
|
|
|
'-'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NEGATE_EXPR; }
|
|
|
|
|
| '+'
|
|
|
|
|
{ $$ = CONVERT_EXPR; }
|
|
|
|
|
| PLUSPLUS
|
|
|
|
|
{ $$ = PREINCREMENT_EXPR; }
|
|
|
|
|
| MINUSMINUS
|
|
|
|
|
{ $$ = PREDECREMENT_EXPR; }
|
|
|
|
|
| '!'
|
|
|
|
|
{ $$ = TRUTH_NOT_EXPR; }
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
expr:
|
|
|
|
|
nontrivial_exprlist
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = build_x_compound_expr ($$); }
|
|
|
|
|
| expr_no_commas
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
paren_expr_or_null:
|
|
|
|
|
LEFT_RIGHT
|
|
|
|
|
{ error ("ANSI C++ forbids an empty condition for `%s'",
|
|
|
|
|
cond_stmt_keyword);
|
|
|
|
|
$$ = integer_zero_node; }
|
|
|
|
|
| '(' expr ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = $2; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
paren_cond_or_null:
|
|
|
|
|
LEFT_RIGHT
|
|
|
|
|
{ error ("ANSI C++ forbids an empty condition for `%s'",
|
|
|
|
|
cond_stmt_keyword);
|
|
|
|
|
$$ = integer_zero_node; }
|
|
|
|
|
| '(' condition ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = $2; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
xcond:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
| condition
|
|
|
|
|
| error
|
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
condition:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
type_specifier_seq declarator maybeasm maybe_attribute '='
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ {
|
|
|
|
|
tree d;
|
|
|
|
|
for (d = getdecls (); d; d = TREE_CHAIN (d))
|
|
|
|
|
if (TREE_CODE (d) == TYPE_DECL) {
|
|
|
|
|
tree s = TREE_TYPE (d);
|
|
|
|
|
if (TREE_CODE (s) == RECORD_TYPE)
|
|
|
|
|
cp_error ("definition of class `%T' in condition", s);
|
|
|
|
|
else if (TREE_CODE (s) == ENUMERAL_TYPE)
|
|
|
|
|
cp_error ("definition of enum `%T' in condition", s);
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
current_declspecs = $1.t;
|
|
|
|
|
$<itype>5 = suspend_momentary ();
|
|
|
|
|
$<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1,
|
|
|
|
|
$4, /*prefix_attributes*/ NULL_TREE);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
init
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
cp_finish_decl ($<ttype>6, $7, $4, 1, LOOKUP_ONLYCONVERTING);
|
|
|
|
|
resume_momentary ($<itype>5);
|
|
|
|
|
$$ = convert_from_reference ($<ttype>6);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
if (TREE_CODE (TREE_TYPE ($$)) == ARRAY_TYPE)
|
|
|
|
|
cp_error ("definition of array `%#D' in condition", $$);
|
|
|
|
|
}
|
|
|
|
|
| expr
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
compstmtend:
|
|
|
|
|
'}'
|
|
|
|
|
| maybe_label_decls stmts '}'
|
|
|
|
|
| maybe_label_decls stmts error '}'
|
|
|
|
|
| maybe_label_decls error '}'
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
already_scoped_stmt:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
'{'
|
|
|
|
|
{ $<ttype>$ = begin_compound_stmt (1); }
|
|
|
|
|
compstmtend
|
|
|
|
|
{ finish_compound_stmt (1, $<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| simple_stmt
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nontrivial_exprlist:
|
|
|
|
|
expr_no_commas ',' expr_no_commas
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = expr_tree_cons (NULL_TREE, $$,
|
|
|
|
|
build_expr_list (NULL_TREE, $3)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| expr_no_commas ',' error
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = expr_tree_cons (NULL_TREE, $$,
|
|
|
|
|
build_expr_list (NULL_TREE, error_mark_node)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| nontrivial_exprlist ',' expr_no_commas
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ chainon ($$, build_expr_list (NULL_TREE, $3)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| nontrivial_exprlist ',' error
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ chainon ($$, build_expr_list (NULL_TREE, error_mark_node)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
nonnull_exprlist:
|
|
|
|
|
expr_no_commas
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_expr_list (NULL_TREE, $$); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| nontrivial_exprlist
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
unary_expr:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
primary %prec UNARY
|
|
|
|
|
{ $$ = $1; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* __extension__ turns off -pedantic for following primary. */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| extension cast_expr %prec UNARY
|
|
|
|
|
{ $$ = $2;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
pedantic = $<itype>1; }
|
|
|
|
|
| '*' cast_expr %prec UNARY
|
|
|
|
|
{ $$ = build_x_indirect_ref ($2, "unary *"); }
|
|
|
|
|
| '&' cast_expr %prec UNARY
|
|
|
|
|
{ $$ = build_x_unary_op (ADDR_EXPR, $2); }
|
|
|
|
|
| '~' cast_expr
|
|
|
|
|
{ $$ = build_x_unary_op (BIT_NOT_EXPR, $2); }
|
|
|
|
|
| unop cast_expr %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_unary_op_expr ($1, $2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* Refer to the address of a label as a pointer. */
|
|
|
|
|
| ANDAND identifier
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ if (pedantic)
|
|
|
|
|
pedwarn ("ANSI C++ forbids `&&'");
|
|
|
|
|
$$ = finish_label_address_expr ($2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| SIZEOF unary_expr %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = expr_sizeof ($2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| SIZEOF '(' type_id ')' %prec HYPERUNARY
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = c_sizeof (groktypename ($3.t));
|
|
|
|
|
check_for_new_type ("sizeof", $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| ALIGNOF unary_expr %prec UNARY
|
|
|
|
|
{ $$ = grok_alignof ($2); }
|
|
|
|
|
| ALIGNOF '(' type_id ')' %prec HYPERUNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = c_alignof (groktypename ($3.t));
|
|
|
|
|
check_for_new_type ("alignof", $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
/* The %prec EMPTY's here are required by the = init initializer
|
|
|
|
|
syntax extension; see below. */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| new new_type_id %prec EMPTY
|
|
|
|
|
{ $$ = build_new (NULL_TREE, $2.t, NULL_TREE, $1);
|
|
|
|
|
check_for_new_type ("new", $2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| new new_type_id new_initializer
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_new (NULL_TREE, $2.t, $3, $1);
|
|
|
|
|
check_for_new_type ("new", $2); }
|
|
|
|
|
| new new_placement new_type_id %prec EMPTY
|
|
|
|
|
{ $$ = build_new ($2, $3.t, NULL_TREE, $1);
|
|
|
|
|
check_for_new_type ("new", $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| new new_placement new_type_id new_initializer
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_new ($2, $3.t, $4, $1);
|
|
|
|
|
check_for_new_type ("new", $3); }
|
|
|
|
|
/* The .begin_new_placement in the following rules is
|
|
|
|
|
necessary to avoid shift/reduce conflicts that lead to
|
|
|
|
|
mis-parsing some expressions. Of course, these constructs
|
|
|
|
|
are not really new-placement and it is bogus to call
|
|
|
|
|
begin_new_placement. But, the parser cannot always tell at this
|
|
|
|
|
point whether the next thing is an expression or a type-id,
|
|
|
|
|
so there is nothing we can do. Fortunately,
|
|
|
|
|
begin_new_placement does nothing harmful. When we rewrite
|
|
|
|
|
the parser, this lossage should be removed, of course. */
|
|
|
|
|
| new '(' .begin_new_placement type_id .finish_new_placement
|
|
|
|
|
%prec EMPTY
|
|
|
|
|
{ $$ = build_new (NULL_TREE, groktypename($4.t),
|
|
|
|
|
NULL_TREE, $1);
|
|
|
|
|
check_for_new_type ("new", $4); }
|
|
|
|
|
| new '(' .begin_new_placement type_id .finish_new_placement
|
|
|
|
|
new_initializer
|
|
|
|
|
{ $$ = build_new (NULL_TREE, groktypename($4.t), $6, $1);
|
|
|
|
|
check_for_new_type ("new", $4); }
|
|
|
|
|
| new new_placement '(' .begin_new_placement type_id
|
|
|
|
|
.finish_new_placement %prec EMPTY
|
|
|
|
|
{ $$ = build_new ($2, groktypename($5.t), NULL_TREE, $1);
|
|
|
|
|
check_for_new_type ("new", $5); }
|
|
|
|
|
| new new_placement '(' .begin_new_placement type_id
|
|
|
|
|
.finish_new_placement new_initializer
|
|
|
|
|
{ $$ = build_new ($2, groktypename($5.t), $7, $1);
|
|
|
|
|
check_for_new_type ("new", $5); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
| delete cast_expr %prec UNARY
|
|
|
|
|
{ $$ = delete_sanity ($2, NULL_TREE, 0, $1); }
|
|
|
|
|
| delete '[' ']' cast_expr %prec UNARY
|
|
|
|
|
{ $$ = delete_sanity ($4, NULL_TREE, 1, $1);
|
|
|
|
|
if (yychar == YYEMPTY)
|
|
|
|
|
yychar = YYLEX; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| delete '[' expr ']' cast_expr %prec UNARY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = delete_sanity ($5, $3, 2, $1);
|
|
|
|
|
if (yychar == YYEMPTY)
|
|
|
|
|
yychar = YYLEX; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| REALPART cast_expr %prec UNARY
|
|
|
|
|
{ $$ = build_x_unary_op (REALPART_EXPR, $2); }
|
|
|
|
|
| IMAGPART cast_expr %prec UNARY
|
|
|
|
|
{ $$ = build_x_unary_op (IMAGPART_EXPR, $2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* Note this rule is not suitable for use in new_placement
|
|
|
|
|
since it uses NULL_TREE as the argument to
|
|
|
|
|
finish_new_placement. This rule serves only to avoid
|
|
|
|
|
reduce/reduce conflicts in unary_expr. See the comments
|
|
|
|
|
there on the use of begin/finish_new_placement. */
|
|
|
|
|
.finish_new_placement:
|
|
|
|
|
')'
|
|
|
|
|
{ finish_new_placement (NULL_TREE, $<itype>-1); }
|
|
|
|
|
|
|
|
|
|
.begin_new_placement:
|
|
|
|
|
{ $$ = begin_new_placement (); }
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
new_placement:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
'(' .begin_new_placement nonnull_exprlist ')'
|
|
|
|
|
{ $$ = finish_new_placement ($3, $2); }
|
|
|
|
|
| '{' .begin_new_placement nonnull_exprlist '}'
|
|
|
|
|
{ cp_pedwarn ("old style placement syntax, use () instead");
|
|
|
|
|
$$ = finish_new_placement ($3, $2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
new_initializer:
|
|
|
|
|
'(' nonnull_exprlist ')'
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
| LEFT_RIGHT
|
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
| '(' typespec ')'
|
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
cp_error ("`%T' is not a valid expression", $2.t);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
$$ = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
/* GNU extension so people can use initializer lists. Note that
|
|
|
|
|
this alters the meaning of `new int = 1', which was previously
|
|
|
|
|
syntactically valid but semantically invalid. */
|
|
|
|
|
| '=' init
|
|
|
|
|
{
|
|
|
|
|
if (pedantic)
|
|
|
|
|
pedwarn ("ANSI C++ forbids initialization of new expression with `='");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (TREE_CODE ($2) != TREE_LIST
|
|
|
|
|
&& TREE_CODE ($2) != CONSTRUCTOR)
|
|
|
|
|
$$ = build_expr_list (NULL_TREE, $2);
|
|
|
|
|
else
|
|
|
|
|
$$ = $2;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* This is necessary to postpone reduction of `int ((int)(int)(int))'. */
|
|
|
|
|
regcast_or_absdcl:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
'(' type_id ')' %prec EMPTY
|
|
|
|
|
{ $2.t = finish_parmlist (build_tree_list (NULL_TREE, $2.t), 0);
|
|
|
|
|
$$ = make_call_declarator (NULL_TREE, $2.t, NULL_TREE, NULL_TREE);
|
|
|
|
|
check_for_new_type ("cast", $2); }
|
|
|
|
|
| regcast_or_absdcl '(' type_id ')' %prec EMPTY
|
|
|
|
|
{ $3.t = finish_parmlist (build_tree_list (NULL_TREE, $3.t), 0);
|
|
|
|
|
$$ = make_call_declarator ($$, $3.t, NULL_TREE, NULL_TREE);
|
|
|
|
|
check_for_new_type ("cast", $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
cast_expr:
|
|
|
|
|
unary_expr
|
|
|
|
|
| regcast_or_absdcl unary_expr %prec UNARY
|
|
|
|
|
{ $$ = reparse_absdcl_as_casts ($$, $2); }
|
|
|
|
|
| regcast_or_absdcl '{' initlist maybecomma '}' %prec UNARY
|
|
|
|
|
{
|
|
|
|
|
tree init = build_nt (CONSTRUCTOR, NULL_TREE,
|
|
|
|
|
nreverse ($3));
|
|
|
|
|
if (pedantic)
|
|
|
|
|
pedwarn ("ANSI C++ forbids constructor-expressions");
|
|
|
|
|
/* Indicate that this was a GNU C constructor expression. */
|
|
|
|
|
TREE_HAS_CONSTRUCTOR (init) = 1;
|
|
|
|
|
|
|
|
|
|
$$ = reparse_absdcl_as_casts ($$, init);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
expr_no_commas:
|
|
|
|
|
cast_expr
|
|
|
|
|
/* Handle general members. */
|
|
|
|
|
| expr_no_commas POINTSAT_STAR expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op (MEMBER_REF, $$, $3); }
|
|
|
|
|
| expr_no_commas DOT_STAR expr_no_commas
|
|
|
|
|
{ $$ = build_m_component_ref ($$, $3); }
|
|
|
|
|
| expr_no_commas '+' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas '-' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas '*' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas '/' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas '%' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas LSHIFT expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas RSHIFT expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas ARITHCOMPARE expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas '<' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op (LT_EXPR, $$, $3); }
|
|
|
|
|
| expr_no_commas '>' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op (GT_EXPR, $$, $3); }
|
|
|
|
|
| expr_no_commas EQCOMPARE expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas MIN_MAX expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas '&' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas '|' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas '^' expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op ($2, $$, $3); }
|
|
|
|
|
| expr_no_commas ANDAND expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op (TRUTH_ANDIF_EXPR, $$, $3); }
|
|
|
|
|
| expr_no_commas OROR expr_no_commas
|
|
|
|
|
{ $$ = build_x_binary_op (TRUTH_ORIF_EXPR, $$, $3); }
|
|
|
|
|
| expr_no_commas '?' xexpr ':' expr_no_commas
|
|
|
|
|
{ $$ = build_x_conditional_expr ($$, $3, $5); }
|
|
|
|
|
| expr_no_commas '=' expr_no_commas
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_x_modify_expr ($$, NOP_EXPR, $3);
|
|
|
|
|
if ($$ != error_mark_node)
|
|
|
|
|
C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| expr_no_commas ASSIGN expr_no_commas
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_x_modify_expr ($$, $2, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| THROW
|
|
|
|
|
{ $$ = build_throw (NULL_TREE); }
|
|
|
|
|
| THROW expr_no_commas
|
|
|
|
|
{ $$ = build_throw ($2); }
|
|
|
|
|
/* These extensions are not defined. The second arg to build_m_component_ref
|
|
|
|
|
is old, build_m_component_ref now does an implicit
|
|
|
|
|
build_indirect_ref (x, NULL_PTR) on the second argument.
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| object '&' expr_no_commas %prec UNARY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = build_m_component_ref ($$, build_x_unary_op (ADDR_EXPR, $3)); }
|
|
|
|
|
| object unop expr_no_commas %prec UNARY
|
|
|
|
|
{ $$ = build_m_component_ref ($$, build_x_unary_op ($2, $3)); }
|
|
|
|
|
| object '(' type_id ')' expr_no_commas %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ tree type = groktypename ($3.t);
|
|
|
|
|
$$ = build_m_component_ref ($$, build_c_cast (type, $5)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| object primary_no_id %prec UNARY
|
|
|
|
|
{ $$ = build_m_component_ref ($$, $2); }
|
|
|
|
|
*/
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_unqualified_id:
|
|
|
|
|
'~' see_typename identifier
|
|
|
|
|
{ $$ = build_parse_node (BIT_NOT_EXPR, $3); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '~' see_typename template_type
|
|
|
|
|
{ $$ = build_parse_node (BIT_NOT_EXPR, $3); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| template_id
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| operator_name
|
|
|
|
|
| IDENTIFIER
|
|
|
|
|
| PTYPENAME
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| NSNAME %prec EMPTY
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
do_id:
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
/* If lastiddecl is a TREE_LIST, it's a baselink, which
|
|
|
|
|
means that we're in an expression like S::f<int>, so
|
|
|
|
|
don't do_identifier; we only do that for unqualified
|
|
|
|
|
identifiers. */
|
|
|
|
|
if (lastiddecl && TREE_CODE (lastiddecl) != TREE_LIST)
|
|
|
|
|
$$ = do_identifier ($<ttype>-1, 1, NULL_TREE);
|
|
|
|
|
else
|
|
|
|
|
$$ = $<ttype>-1;
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
|
|
|
|
|
template_id:
|
|
|
|
|
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
|
|
|
|
|
{ $$ = lookup_template_function ($3, $4); }
|
|
|
|
|
| operator_name '<' do_id template_arg_list_opt template_close_bracket
|
|
|
|
|
{ $$ = lookup_template_function ($3, $4); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
object_template_id:
|
|
|
|
|
TEMPLATE identifier '<' template_arg_list_opt template_close_bracket
|
|
|
|
|
{ $$ = lookup_template_function ($2, $4); }
|
|
|
|
|
| TEMPLATE PFUNCNAME '<' template_arg_list_opt template_close_bracket
|
|
|
|
|
{ $$ = lookup_template_function ($2, $4); }
|
|
|
|
|
| TEMPLATE operator_name '<' template_arg_list_opt
|
|
|
|
|
template_close_bracket
|
|
|
|
|
{ $$ = lookup_template_function ($2, $4); }
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
unqualified_id:
|
|
|
|
|
notype_unqualified_id
|
|
|
|
|
| TYPENAME
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| SELFNAME
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
expr_or_declarator_intern:
|
|
|
|
|
expr_or_declarator
|
|
|
|
|
| attributes expr_or_declarator
|
|
|
|
|
{
|
|
|
|
|
/* Provide support for '(' attributes '*' declarator ')'
|
|
|
|
|
etc */
|
|
|
|
|
$$ = decl_tree_cons ($1, $2, NULL_TREE);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
expr_or_declarator:
|
|
|
|
|
notype_unqualified_id
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '*' expr_or_declarator_intern %prec UNARY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = build_parse_node (INDIRECT_REF, $2); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '&' expr_or_declarator_intern %prec UNARY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = build_parse_node (ADDR_EXPR, $2); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '(' expr_or_declarator_intern ')'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
notype_template_declarator:
|
|
|
|
|
IDENTIFIER '<' template_arg_list_opt template_close_bracket
|
|
|
|
|
{ $$ = lookup_template_function ($1, $3); }
|
|
|
|
|
| NSNAME '<' template_arg_list template_close_bracket
|
|
|
|
|
{ $$ = lookup_template_function ($1, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
direct_notype_declarator:
|
|
|
|
|
complex_direct_notype_declarator
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* This precedence declaration is to prefer this reduce
|
|
|
|
|
to the Koenig lookup shift in primary, below. I hate yacc. */
|
|
|
|
|
| notype_unqualified_id %prec '('
|
|
|
|
|
| notype_template_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '(' expr_or_declarator_intern ')'
|
|
|
|
|
{ $$ = finish_decl_parsing ($2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
primary:
|
|
|
|
|
notype_unqualified_id
|
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (TREE_CODE ($1) == BIT_NOT_EXPR)
|
|
|
|
|
$$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($1, 0));
|
|
|
|
|
else
|
|
|
|
|
$$ = finish_id_expr ($1);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| CONSTANT
|
|
|
|
|
| boolean.literal
|
|
|
|
|
| string
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
if (processing_template_decl)
|
|
|
|
|
push_obstacks (&permanent_obstack, &permanent_obstack);
|
|
|
|
|
$$ = combine_strings ($$);
|
1999-10-16 06:09:09 +00:00
|
|
|
|
/* combine_strings doesn't set up TYPE_MAIN_VARIANT of
|
|
|
|
|
a const array the way we want, so fix it. */
|
|
|
|
|
if (flag_const_strings)
|
|
|
|
|
TREE_TYPE ($$) = build_cplus_array_type
|
|
|
|
|
(TREE_TYPE (TREE_TYPE ($$)),
|
|
|
|
|
TYPE_DOMAIN (TREE_TYPE ($$)));
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (processing_template_decl)
|
|
|
|
|
pop_obstacks ();
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '(' expr ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_parenthesized_expr ($2); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '(' expr_or_declarator_intern ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $2 = reparse_decl_as_expr (NULL_TREE, $2);
|
|
|
|
|
$$ = finish_parenthesized_expr ($2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '(' error ')'
|
|
|
|
|
{ $$ = error_mark_node; }
|
|
|
|
|
| '('
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ tree scope = current_scope ();
|
|
|
|
|
if (!scope || TREE_CODE (scope) != FUNCTION_DECL)
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
|
|
|
|
error ("braced-group within expression allowed only inside a function");
|
|
|
|
|
YYERROR;
|
|
|
|
|
}
|
|
|
|
|
if (pedantic)
|
1999-08-26 09:30:50 +00:00
|
|
|
|
pedwarn ("ANSI C++ forbids braced-groups within expressions");
|
|
|
|
|
$<ttype>$ = begin_stmt_expr ();
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
compstmt ')'
|
|
|
|
|
{ $$ = finish_stmt_expr ($<ttype>2, $3); }
|
|
|
|
|
/* Koenig lookup support
|
|
|
|
|
We could store lastiddecl in $1 to avoid another lookup,
|
|
|
|
|
but that would result in many additional reduce/reduce conflicts. */
|
|
|
|
|
| notype_unqualified_id '(' nonnull_exprlist ')'
|
|
|
|
|
{ $$ = finish_call_expr ($1, $3, 1); }
|
|
|
|
|
| notype_unqualified_id LEFT_RIGHT
|
|
|
|
|
{ $$ = finish_call_expr ($1, NULL_TREE, 1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| primary '(' nonnull_exprlist ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_call_expr ($1, $3, 0); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| primary LEFT_RIGHT
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_call_expr ($1, NULL_TREE, 0); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| primary '[' expr ']'
|
|
|
|
|
{ $$ = grok_array_decl ($$, $3); }
|
|
|
|
|
| primary PLUSPLUS
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_increment_expr ($1, POSTINCREMENT_EXPR); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| primary MINUSMINUS
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_increment_expr ($1, POSTDECREMENT_EXPR); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* C++ extensions */
|
|
|
|
|
| THIS
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_this_expr (); }
|
|
|
|
|
| CV_QUALIFIER '(' nonnull_exprlist ')'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-10-16 06:09:09 +00:00
|
|
|
|
/* This is a C cast in C++'s `functional' notation
|
|
|
|
|
using the "implicit int" extension so that:
|
|
|
|
|
`const (3)' is equivalent to `const int (3)'. */
|
|
|
|
|
tree type;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
if ($3 == error_mark_node)
|
|
|
|
|
{
|
|
|
|
|
$$ = error_mark_node;
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-10-16 06:09:09 +00:00
|
|
|
|
|
|
|
|
|
type = cp_build_qualified_type (integer_type_node,
|
|
|
|
|
cp_type_qual_from_rid ($1));
|
|
|
|
|
$$ = build_c_cast (type, build_compound_expr ($3));
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| functional_cast
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| DYNAMIC_CAST '<' type_id '>' '(' expr ')'
|
|
|
|
|
{ tree type = groktypename ($3.t);
|
|
|
|
|
check_for_new_type ("dynamic_cast", $3);
|
|
|
|
|
$$ = build_dynamic_cast (type, $6); }
|
|
|
|
|
| STATIC_CAST '<' type_id '>' '(' expr ')'
|
|
|
|
|
{ tree type = groktypename ($3.t);
|
|
|
|
|
check_for_new_type ("static_cast", $3);
|
|
|
|
|
$$ = build_static_cast (type, $6); }
|
|
|
|
|
| REINTERPRET_CAST '<' type_id '>' '(' expr ')'
|
|
|
|
|
{ tree type = groktypename ($3.t);
|
|
|
|
|
check_for_new_type ("reinterpret_cast", $3);
|
|
|
|
|
$$ = build_reinterpret_cast (type, $6); }
|
|
|
|
|
| CONST_CAST '<' type_id '>' '(' expr ')'
|
|
|
|
|
{ tree type = groktypename ($3.t);
|
|
|
|
|
check_for_new_type ("const_cast", $3);
|
|
|
|
|
$$ = build_const_cast (type, $6); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| TYPEID '(' expr ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_x_typeid ($3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| TYPEID '(' type_id ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ tree type = groktypename ($3.t);
|
|
|
|
|
check_for_new_type ("typeid", $3);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
$$ = get_typeid (TYPE_MAIN_VARIANT (type)); }
|
|
|
|
|
| global_scope IDENTIFIER
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = do_scoped_id ($2, 1); }
|
|
|
|
|
| global_scope template_id
|
|
|
|
|
{ $$ = $2; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| global_scope operator_name
|
|
|
|
|
{
|
|
|
|
|
got_scope = NULL_TREE;
|
|
|
|
|
if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = do_scoped_id ($2, 1);
|
|
|
|
|
else
|
|
|
|
|
$$ = $2;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| overqualified_id %prec HYPERUNARY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
|
|
|
|
|
| overqualified_id '(' nonnull_exprlist ')'
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = finish_qualified_call_expr ($1, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| overqualified_id LEFT_RIGHT
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = finish_qualified_call_expr ($1, NULL_TREE); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| object object_template_id %prec UNARY
|
|
|
|
|
{
|
|
|
|
|
$$ = build_x_component_ref ($$, $2, NULL_TREE, 1);
|
|
|
|
|
}
|
|
|
|
|
| object object_template_id '(' nonnull_exprlist ')'
|
|
|
|
|
{ $$ = finish_object_call_expr ($2, $1, $4); }
|
|
|
|
|
| object object_template_id LEFT_RIGHT
|
|
|
|
|
{ $$ = finish_object_call_expr ($2, $1, NULL_TREE); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| object unqualified_id %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); }
|
|
|
|
|
| object overqualified_id %prec UNARY
|
|
|
|
|
{ if (processing_template_decl)
|
|
|
|
|
$$ = build_min_nt (COMPONENT_REF, $1, copy_to_permanent ($2));
|
|
|
|
|
else
|
|
|
|
|
$$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| object unqualified_id '(' nonnull_exprlist ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_object_call_expr ($2, $1, $4); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| object unqualified_id LEFT_RIGHT
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_object_call_expr ($2, $1, NULL_TREE); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| object overqualified_id '(' nonnull_exprlist ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_qualified_object_call_expr ($2, $1, $4); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| object overqualified_id LEFT_RIGHT
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_qualified_object_call_expr ($2, $1, NULL_TREE); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* p->int::~int() is valid -- 12.4 */
|
|
|
|
|
| object '~' TYPESPEC LEFT_RIGHT
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_pseudo_destructor_call_expr ($1, NULL_TREE, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_pseudo_destructor_call_expr ($1, $2, $5); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| object error
|
|
|
|
|
{
|
|
|
|
|
$$ = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Not needed for now.
|
|
|
|
|
|
|
|
|
|
primary_no_id:
|
|
|
|
|
'(' expr ')'
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
| '(' error ')'
|
|
|
|
|
{ $$ = error_mark_node; }
|
|
|
|
|
| '('
|
|
|
|
|
{ if (current_function_decl == 0)
|
|
|
|
|
{
|
|
|
|
|
error ("braced-group within expression allowed only inside a function");
|
|
|
|
|
YYERROR;
|
|
|
|
|
}
|
|
|
|
|
$<ttype>$ = expand_start_stmt_expr (); }
|
|
|
|
|
compstmt ')'
|
|
|
|
|
{ if (pedantic)
|
|
|
|
|
pedwarn ("ANSI C++ forbids braced-groups within expressions");
|
|
|
|
|
$$ = expand_end_stmt_expr ($<ttype>2); }
|
|
|
|
|
| primary_no_id '(' nonnull_exprlist ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_x_function_call ($$, $3, current_class_ref); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| primary_no_id LEFT_RIGHT
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_x_function_call ($$, NULL_TREE, current_class_ref); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| primary_no_id '[' expr ']'
|
|
|
|
|
{ goto do_array; }
|
|
|
|
|
| primary_no_id PLUSPLUS
|
|
|
|
|
{ $$ = build_x_unary_op (POSTINCREMENT_EXPR, $$); }
|
|
|
|
|
| primary_no_id MINUSMINUS
|
|
|
|
|
{ $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); }
|
|
|
|
|
| SCOPE IDENTIFIER
|
|
|
|
|
{ goto do_scoped_id; }
|
|
|
|
|
| SCOPE operator_name
|
|
|
|
|
{ if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
|
|
|
|
goto do_scoped_id;
|
|
|
|
|
goto do_scoped_operator;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
*/
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
new:
|
|
|
|
|
NEW
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = 0; }
|
|
|
|
|
| global_scope NEW
|
|
|
|
|
{ got_scope = NULL_TREE; $$ = 1; }
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
delete:
|
|
|
|
|
DELETE
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = 0; }
|
|
|
|
|
| global_scope delete
|
|
|
|
|
{ got_scope = NULL_TREE; $$ = 1; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
boolean.literal:
|
|
|
|
|
CXX_TRUE
|
|
|
|
|
{ $$ = boolean_true_node; }
|
|
|
|
|
| CXX_FALSE
|
|
|
|
|
{ $$ = boolean_false_node; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
|
|
|
|
|
string:
|
|
|
|
|
STRING
|
|
|
|
|
| string STRING
|
|
|
|
|
{ $$ = chainon ($$, $2); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
nodecls:
|
|
|
|
|
/* empty */
|
|
|
|
|
{
|
|
|
|
|
if (! current_function_parms_stored)
|
|
|
|
|
store_parm_decls ();
|
|
|
|
|
setup_vtbl_ptr ();
|
|
|
|
|
/* Always keep the BLOCK node associated with the outermost
|
|
|
|
|
pair of curley braces of a function. These are needed
|
|
|
|
|
for correct operation of dwarfout.c. */
|
|
|
|
|
keep_next_level ();
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
object:
|
|
|
|
|
primary '.'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ got_object = TREE_TYPE ($$); }
|
|
|
|
|
| primary POINTSAT
|
|
|
|
|
{
|
|
|
|
|
$$ = build_x_arrow ($$);
|
|
|
|
|
got_object = TREE_TYPE ($$);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
decl:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
typespec initdecls ';'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
|
|
|
|
resume_momentary ($2);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if ($1.t && IS_AGGR_TYPE_CODE (TREE_CODE ($1.t)))
|
|
|
|
|
note_got_semicolon ($1.t);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| typed_declspecs initdecls ';'
|
|
|
|
|
{
|
|
|
|
|
resume_momentary ($2);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
note_list_got_semicolon ($1.t);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| declmods notype_initdecls ';'
|
|
|
|
|
{ resume_momentary ($2); }
|
|
|
|
|
| typed_declspecs ';'
|
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
shadow_tag ($1.t);
|
|
|
|
|
note_list_got_semicolon ($1.t);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| declmods ';'
|
|
|
|
|
{ warning ("empty declaration"); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| extension decl
|
|
|
|
|
{ pedantic = $<itype>1; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Any kind of declarator (thus, all declarators allowed
|
|
|
|
|
after an explicit typespec). */
|
|
|
|
|
|
|
|
|
|
declarator:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
after_type_declarator %prec EMPTY
|
|
|
|
|
| notype_declarator %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* This is necessary to postpone reduction of `int()()()()'. */
|
|
|
|
|
fcast_or_absdcl:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
LEFT_RIGHT %prec EMPTY
|
|
|
|
|
{ $$ = make_call_declarator (NULL_TREE, empty_parms (),
|
|
|
|
|
NULL_TREE, NULL_TREE); }
|
|
|
|
|
| fcast_or_absdcl LEFT_RIGHT %prec EMPTY
|
|
|
|
|
{ $$ = make_call_declarator ($$, empty_parms (), NULL_TREE,
|
|
|
|
|
NULL_TREE); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* ANSI type-id (8.1) */
|
|
|
|
|
type_id:
|
|
|
|
|
typed_typespecs absdcl
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = build_decl_list ($1.t, $2);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
|
|
|
|
| nonempty_cv_qualifiers absdcl
|
|
|
|
|
{ $$.t = build_decl_list ($1.t, $2);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| typespec absdcl
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = build_decl_list (build_decl_list (NULL_TREE, $1.t),
|
|
|
|
|
$2);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
|
|
|
|
| typed_typespecs %prec EMPTY
|
|
|
|
|
{ $$.t = build_decl_list ($1.t, NULL_TREE);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
|
|
|
|
| nonempty_cv_qualifiers %prec EMPTY
|
|
|
|
|
{ $$.t = build_decl_list ($1.t, NULL_TREE);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Declspecs which contain at least one type specifier or typedef name.
|
|
|
|
|
(Just `const' or `volatile' is not enough.)
|
|
|
|
|
A typedef'd name following these is taken as a name to be declared.
|
|
|
|
|
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
|
|
|
|
|
|
|
|
|
|
typed_declspecs:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
typed_typespecs %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| typed_declspecs1
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
typed_declspecs1:
|
|
|
|
|
declmods typespec
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, $1);
|
|
|
|
|
$$.new_type_flag = $2.new_type_flag; }
|
|
|
|
|
| typespec reserved_declspecs %prec HYPERUNARY
|
|
|
|
|
{ $$.t = decl_tree_cons (NULL_TREE, $1.t, $2);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| typespec reserved_typespecquals reserved_declspecs
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = decl_tree_cons (NULL_TREE, $1.t, chainon ($2, $3));
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| declmods typespec reserved_declspecs
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1));
|
|
|
|
|
$$.new_type_flag = $2.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| declmods typespec reserved_typespecquals
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1));
|
|
|
|
|
$$.new_type_flag = $2.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| declmods typespec reserved_typespecquals reserved_declspecs
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = decl_tree_cons (NULL_TREE, $2.t,
|
|
|
|
|
chainon ($3, chainon ($4, $1)));
|
|
|
|
|
$$.new_type_flag = $2.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
reserved_declspecs:
|
|
|
|
|
SCSPEC
|
|
|
|
|
{ if (extra_warnings)
|
|
|
|
|
warning ("`%s' is not at beginning of declaration",
|
|
|
|
|
IDENTIFIER_POINTER ($$));
|
|
|
|
|
$$ = build_decl_list (NULL_TREE, $$); }
|
|
|
|
|
| reserved_declspecs typespecqual_reserved
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = decl_tree_cons (NULL_TREE, $2.t, $$); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| reserved_declspecs SCSPEC
|
|
|
|
|
{ if (extra_warnings)
|
|
|
|
|
warning ("`%s' is not at beginning of declaration",
|
|
|
|
|
IDENTIFIER_POINTER ($2));
|
|
|
|
|
$$ = decl_tree_cons (NULL_TREE, $2, $$); }
|
|
|
|
|
| reserved_declspecs attributes
|
|
|
|
|
{ $$ = decl_tree_cons ($2, NULL_TREE, $1); }
|
|
|
|
|
| attributes
|
|
|
|
|
{ $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* List of just storage classes and type modifiers.
|
|
|
|
|
A declaration can start with just this, but then it cannot be used
|
|
|
|
|
to redeclare a typedef-name.
|
|
|
|
|
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
/* We use hash_tree_cons for lists of typeless declspecs so that they end
|
|
|
|
|
up on a persistent obstack. Otherwise, they could appear at the
|
|
|
|
|
beginning of something like
|
|
|
|
|
|
|
|
|
|
static const struct { int foo () { } } b;
|
|
|
|
|
|
|
|
|
|
and would be discarded after we finish compiling foo. We don't need to
|
|
|
|
|
worry once we see a type. */
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
declmods:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
nonempty_cv_qualifiers %prec EMPTY
|
|
|
|
|
{ $$ = $1.t; TREE_STATIC ($$) = 1; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| SCSPEC
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = hash_tree_cons (NULL_TREE, $$, NULL_TREE); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| declmods CV_QUALIFIER
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = hash_tree_cons (NULL_TREE, $2, $$);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
TREE_STATIC ($$) = 1; }
|
|
|
|
|
| declmods SCSPEC
|
|
|
|
|
{ if (extra_warnings && TREE_STATIC ($$))
|
|
|
|
|
warning ("`%s' is not at beginning of declaration",
|
|
|
|
|
IDENTIFIER_POINTER ($2));
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$$ = hash_tree_cons (NULL_TREE, $2, $$);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
TREE_STATIC ($$) = TREE_STATIC ($1); }
|
|
|
|
|
| declmods attributes
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = hash_tree_cons ($2, NULL_TREE, $1); }
|
|
|
|
|
| attributes %prec EMPTY
|
|
|
|
|
{ $$ = hash_tree_cons ($1, NULL_TREE, NULL_TREE); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Used instead of declspecs where storage classes are not allowed
|
|
|
|
|
(that is, for typenames and structure components).
|
|
|
|
|
|
|
|
|
|
C++ can takes storage classes for structure components.
|
|
|
|
|
Don't accept a typedef-name if anything but a modifier precedes it. */
|
|
|
|
|
|
|
|
|
|
typed_typespecs:
|
|
|
|
|
typespec %prec EMPTY
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = build_decl_list (NULL_TREE, $1.t);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
|
|
|
|
| nonempty_cv_qualifiers typespec
|
|
|
|
|
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t);
|
|
|
|
|
$$.new_type_flag = $2.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| typespec reserved_typespecquals
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = decl_tree_cons (NULL_TREE, $1.t, $2);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
|
|
|
|
| nonempty_cv_qualifiers typespec reserved_typespecquals
|
|
|
|
|
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
reserved_typespecquals:
|
|
|
|
|
typespecqual_reserved
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_decl_list (NULL_TREE, $1.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| reserved_typespecquals typespecqual_reserved
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = decl_tree_cons (NULL_TREE, $2.t, $1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* A typespec (but not a type qualifier).
|
|
|
|
|
Once we have seen one of these in a declaration,
|
|
|
|
|
if a typedef name appears then it is being redeclared. */
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
typespec:
|
|
|
|
|
structsp
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| TYPESPEC %prec EMPTY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = $1; $$.new_type_flag = 0; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| complete_type_name
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = $1; $$.new_type_flag = 0; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| TYPEOF '(' expr ')'
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = finish_typeof ($3);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 0; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| TYPEOF '(' type_id ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = groktypename ($3.t);
|
|
|
|
|
$$.new_type_flag = 0; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| SIGOF '(' expr ')'
|
|
|
|
|
{ tree type = TREE_TYPE ($3);
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 0;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
if (IS_AGGR_TYPE (type))
|
|
|
|
|
{
|
|
|
|
|
sorry ("sigof type specifier");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.t = type;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
error ("`sigof' applied to non-aggregate expression");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.t = error_mark_node;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| SIGOF '(' type_id ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ tree type = groktypename ($3.t);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 0;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
if (IS_AGGR_TYPE (type))
|
|
|
|
|
{
|
|
|
|
|
sorry ("sigof type specifier");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.t = type;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
error("`sigof' applied to non-aggregate type");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.t = error_mark_node;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* A typespec that is a reserved word, or a type qualifier. */
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
typespecqual_reserved:
|
|
|
|
|
TYPESPEC
|
|
|
|
|
{ $$.t = $1; $$.new_type_flag = 0; }
|
|
|
|
|
| CV_QUALIFIER
|
|
|
|
|
{ $$.t = $1; $$.new_type_flag = 0; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| structsp
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
initdecls:
|
|
|
|
|
initdcl0
|
|
|
|
|
| initdecls ',' initdcl
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ check_multiple_declarators (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_initdecls:
|
|
|
|
|
notype_initdcl0
|
|
|
|
|
| notype_initdecls ',' initdcl
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ check_multiple_declarators (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
nomods_initdecls:
|
|
|
|
|
nomods_initdcl0
|
|
|
|
|
| nomods_initdecls ',' initdcl
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ check_multiple_declarators (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
maybeasm:
|
|
|
|
|
/* empty */
|
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
| asm_keyword '(' string ')'
|
|
|
|
|
{ if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
initdcl:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
declarator maybeasm maybe_attribute '='
|
|
|
|
|
{ $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1,
|
|
|
|
|
$3, prefix_attributes); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
init
|
|
|
|
|
/* Note how the declaration of the variable is in effect while its init is parsed! */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING); }
|
|
|
|
|
| declarator maybeasm maybe_attribute
|
|
|
|
|
{ $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0,
|
|
|
|
|
$3, prefix_attributes);
|
|
|
|
|
cp_finish_decl ($<ttype>$, NULL_TREE, $2, 1, 0); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* This rule assumes a certain configuration of the parser stack.
|
|
|
|
|
In particular, $0, the element directly before the beginning of
|
|
|
|
|
this rule on the stack, must be a maybeasm. $-1 must be a
|
|
|
|
|
declarator or notype_declarator. And $-2 must be some declmods
|
|
|
|
|
or declspecs. We can't move the maybeasm into this rule because
|
|
|
|
|
we need that reduce so we prefer fn.def1 when appropriate. */
|
|
|
|
|
initdcl0_innards:
|
|
|
|
|
maybe_attribute '='
|
|
|
|
|
{ $<itype>2 = parse_decl ($<ttype>-1, $<ttype>-2,
|
|
|
|
|
$1, 1, &$<ttype>$); }
|
|
|
|
|
/* Note how the declaration of the variable is in effect
|
|
|
|
|
while its init is parsed! */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
init
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ cp_finish_decl ($<ttype>3, $4, $<ttype>0, 1,
|
|
|
|
|
LOOKUP_ONLYCONVERTING);
|
|
|
|
|
$$ = $<itype>2; }
|
|
|
|
|
| maybe_attribute
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree d;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = parse_decl ($<ttype>-1, $<ttype>-2, $1, 0, &d);
|
|
|
|
|
cp_finish_decl (d, NULL_TREE, $<ttype>0, 1, 0); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
initdcl0:
|
|
|
|
|
declarator maybeasm initdcl0_innards
|
|
|
|
|
{ $$ = $3; }
|
|
|
|
|
|
|
|
|
|
notype_initdcl0:
|
|
|
|
|
notype_declarator maybeasm initdcl0_innards
|
|
|
|
|
{ $$ = $3; }
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
nomods_initdcl0:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
notype_declarator maybeasm
|
|
|
|
|
{ /* Set things up as initdcl0_innards expects. */
|
|
|
|
|
$<ttype>2 = $1;
|
|
|
|
|
$1 = NULL_TREE; }
|
|
|
|
|
initdcl0_innards
|
|
|
|
|
{}
|
|
|
|
|
| constructor_declarator maybeasm maybe_attribute
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree d;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
parse_decl($1, NULL_TREE, $3, 0, &d);
|
|
|
|
|
cp_finish_decl (d, NULL_TREE, $2, 1, 0); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* the * rules are dummies to accept the Apollo extended syntax
|
1999-08-26 09:30:50 +00:00
|
|
|
|
so that the header files compile. */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
maybe_attribute:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
| attributes
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
attributes:
|
|
|
|
|
attribute
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| attributes attribute
|
|
|
|
|
{ $$ = chainon ($1, $2); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
attribute:
|
|
|
|
|
ATTRIBUTE '(' '(' attribute_list ')' ')'
|
|
|
|
|
{ $$ = $4; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
attribute_list:
|
|
|
|
|
attrib
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| attribute_list ',' attrib
|
|
|
|
|
{ $$ = chainon ($1, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
attrib:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
| any_word
|
|
|
|
|
{ $$ = build_tree_list ($1, NULL_TREE); }
|
|
|
|
|
| any_word '(' IDENTIFIER ')'
|
|
|
|
|
{ $$ = build_tree_list ($1, build_tree_list (NULL_TREE, $3)); }
|
|
|
|
|
| any_word '(' IDENTIFIER ',' nonnull_exprlist ')'
|
|
|
|
|
{ $$ = build_tree_list ($1, tree_cons (NULL_TREE, $3, $5)); }
|
|
|
|
|
| any_word '(' nonnull_exprlist ')'
|
|
|
|
|
{ $$ = build_tree_list ($1, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* This still leaves out most reserved keywords,
|
|
|
|
|
shouldn't we include them? */
|
|
|
|
|
|
|
|
|
|
any_word:
|
|
|
|
|
identifier
|
|
|
|
|
| SCSPEC
|
|
|
|
|
| TYPESPEC
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| CV_QUALIFIER
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* A nonempty list of identifiers, including typenames. */
|
|
|
|
|
identifiers_or_typenames:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
identifier
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = build_tree_list (NULL_TREE, $1); }
|
|
|
|
|
| identifiers_or_typenames ',' identifier
|
|
|
|
|
{ $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
maybe_init:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */ %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
| '=' init
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* If we are processing a template, we don't want to expand this
|
|
|
|
|
initializer yet. */
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
init:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
expr_no_commas %prec '='
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '{' '}'
|
|
|
|
|
{ $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);
|
|
|
|
|
TREE_HAS_CONSTRUCTOR ($$) = 1; }
|
|
|
|
|
| '{' initlist '}'
|
|
|
|
|
{ $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2));
|
|
|
|
|
TREE_HAS_CONSTRUCTOR ($$) = 1; }
|
|
|
|
|
| '{' initlist ',' '}'
|
|
|
|
|
{ $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2));
|
|
|
|
|
TREE_HAS_CONSTRUCTOR ($$) = 1; }
|
|
|
|
|
| error
|
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* This chain is built in reverse order,
|
|
|
|
|
and put in forward order where initlist is used. */
|
|
|
|
|
initlist:
|
|
|
|
|
init
|
|
|
|
|
{ $$ = build_tree_list (NULL_TREE, $$); }
|
|
|
|
|
| initlist ',' init
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = expr_tree_cons (NULL_TREE, $3, $$); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* These are for labeled elements. */
|
|
|
|
|
| '[' expr_no_commas ']' init
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_expr_list ($2, $4); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| identifier ':' init
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_expr_list ($$, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| initlist ',' identifier ':' init
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = expr_tree_cons ($3, $5, $$); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
fn.defpen:
|
|
|
|
|
PRE_PARSED_FUNCTION_DECL
|
|
|
|
|
{ start_function (NULL_TREE, TREE_VALUE ($1),
|
1999-10-16 06:09:09 +00:00
|
|
|
|
NULL_TREE, 2);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
reinit_parse_for_function (); }
|
|
|
|
|
|
|
|
|
|
pending_inline:
|
|
|
|
|
fn.defpen maybe_return_init ctor_initializer_opt compstmt_or_error
|
|
|
|
|
{
|
|
|
|
|
int nested = (hack_decl_function_context
|
|
|
|
|
(current_function_decl) != NULL_TREE);
|
1999-10-16 06:09:09 +00:00
|
|
|
|
finish_function (lineno, (int)$3 | 2, nested);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
process_next_inline ($1);
|
|
|
|
|
}
|
|
|
|
|
| fn.defpen maybe_return_init function_try_block
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
int nested = (hack_decl_function_context
|
|
|
|
|
(current_function_decl) != NULL_TREE);
|
|
|
|
|
finish_function (lineno, (int)$3 | 2, nested);
|
|
|
|
|
process_next_inline ($1);
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| fn.defpen maybe_return_init error
|
|
|
|
|
{ process_next_inline ($1); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
pending_inlines:
|
|
|
|
|
/* empty */
|
|
|
|
|
| pending_inlines pending_inline eat_saved_input
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* A regurgitated default argument. The value of DEFARG_MARKER will be
|
|
|
|
|
the TREE_LIST node for the parameter in question. */
|
|
|
|
|
defarg_again:
|
|
|
|
|
DEFARG_MARKER expr_no_commas END_OF_SAVED_INPUT
|
|
|
|
|
{ replace_defarg ($1, $2); }
|
|
|
|
|
| DEFARG_MARKER error END_OF_SAVED_INPUT
|
|
|
|
|
{ replace_defarg ($1, error_mark_node); }
|
|
|
|
|
|
|
|
|
|
pending_defargs:
|
|
|
|
|
/* empty */ %prec EMPTY
|
|
|
|
|
| pending_defargs defarg_again
|
|
|
|
|
{ do_pending_defargs (); }
|
|
|
|
|
| pending_defargs error
|
|
|
|
|
{ do_pending_defargs (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
structsp:
|
|
|
|
|
ENUM identifier '{'
|
|
|
|
|
{ $<itype>3 = suspend_momentary ();
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$<ttype>$ = current_enum_type;
|
|
|
|
|
current_enum_type = start_enum ($2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
enumlist maybecomma_warn '}'
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ TYPE_VALUES (current_enum_type) = $5;
|
|
|
|
|
$$.t = finish_enum (current_enum_type);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 1;
|
1999-10-16 06:09:09 +00:00
|
|
|
|
current_enum_type = $<ttype>4;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
resume_momentary ((int) $<itype>3);
|
1999-10-16 06:09:09 +00:00
|
|
|
|
check_for_missing_semicolon ($$.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| ENUM identifier '{' '}'
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = finish_enum (start_enum ($2));
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 1;
|
|
|
|
|
check_for_missing_semicolon ($$.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| ENUM '{'
|
|
|
|
|
{ $<itype>2 = suspend_momentary ();
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$<ttype>$ = current_enum_type;
|
|
|
|
|
current_enum_type = start_enum (make_anon_name ()); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
enumlist maybecomma_warn '}'
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ TYPE_VALUES (current_enum_type) = $4;
|
|
|
|
|
$$.t = finish_enum (current_enum_type);
|
|
|
|
|
$$.new_type_flag = 1;
|
|
|
|
|
current_enum_type = $<ttype>3;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
resume_momentary ((int) $<itype>1);
|
1999-10-16 06:09:09 +00:00
|
|
|
|
check_for_missing_semicolon ($$.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| ENUM '{' '}'
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = finish_enum (start_enum (make_anon_name()));
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 1;
|
|
|
|
|
check_for_missing_semicolon ($$.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| ENUM identifier
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = xref_tag (enum_type_node, $2, 1);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 0; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| ENUM complex_type_name
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = xref_tag (enum_type_node, $2, 1);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 0; }
|
|
|
|
|
| TYPENAME_KEYWORD typename_sub
|
|
|
|
|
{ $$.t = $2;
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$$.new_type_flag = 0;
|
|
|
|
|
if (!processing_template_decl)
|
|
|
|
|
cp_pedwarn ("using `typename' outside of template"); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| class_head '{'
|
|
|
|
|
{ $1.t = begin_class_definition ($1.t); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
opt.component_decl_list '}' maybe_attribute
|
|
|
|
|
{
|
1996-09-18 05:35:50 +00:00
|
|
|
|
int semi;
|
|
|
|
|
|
|
|
|
|
if (yychar == YYEMPTY)
|
|
|
|
|
yychar = YYLEX;
|
|
|
|
|
semi = yychar == ';';
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$<ttype>$ = finish_class_definition ($1.t, $6, semi,
|
|
|
|
|
$1.new_type_flag);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
}
|
|
|
|
|
pending_defargs
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
begin_inline_definitions ();
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
pending_inlines
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
finish_inline_definitions ();
|
|
|
|
|
$$.t = $<ttype>7;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 1;
|
1999-10-16 06:09:09 +00:00
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| class_head %prec EMPTY
|
|
|
|
|
{
|
1999-10-16 06:09:09 +00:00
|
|
|
|
if ($1.new_type_flag)
|
|
|
|
|
pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL ($1.t)));
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 0;
|
1999-10-16 06:09:09 +00:00
|
|
|
|
if (TYPE_BINFO ($1.t) == NULL_TREE)
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-10-16 06:09:09 +00:00
|
|
|
|
cp_error ("%T is not a class type", $1.t);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.t = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
else
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$$.t = $1.t;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* struct B: public A; is not accepted by the WP grammar. */
|
|
|
|
|
if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t)
|
|
|
|
|
&& ! TYPE_BEING_DEFINED ($$.t))
|
|
|
|
|
cp_error ("base clause without member specification for `%#T'",
|
|
|
|
|
$$.t);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
maybecomma:
|
|
|
|
|
/* empty */
|
|
|
|
|
| ','
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
maybecomma_warn:
|
|
|
|
|
/* empty */
|
|
|
|
|
| ','
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ if (pedantic && !in_system_header)
|
|
|
|
|
pedwarn ("comma at end of enumerator list"); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
aggr:
|
|
|
|
|
AGGR
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| aggr SCSPEC
|
|
|
|
|
{ error ("storage class specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); }
|
|
|
|
|
| aggr TYPESPEC
|
|
|
|
|
{ error ("type specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| aggr CV_QUALIFIER
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ error ("type qualifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); }
|
|
|
|
|
| aggr AGGR
|
|
|
|
|
{ error ("no body nor ';' separates two class, struct or union declarations"); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| aggr attributes
|
|
|
|
|
{ $$ = build_decl_list ($2, $1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
named_class_head_sans_basetype:
|
|
|
|
|
aggr identifier
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
current_aggr = $1;
|
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
named_class_head_sans_basetype_defn:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
aggr identifier_defn %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ current_aggr = $$; $$ = $2; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| named_class_head_sans_basetype '{'
|
|
|
|
|
{ yyungetc ('{', 1); }
|
|
|
|
|
| named_class_head_sans_basetype ':'
|
|
|
|
|
{ yyungetc (':', 1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
named_complex_class_head_sans_basetype:
|
|
|
|
|
aggr nested_name_specifier identifier
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
current_aggr = $1;
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$$.t = handle_class_head ($1, $2, $3);
|
|
|
|
|
$$.new_type_flag = 1;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
}
|
|
|
|
|
| aggr global_scope nested_name_specifier identifier
|
|
|
|
|
{
|
|
|
|
|
current_aggr = $1;
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$$.t = handle_class_head ($1, $3, $4);
|
|
|
|
|
$$.new_type_flag = 1;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
}
|
|
|
|
|
| aggr global_scope identifier
|
|
|
|
|
{
|
|
|
|
|
current_aggr = $1;
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$$.t = handle_class_head ($1, NULL_TREE, $3);
|
|
|
|
|
$$.new_type_flag = 1;
|
|
|
|
|
}
|
|
|
|
|
| aggr apparent_template_type
|
|
|
|
|
{
|
|
|
|
|
current_aggr = $1;
|
|
|
|
|
$$.t = $2;
|
|
|
|
|
$$.new_type_flag = 0;
|
|
|
|
|
}
|
|
|
|
|
| aggr nested_name_specifier apparent_template_type
|
|
|
|
|
{
|
|
|
|
|
current_aggr = $1;
|
|
|
|
|
$$.t = $3;
|
|
|
|
|
if (CP_DECL_CONTEXT ($$.t))
|
|
|
|
|
push_scope (CP_DECL_CONTEXT ($$.t));
|
|
|
|
|
$$.new_type_flag = 1;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
named_class_head:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
named_class_head_sans_basetype %prec EMPTY
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
$$.t = xref_tag (current_aggr, $1, 1);
|
|
|
|
|
$$.new_type_flag = 0;
|
|
|
|
|
}
|
|
|
|
|
| named_class_head_sans_basetype_defn
|
|
|
|
|
{ $<ttype>$ = xref_tag (current_aggr, $1, 0); }
|
|
|
|
|
/* Class name is unqualified, so we look for base classes
|
|
|
|
|
in the current scope. */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
maybe_base_class_list %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$$.t = $<ttype>2;
|
|
|
|
|
$$.new_type_flag = 0;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
if ($3)
|
|
|
|
|
xref_basetypes (current_aggr, $1, $<ttype>2, $3);
|
|
|
|
|
}
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| named_complex_class_head_sans_basetype
|
|
|
|
|
maybe_base_class_list
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-10-16 06:09:09 +00:00
|
|
|
|
if ($1.t != error_mark_node)
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$$.t = TREE_TYPE ($1.t);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag;
|
|
|
|
|
if (current_aggr == union_type_node
|
|
|
|
|
&& TREE_CODE ($$.t) != UNION_TYPE)
|
|
|
|
|
cp_pedwarn ("`union' tag used in declaring `%#T'",
|
|
|
|
|
$$.t);
|
|
|
|
|
else if (TREE_CODE ($$.t) == UNION_TYPE
|
|
|
|
|
&& current_aggr != union_type_node)
|
|
|
|
|
cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
|
|
|
|
|
else if (TREE_CODE ($$.t) == RECORD_TYPE)
|
|
|
|
|
/* We might be specializing a template with a different
|
|
|
|
|
class-key; deal. */
|
|
|
|
|
CLASSTYPE_DECLARED_CLASS ($$.t)
|
|
|
|
|
= (current_aggr == class_type_node);
|
|
|
|
|
if ($2)
|
|
|
|
|
{
|
|
|
|
|
maybe_process_partial_specialization ($$.t);
|
|
|
|
|
xref_basetypes (current_aggr, $1.t, $$.t, $2);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
unnamed_class_head:
|
|
|
|
|
aggr '{'
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = xref_tag ($$, make_anon_name (), 0);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
yyungetc ('{', 1); }
|
|
|
|
|
;
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
/* The tree output of this nonterminal a declarationf or the type
|
|
|
|
|
named. If NEW_TYPE_FLAG is set, then the name used in this
|
|
|
|
|
class-head was explicitly qualified, e.g.: `struct X::Y'. We have
|
|
|
|
|
already called push_scope for X. */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
class_head:
|
|
|
|
|
unnamed_class_head
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
$$.t = $1;
|
|
|
|
|
$$.new_type_flag = 0;
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| named_class_head
|
|
|
|
|
;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
maybe_base_class_list:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */ %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| ':' see_typename %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ yyungetc(':', 1); $$ = NULL_TREE; }
|
|
|
|
|
| ':' see_typename base_class_list %prec EMPTY
|
|
|
|
|
{ $$ = $3; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
base_class_list:
|
|
|
|
|
base_class
|
|
|
|
|
| base_class_list ',' see_typename base_class
|
|
|
|
|
{ $$ = chainon ($$, $4); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
base_class:
|
|
|
|
|
base_class.1
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = finish_base_specifier (access_default_node, $1,
|
|
|
|
|
current_aggr
|
|
|
|
|
== signature_type_node); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| base_class_access_list see_typename base_class.1
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = finish_base_specifier ($1, $3,
|
|
|
|
|
current_aggr
|
|
|
|
|
== signature_type_node); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
base_class.1:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
typename_sub
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ if ($$ != error_mark_node) $$ = TYPE_MAIN_DECL ($1); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| nonnested_type
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| SIGOF '(' expr ')'
|
|
|
|
|
{
|
|
|
|
|
if (current_aggr == signature_type_node)
|
|
|
|
|
{
|
|
|
|
|
if (IS_AGGR_TYPE (TREE_TYPE ($3)))
|
|
|
|
|
{
|
|
|
|
|
sorry ("`sigof' as base signature specifier");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = TREE_TYPE ($3);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
error ("`sigof' applied to non-aggregate expression");
|
|
|
|
|
$$ = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
error ("`sigof' in struct or class declaration");
|
|
|
|
|
$$ = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| SIGOF '(' type_id ')'
|
|
|
|
|
{
|
|
|
|
|
if (current_aggr == signature_type_node)
|
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (IS_AGGR_TYPE (groktypename ($3.t)))
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
|
|
|
|
sorry ("`sigof' as base signature specifier");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = groktypename ($3.t);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
error ("`sigof' applied to non-aggregate expression");
|
|
|
|
|
$$ = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
error ("`sigof' in struct or class declaration");
|
|
|
|
|
$$ = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
base_class_access_list:
|
|
|
|
|
VISSPEC see_typename
|
|
|
|
|
| SCSPEC see_typename
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ if ($1 != ridpointers[(int)RID_VIRTUAL])
|
|
|
|
|
cp_error ("`%D' access", $1);
|
|
|
|
|
$$ = access_default_virtual_node; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| base_class_access_list VISSPEC see_typename
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
if ($1 != access_default_virtual_node)
|
|
|
|
|
error ("multiple access specifiers");
|
|
|
|
|
else if ($2 == access_public_node)
|
|
|
|
|
$$ = access_public_virtual_node;
|
|
|
|
|
else if ($2 == access_protected_node)
|
|
|
|
|
$$ = access_protected_virtual_node;
|
|
|
|
|
else /* $2 == access_private_node */
|
|
|
|
|
$$ = access_private_virtual_node;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| base_class_access_list SCSPEC see_typename
|
|
|
|
|
{ if ($2 != ridpointers[(int)RID_VIRTUAL])
|
1999-08-26 09:30:50 +00:00
|
|
|
|
cp_error ("`%D' access", $2);
|
|
|
|
|
else if ($$ == access_public_node)
|
|
|
|
|
$$ = access_public_virtual_node;
|
|
|
|
|
else if ($$ == access_protected_node)
|
|
|
|
|
$$ = access_protected_virtual_node;
|
|
|
|
|
else if ($$ == access_private_node)
|
|
|
|
|
$$ = access_private_virtual_node;
|
|
|
|
|
else
|
|
|
|
|
error ("multiple `virtual' specifiers");
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
opt.component_decl_list:
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| component_decl_list
|
|
|
|
|
| opt.component_decl_list access_specifier component_decl_list
|
|
|
|
|
| opt.component_decl_list access_specifier
|
|
|
|
|
;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
access_specifier:
|
|
|
|
|
VISSPEC ':'
|
|
|
|
|
{
|
1996-09-18 05:35:50 +00:00
|
|
|
|
if (current_aggr == signature_type_node)
|
|
|
|
|
{
|
|
|
|
|
error ("access specifier not allowed in signature");
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$1 = access_public_node;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
1999-10-16 06:09:09 +00:00
|
|
|
|
|
|
|
|
|
current_access_specifier = $1;
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Note: we no longer warn about the semicolon after a component_decl_list.
|
|
|
|
|
ARM $9.2 says that the semicolon is optional, and therefore allowed. */
|
|
|
|
|
component_decl_list:
|
|
|
|
|
component_decl
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
finish_member_declaration ($1);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| component_decl_list component_decl
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
finish_member_declaration ($2);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
component_decl:
|
|
|
|
|
component_decl_1 ';'
|
|
|
|
|
| component_decl_1 '}'
|
|
|
|
|
{ error ("missing ';' before right brace");
|
|
|
|
|
yyungetc ('}', 0); }
|
|
|
|
|
/* C++: handle constructors, destructors and inline functions */
|
|
|
|
|
/* note that INLINE is like a TYPESPEC */
|
|
|
|
|
| fn.def2 ':' /* base_init compstmt */
|
|
|
|
|
{ $$ = finish_method ($$); }
|
|
|
|
|
| fn.def2 TRY /* base_init compstmt */
|
|
|
|
|
{ $$ = finish_method ($$); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| fn.def2 RETURN_KEYWORD /* base_init compstmt */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = finish_method ($$); }
|
|
|
|
|
| fn.def2 '{' /* nodecls compstmt */
|
|
|
|
|
{ $$ = finish_method ($$); }
|
|
|
|
|
| ';'
|
|
|
|
|
{ $$ = NULL_TREE; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| extension component_decl
|
|
|
|
|
{ $$ = $2;
|
|
|
|
|
pedantic = $<itype>1; }
|
|
|
|
|
| template_header component_decl
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
if ($2)
|
|
|
|
|
$$ = finish_member_template_decl ($2);
|
|
|
|
|
else
|
|
|
|
|
/* The component was already processed. */
|
|
|
|
|
$$ = NULL_TREE;
|
|
|
|
|
|
|
|
|
|
finish_template_decl ($1);
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| template_header typed_declspecs ';'
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
$$ = finish_member_class_template ($2.t);
|
|
|
|
|
finish_template_decl ($1);
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
component_decl_1:
|
|
|
|
|
/* Do not add a "typed_declspecs declarator" rule here for
|
|
|
|
|
speed; we need to call grok_x_components for enums, so the
|
|
|
|
|
speedup would be insignificant. */
|
|
|
|
|
typed_declspecs components
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
/* Most of the productions for component_decl only
|
|
|
|
|
allow the creation of one new member, so we call
|
|
|
|
|
finish_member_declaration in component_decl_list.
|
|
|
|
|
For this rule and the next, however, there can be
|
|
|
|
|
more than one member, e.g.:
|
|
|
|
|
|
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
|
|
and we need the first member to be fully
|
|
|
|
|
registered before the second is processed.
|
|
|
|
|
Therefore, the rules for components take care of
|
|
|
|
|
this processing. To avoid registering the
|
|
|
|
|
components more than once, we send NULL_TREE up
|
|
|
|
|
here; that lets finish_member_declaration know
|
|
|
|
|
that there is nothing to do. */
|
|
|
|
|
if (!$2)
|
|
|
|
|
grok_x_components ($1.t);
|
|
|
|
|
$$ = NULL_TREE;
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| declmods notype_components
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
if (!$2)
|
|
|
|
|
grok_x_components ($1);
|
|
|
|
|
$$ = NULL_TREE;
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| notype_declarator maybeasm maybe_attribute maybe_init
|
|
|
|
|
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
|
|
|
|
|
build_tree_list ($3, NULL_TREE)); }
|
|
|
|
|
| constructor_declarator maybeasm maybe_attribute maybe_init
|
|
|
|
|
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
|
|
|
|
|
build_tree_list ($3, NULL_TREE)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| ':' expr_no_commas
|
|
|
|
|
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
|
|
|
|
|
| error
|
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
|
|
|
|
|
/* These rules introduce a reduce/reduce conflict; in
|
|
|
|
|
typedef int foo, bar;
|
|
|
|
|
class A {
|
|
|
|
|
foo (bar);
|
|
|
|
|
};
|
|
|
|
|
should "A::foo" be declared as a function or "A::bar" as a data
|
|
|
|
|
member? In other words, is "bar" an after_type_declarator or a
|
|
|
|
|
parmlist? */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| declmods component_constructor_declarator maybeasm maybe_attribute maybe_init
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree specs, attrs;
|
|
|
|
|
split_specs_attrs ($1, &specs, &attrs);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = grokfield ($2, specs, $5, $3,
|
|
|
|
|
build_tree_list ($4, attrs)); }
|
|
|
|
|
| component_constructor_declarator maybeasm maybe_attribute maybe_init
|
|
|
|
|
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
|
|
|
|
|
build_tree_list ($3, NULL_TREE)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| using_decl
|
|
|
|
|
{ $$ = do_class_using_decl ($1); }
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* The case of exactly one component is handled directly by component_decl. */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* ??? Huh? ^^^ */
|
|
|
|
|
components:
|
|
|
|
|
/* empty: possibly anonymous */
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = 0; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| component_declarator0
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
|
|
|
|
|
$1 = finish_member_template_decl ($1);
|
|
|
|
|
finish_member_declaration ($1);
|
|
|
|
|
$$ = 1;
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| components ',' component_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
check_multiple_declarators ();
|
|
|
|
|
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
|
|
|
|
|
$3 = finish_member_template_decl ($3);
|
|
|
|
|
finish_member_declaration ($3);
|
|
|
|
|
$$ = 2;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_components:
|
|
|
|
|
/* empty: possibly anonymous */
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = 0; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| notype_component_declarator0
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
|
|
|
|
|
$1 = finish_member_template_decl ($1);
|
|
|
|
|
finish_member_declaration ($1);
|
|
|
|
|
$$ = 1;
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| notype_components ',' notype_component_declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{
|
|
|
|
|
check_multiple_declarators ();
|
|
|
|
|
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
|
|
|
|
|
$3 = finish_member_template_decl ($3);
|
|
|
|
|
finish_member_declaration ($3);
|
|
|
|
|
$$ = 2;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
component_declarator0:
|
|
|
|
|
after_type_component_declarator0
|
|
|
|
|
| notype_component_declarator0
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
component_declarator:
|
|
|
|
|
after_type_component_declarator
|
|
|
|
|
| notype_component_declarator
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
after_type_component_declarator0:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
after_type_declarator maybeasm maybe_attribute maybe_init
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ split_specs_attrs ($<ttype>0, ¤t_declspecs,
|
|
|
|
|
&prefix_attributes);
|
|
|
|
|
$<ttype>0 = current_declspecs;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = grokfield ($$, current_declspecs, $4, $2,
|
|
|
|
|
build_tree_list ($3, prefix_attributes)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| TYPENAME ':' expr_no_commas maybe_attribute
|
|
|
|
|
{ split_specs_attrs ($<ttype>0, ¤t_declspecs,
|
|
|
|
|
&prefix_attributes);
|
|
|
|
|
$<ttype>0 = current_declspecs;
|
|
|
|
|
$$ = grokbitfield ($$, current_declspecs, $3);
|
|
|
|
|
cplus_decl_attributes ($$, $4, prefix_attributes); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_component_declarator0:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
notype_declarator maybeasm maybe_attribute maybe_init
|
|
|
|
|
{ split_specs_attrs ($<ttype>0, ¤t_declspecs,
|
|
|
|
|
&prefix_attributes);
|
|
|
|
|
$<ttype>0 = current_declspecs;
|
|
|
|
|
$$ = grokfield ($$, current_declspecs, $4, $2,
|
|
|
|
|
build_tree_list ($3, prefix_attributes)); }
|
|
|
|
|
| constructor_declarator maybeasm maybe_attribute maybe_init
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ split_specs_attrs ($<ttype>0, ¤t_declspecs,
|
|
|
|
|
&prefix_attributes);
|
|
|
|
|
$<ttype>0 = current_declspecs;
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = grokfield ($$, current_declspecs, $4, $2,
|
|
|
|
|
build_tree_list ($3, prefix_attributes)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| IDENTIFIER ':' expr_no_commas maybe_attribute
|
|
|
|
|
{ split_specs_attrs ($<ttype>0, ¤t_declspecs,
|
|
|
|
|
&prefix_attributes);
|
|
|
|
|
$<ttype>0 = current_declspecs;
|
|
|
|
|
$$ = grokbitfield ($$, current_declspecs, $3);
|
|
|
|
|
cplus_decl_attributes ($$, $4, prefix_attributes); }
|
|
|
|
|
| ':' expr_no_commas maybe_attribute
|
|
|
|
|
{ split_specs_attrs ($<ttype>0, ¤t_declspecs,
|
|
|
|
|
&prefix_attributes);
|
|
|
|
|
$<ttype>0 = current_declspecs;
|
|
|
|
|
$$ = grokbitfield (NULL_TREE, current_declspecs, $2);
|
|
|
|
|
cplus_decl_attributes ($$, $3, prefix_attributes); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
after_type_component_declarator:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
after_type_declarator maybeasm maybe_attribute maybe_init
|
|
|
|
|
{ $$ = grokfield ($$, current_declspecs, $4, $2,
|
|
|
|
|
build_tree_list ($3, prefix_attributes)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| TYPENAME ':' expr_no_commas maybe_attribute
|
|
|
|
|
{ $$ = grokbitfield ($$, current_declspecs, $3);
|
|
|
|
|
cplus_decl_attributes ($$, $4, prefix_attributes); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_component_declarator:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
notype_declarator maybeasm maybe_attribute maybe_init
|
|
|
|
|
{ $$ = grokfield ($$, current_declspecs, $4, $2,
|
|
|
|
|
build_tree_list ($3, prefix_attributes)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| IDENTIFIER ':' expr_no_commas maybe_attribute
|
|
|
|
|
{ $$ = grokbitfield ($$, current_declspecs, $3);
|
|
|
|
|
cplus_decl_attributes ($$, $4, prefix_attributes); }
|
|
|
|
|
| ':' expr_no_commas maybe_attribute
|
|
|
|
|
{ $$ = grokbitfield (NULL_TREE, current_declspecs, $2);
|
|
|
|
|
cplus_decl_attributes ($$, $3, prefix_attributes); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* We chain the enumerators in reverse order.
|
|
|
|
|
Because of the way enums are built, the order is
|
|
|
|
|
insignificant. Take advantage of this fact. */
|
|
|
|
|
|
|
|
|
|
enumlist:
|
|
|
|
|
enumerator
|
|
|
|
|
| enumlist ',' enumerator
|
|
|
|
|
{ TREE_CHAIN ($3) = $$; $$ = $3; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
enumerator:
|
|
|
|
|
identifier
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = build_enumerator ($$, NULL_TREE, current_enum_type); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| identifier '=' expr_no_commas
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$ = build_enumerator ($$, $3, current_enum_type); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* ANSI new-type-id (5.3.4) */
|
|
|
|
|
new_type_id:
|
|
|
|
|
type_specifier_seq new_declarator
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = build_decl_list ($1.t, $2);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
|
|
|
|
| type_specifier_seq %prec EMPTY
|
|
|
|
|
{ $$.t = build_decl_list ($1.t, NULL_TREE);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* GNU extension to allow arrays of arbitrary types with
|
1999-08-26 09:30:50 +00:00
|
|
|
|
non-constant dimension. For the use of begin_new_placement
|
|
|
|
|
here, see the comments in unary_expr above. */
|
|
|
|
|
| '(' .begin_new_placement type_id .finish_new_placement
|
|
|
|
|
'[' expr ']'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
|
|
|
|
if (pedantic)
|
|
|
|
|
pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.t = build_parse_node (ARRAY_REF, TREE_VALUE ($3.t), $6);
|
|
|
|
|
$$.t = build_decl_list (TREE_PURPOSE ($3.t), $$.t);
|
|
|
|
|
$$.new_type_flag = $3.new_type_flag;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
cv_qualifiers:
|
|
|
|
|
/* empty */ %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| cv_qualifiers CV_QUALIFIER
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = decl_tree_cons (NULL_TREE, $2, $$); }
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
nonempty_cv_qualifiers:
|
|
|
|
|
CV_QUALIFIER
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = 0; }
|
|
|
|
|
| nonempty_cv_qualifiers CV_QUALIFIER
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* These rules must follow the rules for function declarations
|
|
|
|
|
and component declarations. That way, longer rules are preferred. */
|
|
|
|
|
|
|
|
|
|
suspend_mom:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */
|
|
|
|
|
{ $<itype>$ = suspend_momentary (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
|
|
|
|
|
/* An expression which will not live on the momentary obstack. */
|
|
|
|
|
nonmomentary_expr:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
suspend_mom expr
|
|
|
|
|
{ resume_momentary ((int) $<itype>1); $$ = $2; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* An expression which will not live on the momentary obstack. */
|
|
|
|
|
maybe_parmlist:
|
|
|
|
|
suspend_mom '(' nonnull_exprlist ')'
|
|
|
|
|
{ resume_momentary ((int) $<itype>1); $$ = $3; }
|
|
|
|
|
| suspend_mom '(' parmlist ')'
|
|
|
|
|
{ resume_momentary ((int) $<itype>1); $$ = $3; }
|
|
|
|
|
| suspend_mom LEFT_RIGHT
|
|
|
|
|
{ resume_momentary ((int) $<itype>1); $$ = empty_parms (); }
|
|
|
|
|
| suspend_mom '(' error ')'
|
|
|
|
|
{ resume_momentary ((int) $<itype>1); $$ = NULL_TREE; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* A declarator that is allowed only after an explicit typespec. */
|
1999-10-16 06:09:09 +00:00
|
|
|
|
|
|
|
|
|
after_type_declarator_intern:
|
|
|
|
|
after_type_declarator
|
|
|
|
|
| attributes after_type_declarator
|
|
|
|
|
{
|
|
|
|
|
/* Provide support for '(' attributes '*' declarator ')'
|
|
|
|
|
etc */
|
|
|
|
|
$$ = decl_tree_cons ($1, $2, NULL_TREE);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* may all be followed by prec '.' */
|
|
|
|
|
after_type_declarator:
|
1999-10-16 06:09:09 +00:00
|
|
|
|
'*' nonempty_cv_qualifiers after_type_declarator_intern %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator ($2.t, $3); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '&' nonempty_cv_qualifiers after_type_declarator_intern %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator ($2.t, $3); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '*' after_type_declarator_intern %prec UNARY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '&' after_type_declarator_intern %prec UNARY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator (NULL_TREE, $2); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| ptr_to_mem cv_qualifiers after_type_declarator_intern
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree arg = make_pointer_declarator ($2, $3);
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, arg);
|
|
|
|
|
}
|
|
|
|
|
| direct_after_type_declarator
|
|
|
|
|
;
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
direct_after_type_declarator:
|
|
|
|
|
direct_after_type_declarator maybe_parmlist cv_qualifiers exception_specification_opt %prec '.'
|
|
|
|
|
{ $$ = make_call_declarator ($$, $2, $3, $4); }
|
|
|
|
|
| direct_after_type_declarator '[' nonmomentary_expr ']'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
|
|
|
|
|
| direct_after_type_declarator '[' ']'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
|
|
|
|
|
| '(' after_type_declarator_intern ')'
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
| nested_name_specifier type_name %prec EMPTY
|
|
|
|
|
{ push_nested_class ($1, 3);
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $$, $2);
|
|
|
|
|
TREE_COMPLEXITY ($$) = current_class_depth; }
|
|
|
|
|
| type_name %prec EMPTY
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
nonnested_type:
|
|
|
|
|
type_name %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (TREE_CODE ($1) == IDENTIFIER_NODE)
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = lookup_name ($1, 1);
|
1999-10-16 06:09:09 +00:00
|
|
|
|
maybe_note_name_used_in_class ($1, $$);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
else
|
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
| global_scope type_name
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
|
|
|
|
$$ = IDENTIFIER_GLOBAL_VALUE ($2);
|
|
|
|
|
else
|
|
|
|
|
$$ = $2;
|
|
|
|
|
got_scope = NULL_TREE;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
complete_type_name:
|
|
|
|
|
nonnested_type
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| nested_type
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| global_scope nested_type
|
|
|
|
|
{ $$ = $2; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
nested_type:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
nested_name_specifier type_name %prec EMPTY
|
|
|
|
|
{ $$ = get_type_decl ($2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* A declarator allowed whether or not there has been
|
|
|
|
|
an explicit typespec. These cannot redeclare a typedef-name. */
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
notype_declarator_intern:
|
|
|
|
|
notype_declarator
|
|
|
|
|
| attributes notype_declarator
|
|
|
|
|
{
|
|
|
|
|
/* Provide support for '(' attributes '*' declarator ')'
|
|
|
|
|
etc */
|
|
|
|
|
$$ = decl_tree_cons ($1, $2, NULL_TREE);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
notype_declarator:
|
1999-10-16 06:09:09 +00:00
|
|
|
|
'*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator ($2.t, $3); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '&' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator ($2.t, $3); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '*' notype_declarator_intern %prec UNARY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '&' notype_declarator_intern %prec UNARY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator (NULL_TREE, $2); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| ptr_to_mem cv_qualifiers notype_declarator_intern
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree arg = make_pointer_declarator ($2, $3);
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, arg);
|
|
|
|
|
}
|
|
|
|
|
| direct_notype_declarator
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
complex_notype_declarator:
|
1999-10-16 06:09:09 +00:00
|
|
|
|
'*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator ($2.t, $3); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '&' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator ($2.t, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '*' complex_notype_declarator %prec UNARY
|
|
|
|
|
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
|
|
|
|
|
| '&' complex_notype_declarator %prec UNARY
|
|
|
|
|
{ $$ = make_reference_declarator (NULL_TREE, $2); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| ptr_to_mem cv_qualifiers notype_declarator_intern
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree arg = make_pointer_declarator ($2, $3);
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, arg);
|
|
|
|
|
}
|
|
|
|
|
| complex_direct_notype_declarator
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
complex_direct_notype_declarator:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
direct_notype_declarator maybe_parmlist cv_qualifiers exception_specification_opt %prec '.'
|
|
|
|
|
{ $$ = make_call_declarator ($$, $2, $3, $4); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '(' complex_notype_declarator ')'
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
| direct_notype_declarator '[' nonmomentary_expr ']'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
|
|
|
|
|
| direct_notype_declarator '[' ']'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
|
|
|
|
|
| notype_qualified_id
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ enter_scope_of ($1); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| nested_name_specifier notype_template_declarator
|
|
|
|
|
{ got_scope = NULL_TREE;
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, $2);
|
1999-10-16 06:09:09 +00:00
|
|
|
|
enter_scope_of ($$);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
qualified_id:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
nested_name_specifier unqualified_id
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ got_scope = NULL_TREE;
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $$, $2); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| nested_name_specifier object_template_id
|
|
|
|
|
{ got_scope = NULL_TREE;
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, $2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
notype_qualified_id:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
nested_name_specifier notype_unqualified_id
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ got_scope = NULL_TREE;
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $$, $2); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| nested_name_specifier object_template_id
|
|
|
|
|
{ got_scope = NULL_TREE;
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, $2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
overqualified_id:
|
|
|
|
|
notype_qualified_id
|
|
|
|
|
| global_scope notype_qualified_id
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
functional_cast:
|
|
|
|
|
typespec '(' nonnull_exprlist ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_functional_cast ($1.t, $3); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| typespec '(' expr_or_declarator_intern ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = reparse_decl_as_expr ($1.t, $3); }
|
|
|
|
|
| typespec fcast_or_absdcl %prec EMPTY
|
|
|
|
|
{ $$ = reparse_absdcl_as_expr ($1.t, $2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
type_name:
|
|
|
|
|
TYPENAME
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| SELFNAME
|
|
|
|
|
| template_type %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
nested_name_specifier:
|
|
|
|
|
nested_name_specifier_1
|
|
|
|
|
| nested_name_specifier nested_name_specifier_1
|
|
|
|
|
{ $$ = $2; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| nested_name_specifier TEMPLATE explicit_template_type SCOPE
|
|
|
|
|
{ got_scope = $$ = make_typename_type ($1, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Why the @#$%^& do type_name and notype_identifier need to be expanded
|
|
|
|
|
inline here?!? (jason) */
|
|
|
|
|
nested_name_specifier_1:
|
|
|
|
|
TYPENAME SCOPE
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($1) == IDENTIFIER_NODE)
|
|
|
|
|
{
|
|
|
|
|
$$ = lastiddecl;
|
1999-10-16 06:09:09 +00:00
|
|
|
|
maybe_note_name_used_in_class ($1, $$);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
}
|
1999-10-16 06:09:09 +00:00
|
|
|
|
got_scope = $$ =
|
|
|
|
|
complete_type (TYPE_MAIN_VARIANT (TREE_TYPE ($$)));
|
1999-08-26 09:30:50 +00:00
|
|
|
|
}
|
|
|
|
|
| SELFNAME SCOPE
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($1) == IDENTIFIER_NODE)
|
|
|
|
|
$$ = lastiddecl;
|
|
|
|
|
got_scope = $$ = TREE_TYPE ($$);
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| NSNAME SCOPE
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($$) == IDENTIFIER_NODE)
|
|
|
|
|
$$ = lastiddecl;
|
|
|
|
|
got_scope = $$;
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| template_type SCOPE
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ got_scope = $$ = complete_type (TREE_TYPE ($1)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* These break 'const i;'
|
|
|
|
|
| IDENTIFIER SCOPE
|
|
|
|
|
{
|
|
|
|
|
failed_scope:
|
|
|
|
|
cp_error ("`%D' is not an aggregate typedef",
|
|
|
|
|
lastiddecl ? lastiddecl : $$);
|
|
|
|
|
$$ = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
| PTYPENAME SCOPE
|
|
|
|
|
{ goto failed_scope; } */
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
typename_sub:
|
|
|
|
|
typename_sub0
|
|
|
|
|
| global_scope typename_sub0
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
typename_sub0:
|
|
|
|
|
typename_sub1 identifier %prec EMPTY
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't')
|
|
|
|
|
$$ = make_typename_type ($1, $2);
|
|
|
|
|
else if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
|
|
|
|
cp_error ("`%T' is not a class or namespace", $2);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$$ = $2;
|
|
|
|
|
if (TREE_CODE ($$) == TYPE_DECL)
|
|
|
|
|
$$ = TREE_TYPE ($$);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| typename_sub1 template_type %prec EMPTY
|
|
|
|
|
{ $$ = TREE_TYPE ($2); }
|
|
|
|
|
| typename_sub1 explicit_template_type %prec EMPTY
|
|
|
|
|
{ $$ = make_typename_type ($1, $2); }
|
|
|
|
|
| typename_sub1 TEMPLATE explicit_template_type %prec EMPTY
|
|
|
|
|
{ $$ = make_typename_type ($1, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
typename_sub1:
|
|
|
|
|
typename_sub2
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($1) == IDENTIFIER_NODE)
|
|
|
|
|
cp_error ("`%T' is not a class or namespace", $1);
|
|
|
|
|
}
|
|
|
|
|
| typename_sub1 typename_sub2
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE_CLASS (TREE_CODE ($1)) == 't')
|
|
|
|
|
$$ = make_typename_type ($1, $2);
|
|
|
|
|
else if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
|
|
|
|
cp_error ("`%T' is not a class or namespace", $2);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$$ = $2;
|
|
|
|
|
if (TREE_CODE ($$) == TYPE_DECL)
|
|
|
|
|
$$ = TREE_TYPE ($$);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| typename_sub1 explicit_template_type SCOPE
|
|
|
|
|
{ got_scope = $$ = make_typename_type ($1, $2); }
|
|
|
|
|
| typename_sub1 TEMPLATE explicit_template_type SCOPE
|
|
|
|
|
{ got_scope = $$ = make_typename_type ($1, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
typename_sub2:
|
|
|
|
|
TYPENAME SCOPE
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($1) != IDENTIFIER_NODE)
|
|
|
|
|
$1 = lastiddecl;
|
|
|
|
|
|
|
|
|
|
/* Retrieve the type for the identifier, which might involve
|
|
|
|
|
some computation. */
|
|
|
|
|
got_scope = $$ = complete_type (IDENTIFIER_TYPE_VALUE ($1));
|
|
|
|
|
|
|
|
|
|
if ($$ == error_mark_node)
|
|
|
|
|
cp_error ("`%T' is not a class or namespace", $1);
|
|
|
|
|
}
|
|
|
|
|
| SELFNAME SCOPE
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($1) != IDENTIFIER_NODE)
|
|
|
|
|
$$ = lastiddecl;
|
|
|
|
|
got_scope = $$ = complete_type (TREE_TYPE ($$));
|
|
|
|
|
}
|
|
|
|
|
| template_type SCOPE
|
|
|
|
|
{ got_scope = $$ = complete_type (TREE_TYPE ($$)); }
|
|
|
|
|
| PTYPENAME SCOPE
|
|
|
|
|
| IDENTIFIER SCOPE
|
|
|
|
|
| NSNAME SCOPE
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($$) == IDENTIFIER_NODE)
|
|
|
|
|
$$ = lastiddecl;
|
|
|
|
|
got_scope = $$;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
explicit_template_type:
|
|
|
|
|
identifier '<' template_arg_list_opt template_close_bracket
|
|
|
|
|
{ $$ = build_min_nt (TEMPLATE_ID_EXPR, $1, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
complex_type_name:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
global_scope type_name
|
|
|
|
|
{
|
|
|
|
|
if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
|
|
|
|
$$ = IDENTIFIER_GLOBAL_VALUE ($2);
|
|
|
|
|
else
|
|
|
|
|
$$ = $2;
|
|
|
|
|
got_scope = NULL_TREE;
|
|
|
|
|
}
|
|
|
|
|
| nested_type
|
|
|
|
|
| global_scope nested_type
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
ptr_to_mem:
|
|
|
|
|
nested_name_specifier '*'
|
|
|
|
|
{ got_scope = NULL_TREE; }
|
|
|
|
|
| global_scope nested_name_specifier '*'
|
|
|
|
|
{ $$ = $2; got_scope = NULL_TREE; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* All uses of explicit global scope must go through this nonterminal so
|
1999-08-26 09:30:50 +00:00
|
|
|
|
that got_scope will be set before yylex is called to get the next token. */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
global_scope:
|
|
|
|
|
SCOPE
|
|
|
|
|
{ got_scope = void_type_node; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* ANSI new-declarator (5.3.4) */
|
|
|
|
|
new_declarator:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
'*' cv_qualifiers new_declarator
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator ($2, $3); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| '*' cv_qualifiers %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| '&' cv_qualifiers new_declarator %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator ($2, $3); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| '&' cv_qualifiers %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator ($2, NULL_TREE); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| ptr_to_mem cv_qualifiers %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree arg = make_pointer_declarator ($2, NULL_TREE);
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, arg);
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| ptr_to_mem cv_qualifiers new_declarator
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree arg = make_pointer_declarator ($2, $3);
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, arg);
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| direct_new_declarator %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* ANSI direct-new-declarator (5.3.4) */
|
|
|
|
|
direct_new_declarator:
|
|
|
|
|
'[' expr ']'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, NULL_TREE, $2); }
|
|
|
|
|
| direct_new_declarator '[' nonmomentary_expr ']'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
1999-10-16 06:09:09 +00:00
|
|
|
|
absdcl_intern:
|
|
|
|
|
absdcl
|
|
|
|
|
| attributes absdcl
|
|
|
|
|
{
|
|
|
|
|
/* Provide support for '(' attributes '*' declarator ')'
|
|
|
|
|
etc */
|
|
|
|
|
$$ = decl_tree_cons ($1, $2, NULL_TREE);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* ANSI abstract-declarator (8.1) */
|
|
|
|
|
absdcl:
|
1999-10-16 06:09:09 +00:00
|
|
|
|
'*' nonempty_cv_qualifiers absdcl_intern
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator ($2.t, $3); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '*' absdcl_intern
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| '*' nonempty_cv_qualifiers %prec EMPTY
|
|
|
|
|
{ $$ = make_pointer_declarator ($2.t, NULL_TREE); }
|
|
|
|
|
| '*' %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator (NULL_TREE, NULL_TREE); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '&' nonempty_cv_qualifiers absdcl_intern
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator ($2.t, $3); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| '&' absdcl_intern
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator (NULL_TREE, $2); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| '&' nonempty_cv_qualifiers %prec EMPTY
|
|
|
|
|
{ $$ = make_reference_declarator ($2.t, NULL_TREE); }
|
|
|
|
|
| '&' %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator (NULL_TREE, NULL_TREE); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| ptr_to_mem cv_qualifiers %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree arg = make_pointer_declarator ($2, NULL_TREE);
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, arg);
|
|
|
|
|
}
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| ptr_to_mem cv_qualifiers absdcl_intern
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree arg = make_pointer_declarator ($2, $3);
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, arg);
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| direct_abstract_declarator %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* ANSI direct-abstract-declarator (8.1) */
|
|
|
|
|
direct_abstract_declarator:
|
1999-10-16 06:09:09 +00:00
|
|
|
|
'(' absdcl_intern ')'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
/* `(typedef)1' is `int'. */
|
|
|
|
|
| PAREN_STAR_PAREN
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| direct_abstract_declarator '(' parmlist ')' cv_qualifiers exception_specification_opt %prec '.'
|
|
|
|
|
{ $$ = make_call_declarator ($$, $3, $5, $6); }
|
|
|
|
|
| direct_abstract_declarator LEFT_RIGHT cv_qualifiers exception_specification_opt %prec '.'
|
|
|
|
|
{ $$ = make_call_declarator ($$, empty_parms (), $3, $4); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| direct_abstract_declarator '[' nonmomentary_expr ']' %prec '.'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
|
|
|
|
|
| direct_abstract_declarator '[' ']' %prec '.'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| '(' complex_parmlist ')' cv_qualifiers exception_specification_opt %prec '.'
|
|
|
|
|
{ $$ = make_call_declarator (NULL_TREE, $2, $4, $5); }
|
|
|
|
|
| regcast_or_absdcl cv_qualifiers exception_specification_opt %prec '.'
|
|
|
|
|
{ set_quals_and_spec ($$, $2, $3); }
|
|
|
|
|
| fcast_or_absdcl cv_qualifiers exception_specification_opt %prec '.'
|
|
|
|
|
{ set_quals_and_spec ($$, $2, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '[' nonmomentary_expr ']' %prec '.'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, NULL_TREE, $2); }
|
|
|
|
|
| '[' ']' %prec '.'
|
|
|
|
|
{ $$ = build_parse_node (ARRAY_REF, NULL_TREE, NULL_TREE); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* For C++, decls and stmts can be intermixed, so we don't need to
|
|
|
|
|
have a special rule that won't start parsing the stmt section
|
|
|
|
|
until we have a stmt that parses without errors. */
|
|
|
|
|
|
|
|
|
|
stmts:
|
|
|
|
|
stmt
|
|
|
|
|
| errstmt
|
|
|
|
|
| stmts stmt
|
|
|
|
|
| stmts errstmt
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
errstmt:
|
|
|
|
|
error ';'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Read zero or more forward-declarations for labels
|
|
|
|
|
that nested functions can jump to. */
|
|
|
|
|
maybe_label_decls:
|
|
|
|
|
/* empty */
|
|
|
|
|
| label_decls
|
|
|
|
|
{ if (pedantic)
|
|
|
|
|
pedwarn ("ANSI C++ forbids label declarations"); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
label_decls:
|
|
|
|
|
label_decl
|
|
|
|
|
| label_decls label_decl
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
label_decl:
|
|
|
|
|
LABEL identifiers_or_typenames ';'
|
|
|
|
|
{ tree link;
|
|
|
|
|
for (link = $2; link; link = TREE_CHAIN (link))
|
|
|
|
|
{
|
|
|
|
|
tree label = shadow_label (TREE_VALUE (link));
|
|
|
|
|
C_DECLARED_LABEL_FLAG (label) = 1;
|
|
|
|
|
declare_nonlocal_label (label);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* This is the body of a function definition.
|
|
|
|
|
It causes syntax errors to ignore to the next openbrace. */
|
|
|
|
|
compstmt_or_error:
|
|
|
|
|
compstmt
|
|
|
|
|
{}
|
|
|
|
|
| error compstmt
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
compstmt:
|
|
|
|
|
'{'
|
|
|
|
|
{ $<ttype>$ = begin_compound_stmt (0); }
|
|
|
|
|
compstmtend
|
|
|
|
|
{ $$ = finish_compound_stmt (0, $<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
simple_if:
|
|
|
|
|
IF
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
$<ttype>$ = begin_if_stmt ();
|
|
|
|
|
cond_stmt_keyword = "if";
|
|
|
|
|
}
|
|
|
|
|
paren_cond_or_null
|
|
|
|
|
{ finish_if_stmt_cond ($3, $<ttype>2); }
|
|
|
|
|
implicitly_scoped_stmt
|
|
|
|
|
{ $<ttype>$ = finish_then_clause ($<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
implicitly_scoped_stmt:
|
|
|
|
|
compstmt
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| { $<ttype>$ = begin_compound_stmt (0); }
|
|
|
|
|
simple_stmt
|
|
|
|
|
{ $$ = finish_compound_stmt (0, $<ttype>1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
stmt:
|
|
|
|
|
compstmt
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| simple_stmt
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
simple_stmt:
|
|
|
|
|
decl
|
|
|
|
|
{ finish_stmt (); }
|
|
|
|
|
| expr ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_expr_stmt ($1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| simple_if ELSE
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ begin_else_clause (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
implicitly_scoped_stmt
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
finish_else_clause ($<ttype>1);
|
|
|
|
|
finish_if_stmt ();
|
|
|
|
|
}
|
|
|
|
|
| simple_if %prec IF
|
|
|
|
|
{ finish_if_stmt (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| WHILE
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
$<ttype>$ = begin_while_stmt ();
|
|
|
|
|
cond_stmt_keyword = "while";
|
|
|
|
|
}
|
|
|
|
|
paren_cond_or_null
|
|
|
|
|
{ finish_while_stmt_cond ($3, $<ttype>2); }
|
|
|
|
|
already_scoped_stmt
|
|
|
|
|
{ finish_while_stmt ($<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| DO
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $<ttype>$ = begin_do_stmt (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
implicitly_scoped_stmt WHILE
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
finish_do_body ($<ttype>2);
|
|
|
|
|
cond_stmt_keyword = "do";
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
paren_expr_or_null ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_do_stmt ($6, $<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| FOR
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $<ttype>$ = begin_for_stmt (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
'(' for.init.statement
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_for_init_stmt ($<ttype>2); }
|
|
|
|
|
xcond ';'
|
|
|
|
|
{ finish_for_cond ($6, $<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
xexpr ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_for_expr ($9, $<ttype>2); }
|
|
|
|
|
already_scoped_stmt
|
|
|
|
|
{ finish_for_stmt ($9, $<ttype>2); }
|
|
|
|
|
| SWITCH
|
|
|
|
|
{ begin_switch_stmt (); }
|
|
|
|
|
'(' condition ')'
|
|
|
|
|
{ $<ttype>$ = finish_switch_cond ($4); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
implicitly_scoped_stmt
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_switch_stmt ($4, $<ttype>6); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| CASE expr_no_commas ':'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_case_label ($2, NULL_TREE); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
stmt
|
|
|
|
|
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_case_label ($2, $4); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
stmt
|
|
|
|
|
| DEFAULT ':'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_case_label (NULL_TREE, NULL_TREE); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
stmt
|
|
|
|
|
| BREAK ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_break_stmt (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| CONTINUE ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_continue_stmt (); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| RETURN_KEYWORD ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_return_stmt (NULL_TREE); }
|
1999-10-16 06:09:09 +00:00
|
|
|
|
| RETURN_KEYWORD expr ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_return_stmt ($2); }
|
|
|
|
|
| asm_keyword maybe_cv_qualifier '(' string ')' ';'
|
|
|
|
|
{
|
|
|
|
|
finish_asm_stmt ($2, $4, NULL_TREE, NULL_TREE,
|
|
|
|
|
NULL_TREE);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
/* This is the case with just output operands. */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ')' ';'
|
|
|
|
|
{
|
|
|
|
|
finish_asm_stmt ($2, $4, $6, NULL_TREE,
|
|
|
|
|
NULL_TREE);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
/* This is the case with input operands as well. */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':' asm_operands ')' ';'
|
|
|
|
|
{ finish_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* This is the case with clobbered registers as well. */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':'
|
1996-09-18 05:35:50 +00:00
|
|
|
|
asm_operands ':' asm_clobbers ')' ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_asm_stmt ($2, $4, $6, $8, $10); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| GOTO '*' expr ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{
|
|
|
|
|
if (pedantic)
|
|
|
|
|
pedwarn ("ANSI C++ forbids computed gotos");
|
|
|
|
|
finish_goto_stmt ($3);
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| GOTO identifier ';'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_goto_stmt ($2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| label_colon stmt
|
|
|
|
|
{ finish_stmt (); }
|
|
|
|
|
| label_colon '}'
|
|
|
|
|
{ error ("label must be followed by statement");
|
|
|
|
|
yyungetc ('}', 0);
|
|
|
|
|
finish_stmt (); }
|
|
|
|
|
| ';'
|
|
|
|
|
{ finish_stmt (); }
|
|
|
|
|
| try_block
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| using_directive
|
|
|
|
|
| namespace_using_decl
|
|
|
|
|
{ do_local_using_decl ($1); }
|
|
|
|
|
| namespace_alias
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
function_try_block:
|
|
|
|
|
TRY
|
|
|
|
|
{
|
|
|
|
|
if (! current_function_parms_stored)
|
|
|
|
|
store_parm_decls ();
|
|
|
|
|
expand_start_early_try_stmts ();
|
|
|
|
|
}
|
1999-08-26 09:30:50 +00:00
|
|
|
|
ctor_initializer_opt compstmt
|
|
|
|
|
{
|
1999-10-16 06:09:09 +00:00
|
|
|
|
end_protect_partials ();
|
1999-08-26 09:30:50 +00:00
|
|
|
|
expand_start_all_catch ();
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
handler_seq
|
|
|
|
|
{
|
|
|
|
|
expand_end_all_catch ();
|
1999-10-16 06:09:09 +00:00
|
|
|
|
$$ = $3;
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
try_block:
|
|
|
|
|
TRY
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $<ttype>$ = begin_try_block (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
compstmt
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_try_block ($<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
handler_seq
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_handler_sequence ($<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
handler_seq:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
handler
|
|
|
|
|
| handler_seq handler
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
handler:
|
|
|
|
|
CATCH
|
|
|
|
|
{ $<ttype>$ = begin_handler(); }
|
|
|
|
|
handler_args
|
|
|
|
|
{ finish_handler_parms ($<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
compstmt
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ finish_handler ($<ttype>2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
type_specifier_seq:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
typed_typespecs %prec EMPTY
|
|
|
|
|
| nonempty_cv_qualifiers %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
handler_args:
|
|
|
|
|
'(' ELLIPSIS ')'
|
|
|
|
|
{ expand_start_catch_block (NULL_TREE, NULL_TREE); }
|
|
|
|
|
/* This doesn't allow reference parameters, the below does.
|
|
|
|
|
| '(' type_specifier_seq absdcl ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ check_for_new_type ("inside exception declarations", $2);
|
|
|
|
|
expand_start_catch_block ($2.t, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '(' type_specifier_seq ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ check_for_new_type ("inside exception declarations", $2);
|
|
|
|
|
expand_start_catch_block ($2.t, NULL_TREE); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '(' type_specifier_seq notype_declarator ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ check_for_new_type ("inside exception declarations", $2);
|
|
|
|
|
expand_start_catch_block ($2.t, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '(' typed_typespecs after_type_declarator ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ check_for_new_type ("inside exception declarations", $2);
|
|
|
|
|
expand_start_catch_block ($2.t, $3); }
|
|
|
|
|
This allows reference parameters... */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| '(' parm ')'
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ check_for_new_type ("inside exception declarations", $2);
|
|
|
|
|
expand_start_catch_block (TREE_PURPOSE ($2.t),
|
|
|
|
|
TREE_VALUE ($2.t)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
label_colon:
|
|
|
|
|
IDENTIFIER ':'
|
|
|
|
|
{ tree label;
|
|
|
|
|
do_label:
|
|
|
|
|
label = define_label (input_filename, lineno, $1);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (label && ! minimal_parse_mode)
|
1996-09-18 05:35:50 +00:00
|
|
|
|
expand_label (label);
|
|
|
|
|
}
|
|
|
|
|
| PTYPENAME ':'
|
|
|
|
|
{ goto do_label; }
|
|
|
|
|
| TYPENAME ':'
|
|
|
|
|
{ goto do_label; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| SELFNAME ':'
|
|
|
|
|
{ goto do_label; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
for.init.statement:
|
|
|
|
|
xexpr ';'
|
|
|
|
|
{ if ($1) cplus_expand_expr_stmt ($1); }
|
|
|
|
|
| decl
|
|
|
|
|
| '{' compstmtend
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ if (pedantic)
|
|
|
|
|
pedwarn ("ANSI C++ forbids compound statements inside for initializations");
|
|
|
|
|
}
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Either a type-qualifier or nothing. First thing in an `asm' statement. */
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
maybe_cv_qualifier:
|
|
|
|
|
/* empty */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ emit_line_note (input_filename, lineno);
|
|
|
|
|
$$ = NULL_TREE; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| CV_QUALIFIER
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ emit_line_note (input_filename, lineno); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
xexpr:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
| expr
|
|
|
|
|
| error
|
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* These are the operands other than the first string and colon
|
|
|
|
|
in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */
|
1999-08-26 09:30:50 +00:00
|
|
|
|
asm_operands:
|
|
|
|
|
/* empty */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
|
|
|
|
| nonnull_asm_operands
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
nonnull_asm_operands:
|
|
|
|
|
asm_operand
|
|
|
|
|
| nonnull_asm_operands ',' asm_operand
|
|
|
|
|
{ $$ = chainon ($$, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
asm_operand:
|
|
|
|
|
STRING '(' expr ')'
|
|
|
|
|
{ $$ = build_tree_list ($$, $3); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
asm_clobbers:
|
|
|
|
|
STRING
|
|
|
|
|
{ $$ = tree_cons (NULL_TREE, $$, NULL_TREE); }
|
|
|
|
|
| asm_clobbers ',' STRING
|
|
|
|
|
{ $$ = tree_cons (NULL_TREE, $3, $$); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* This is what appears inside the parens in a function declarator.
|
|
|
|
|
Its value is represented in the format that grokdeclarator expects.
|
|
|
|
|
|
|
|
|
|
In C++, declaring a function with no parameters
|
|
|
|
|
means that that function takes *no* parameters. */
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
parmlist:
|
|
|
|
|
/* empty */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = empty_parms();
|
1996-09-18 05:35:50 +00:00
|
|
|
|
}
|
|
|
|
|
| complex_parmlist
|
|
|
|
|
| type_id
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_parmlist (build_tree_list (NULL_TREE, $1.t), 0);
|
|
|
|
|
check_for_new_type ("inside parameter list", $1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* This nonterminal does not include the common sequence '(' type_id ')',
|
|
|
|
|
as it is ambiguous and must be disambiguated elsewhere. */
|
|
|
|
|
complex_parmlist:
|
|
|
|
|
parms
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_parmlist ($$, 0); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| parms_comma ELLIPSIS
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_parmlist ($1, 1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* C++ allows an ellipsis without a separating ',' */
|
|
|
|
|
| parms ELLIPSIS
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_parmlist ($1, 1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| type_id ELLIPSIS
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_parmlist (build_tree_list (NULL_TREE,
|
|
|
|
|
$1.t), 1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| ELLIPSIS
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = finish_parmlist (NULL_TREE, 1); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| parms ':'
|
|
|
|
|
{
|
|
|
|
|
/* This helps us recover from really nasty
|
|
|
|
|
parse errors, for example, a missing right
|
|
|
|
|
parenthesis. */
|
|
|
|
|
yyerror ("possibly missing ')'");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = finish_parmlist ($1, 0);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
yyungetc (':', 0);
|
|
|
|
|
yychar = ')';
|
|
|
|
|
}
|
|
|
|
|
| type_id ':'
|
|
|
|
|
{
|
|
|
|
|
/* This helps us recover from really nasty
|
|
|
|
|
parse errors, for example, a missing right
|
|
|
|
|
parenthesis. */
|
|
|
|
|
yyerror ("possibly missing ')'");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$ = finish_parmlist (build_tree_list (NULL_TREE,
|
|
|
|
|
$1.t), 0);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
yyungetc (':', 0);
|
|
|
|
|
yychar = ')';
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* A default argument to a */
|
|
|
|
|
defarg:
|
|
|
|
|
'='
|
|
|
|
|
{ maybe_snarf_defarg (); }
|
|
|
|
|
defarg1
|
|
|
|
|
{ $$ = $3; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
defarg1:
|
|
|
|
|
DEFARG
|
|
|
|
|
| init
|
|
|
|
|
;
|
|
|
|
|
|
1996-09-18 05:35:50 +00:00
|
|
|
|
/* A nonempty list of parameter declarations or type names. */
|
|
|
|
|
parms:
|
|
|
|
|
named_parm
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ check_for_new_type ("in a parameter list", $1);
|
|
|
|
|
$$ = build_tree_list (NULL_TREE, $1.t); }
|
|
|
|
|
| parm defarg
|
|
|
|
|
{ check_for_new_type ("in a parameter list", $1);
|
|
|
|
|
$$ = build_tree_list ($2, $1.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| parms_comma full_parm
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ check_for_new_type ("in a parameter list", $2);
|
|
|
|
|
$$ = chainon ($$, $2.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| parms_comma bad_parm
|
|
|
|
|
{ $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); }
|
|
|
|
|
| parms_comma bad_parm '=' init
|
|
|
|
|
{ $$ = chainon ($$, build_tree_list ($4, $2)); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
parms_comma:
|
|
|
|
|
parms ','
|
|
|
|
|
| type_id ','
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ check_for_new_type ("in a parameter list", $1);
|
|
|
|
|
$$ = build_tree_list (NULL_TREE, $1.t); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* A single parameter declaration or parameter type name,
|
1999-08-26 09:30:50 +00:00
|
|
|
|
as found in a parmlist. */
|
1996-09-18 05:35:50 +00:00
|
|
|
|
named_parm:
|
|
|
|
|
/* Here we expand typed_declspecs inline to avoid mis-parsing of
|
|
|
|
|
TYPESPEC IDENTIFIER. */
|
|
|
|
|
typed_declspecs1 declarator
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ tree specs = strip_attrs ($1.t);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag;
|
|
|
|
|
$$.t = build_tree_list (specs, $2); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| typed_typespecs declarator
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$.t = build_tree_list ($1.t, $2);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| typespec declarator
|
1999-10-16 06:09:09 +00:00
|
|
|
|
{ $$.t = build_tree_list (build_decl_list (NULL_TREE, $1.t),
|
|
|
|
|
$2);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| typed_declspecs1 absdcl
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ tree specs = strip_attrs ($1.t);
|
|
|
|
|
$$.t = build_tree_list (specs, $2);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
|
|
|
|
| typed_declspecs1 %prec EMPTY
|
|
|
|
|
{ tree specs = strip_attrs ($1.t);
|
|
|
|
|
$$.t = build_tree_list (specs, NULL_TREE);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| declmods notype_declarator
|
|
|
|
|
{ tree specs = strip_attrs ($1);
|
1999-08-26 09:30:50 +00:00
|
|
|
|
$$.t = build_tree_list (specs, $2);
|
|
|
|
|
$$.new_type_flag = 0; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
full_parm:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
parm
|
|
|
|
|
{ $$.t = build_tree_list (NULL_TREE, $1.t);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
|
|
|
|
| parm defarg
|
|
|
|
|
{ $$.t = build_tree_list ($2, $1.t);
|
|
|
|
|
$$.new_type_flag = $1.new_type_flag; }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
parm:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
named_parm
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| type_id
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
see_typename:
|
|
|
|
|
/* empty */ %prec EMPTY
|
|
|
|
|
{ see_typename (); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
bad_parm:
|
|
|
|
|
/* empty */ %prec EMPTY
|
|
|
|
|
{
|
|
|
|
|
error ("type specifier omitted for parameter");
|
|
|
|
|
$$ = build_tree_list (integer_type_node, NULL_TREE);
|
|
|
|
|
}
|
|
|
|
|
| notype_declarator
|
|
|
|
|
{
|
|
|
|
|
error ("type specifier omitted for parameter");
|
1999-08-26 09:30:50 +00:00
|
|
|
|
if (TREE_CODE ($$) == SCOPE_REF
|
|
|
|
|
&& (TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TYPE_PARM
|
|
|
|
|
|| TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TEMPLATE_PARM))
|
|
|
|
|
cp_error (" perhaps you want `typename %E' to make it a type", $$);
|
1996-09-18 05:35:50 +00:00
|
|
|
|
$$ = build_tree_list (integer_type_node, $$);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
exception_specification_opt:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */ %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| THROW '(' ansi_raise_identifiers ')' %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = $3; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| THROW LEFT_RIGHT %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = build_decl_list (NULL_TREE, NULL_TREE); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
ansi_raise_identifier:
|
|
|
|
|
type_id
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = build_decl_list (NULL_TREE, groktypename($1.t)); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
ansi_raise_identifiers:
|
|
|
|
|
ansi_raise_identifier
|
|
|
|
|
| ansi_raise_identifiers ',' ansi_raise_identifier
|
|
|
|
|
{
|
|
|
|
|
TREE_CHAIN ($3) = $$;
|
|
|
|
|
$$ = $3;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
conversion_declarator:
|
1999-08-26 09:30:50 +00:00
|
|
|
|
/* empty */ %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = NULL_TREE; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| '*' cv_qualifiers conversion_declarator
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_pointer_declarator ($2, $3); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| '&' cv_qualifiers conversion_declarator
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = make_reference_declarator ($2, $3); }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| ptr_to_mem cv_qualifiers conversion_declarator
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ tree arg = make_pointer_declarator ($2, $3);
|
|
|
|
|
$$ = build_parse_node (SCOPE_REF, $1, arg);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-08-26 09:30:50 +00:00
|
|
|
|
operator:
|
|
|
|
|
OPERATOR
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ got_scope = NULL_TREE; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
operator_name:
|
|
|
|
|
operator '*'
|
|
|
|
|
{ $$ = ansi_opname[MULT_EXPR]; }
|
|
|
|
|
| operator '/'
|
|
|
|
|
{ $$ = ansi_opname[TRUNC_DIV_EXPR]; }
|
|
|
|
|
| operator '%'
|
|
|
|
|
{ $$ = ansi_opname[TRUNC_MOD_EXPR]; }
|
|
|
|
|
| operator '+'
|
|
|
|
|
{ $$ = ansi_opname[PLUS_EXPR]; }
|
|
|
|
|
| operator '-'
|
|
|
|
|
{ $$ = ansi_opname[MINUS_EXPR]; }
|
|
|
|
|
| operator '&'
|
|
|
|
|
{ $$ = ansi_opname[BIT_AND_EXPR]; }
|
|
|
|
|
| operator '|'
|
|
|
|
|
{ $$ = ansi_opname[BIT_IOR_EXPR]; }
|
|
|
|
|
| operator '^'
|
|
|
|
|
{ $$ = ansi_opname[BIT_XOR_EXPR]; }
|
|
|
|
|
| operator '~'
|
|
|
|
|
{ $$ = ansi_opname[BIT_NOT_EXPR]; }
|
|
|
|
|
| operator ','
|
|
|
|
|
{ $$ = ansi_opname[COMPOUND_EXPR]; }
|
|
|
|
|
| operator ARITHCOMPARE
|
|
|
|
|
{ $$ = ansi_opname[$2]; }
|
|
|
|
|
| operator '<'
|
|
|
|
|
{ $$ = ansi_opname[LT_EXPR]; }
|
|
|
|
|
| operator '>'
|
|
|
|
|
{ $$ = ansi_opname[GT_EXPR]; }
|
|
|
|
|
| operator EQCOMPARE
|
|
|
|
|
{ $$ = ansi_opname[$2]; }
|
|
|
|
|
| operator ASSIGN
|
|
|
|
|
{ $$ = ansi_assopname[$2]; }
|
|
|
|
|
| operator '='
|
|
|
|
|
{ $$ = ansi_opname [MODIFY_EXPR]; }
|
|
|
|
|
| operator LSHIFT
|
|
|
|
|
{ $$ = ansi_opname[$2]; }
|
|
|
|
|
| operator RSHIFT
|
|
|
|
|
{ $$ = ansi_opname[$2]; }
|
|
|
|
|
| operator PLUSPLUS
|
|
|
|
|
{ $$ = ansi_opname[POSTINCREMENT_EXPR]; }
|
|
|
|
|
| operator MINUSMINUS
|
|
|
|
|
{ $$ = ansi_opname[PREDECREMENT_EXPR]; }
|
|
|
|
|
| operator ANDAND
|
|
|
|
|
{ $$ = ansi_opname[TRUTH_ANDIF_EXPR]; }
|
|
|
|
|
| operator OROR
|
|
|
|
|
{ $$ = ansi_opname[TRUTH_ORIF_EXPR]; }
|
|
|
|
|
| operator '!'
|
|
|
|
|
{ $$ = ansi_opname[TRUTH_NOT_EXPR]; }
|
|
|
|
|
| operator '?' ':'
|
|
|
|
|
{ $$ = ansi_opname[COND_EXPR]; }
|
|
|
|
|
| operator MIN_MAX
|
|
|
|
|
{ $$ = ansi_opname[$2]; }
|
|
|
|
|
| operator POINTSAT %prec EMPTY
|
|
|
|
|
{ $$ = ansi_opname[COMPONENT_REF]; }
|
|
|
|
|
| operator POINTSAT_STAR %prec EMPTY
|
|
|
|
|
{ $$ = ansi_opname[MEMBER_REF]; }
|
|
|
|
|
| operator LEFT_RIGHT
|
|
|
|
|
{ $$ = ansi_opname[CALL_EXPR]; }
|
|
|
|
|
| operator '[' ']'
|
|
|
|
|
{ $$ = ansi_opname[ARRAY_REF]; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| operator NEW %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = ansi_opname[NEW_EXPR]; }
|
1999-08-26 09:30:50 +00:00
|
|
|
|
| operator DELETE %prec EMPTY
|
1996-09-18 05:35:50 +00:00
|
|
|
|
{ $$ = ansi_opname[DELETE_EXPR]; }
|
|
|
|
|
| operator NEW '[' ']'
|
|
|
|
|
{ $$ = ansi_opname[VEC_NEW_EXPR]; }
|
|
|
|
|
| operator DELETE '[' ']'
|
|
|
|
|
{ $$ = ansi_opname[VEC_DELETE_EXPR]; }
|
|
|
|
|
/* Names here should be looked up in class scope ALSO. */
|
|
|
|
|
| operator type_specifier_seq conversion_declarator
|
1999-08-26 09:30:50 +00:00
|
|
|
|
{ $$ = grokoptypename ($2.t, $3); }
|
1996-09-18 05:35:50 +00:00
|
|
|
|
| operator error
|
|
|
|
|
{ $$ = ansi_opname[ERROR_MARK]; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
|
|
#ifdef SPEW_DEBUG
|
|
|
|
|
const char *
|
|
|
|
|
debug_yytranslate (value)
|
|
|
|
|
int value;
|
|
|
|
|
{
|
|
|
|
|
return yytname[YYTRANSLATE (value)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|