OSDN Git Service

* parse.y (nested_name_specifier_1): Pull out the TYPE_MAIN_VARIANT.
[pf3gnuchains/gcc-fork.git] / gcc / cp / parse.y
index 9bdc979..c5acf27 100644 (file)
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA.  */
 #include "cp-tree.h"
 #include "output.h"
 #include "except.h"
+#include "toplev.h"
 
 /* Since parsers are distinct for each language, put the language string
    definition here.  (fnf) */
@@ -221,7 +222,8 @@ empty_parms ()
 %type <ttype> template_id do_id object_template_id notype_template_declarator
 %type <ttype> overqualified_id notype_qualified_id any_id
 %type <ttype> complex_direct_notype_declarator functional_cast
-%type <ttype> complex_parmlist parms_comma
+%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
@@ -243,7 +245,7 @@ empty_parms ()
 %type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
 %type <ttype> operator_name
 %type <ttype> object aggr
-%type <itype> new delete
+%type <itype> new delete .begin_new_placement
 /* %type <ttype> primary_no_id */
 %type <ttype> nonmomentary_expr maybe_parmlist
 %type <itype> initdcl0 notype_initdcl0 member_init_list initdcl0_innards
@@ -279,13 +281,14 @@ empty_parms ()
 \f
 %{
 /* List of types and structure classes of the current declaration.  */
-static tree current_declspecs = NULL_TREE;
+static tree current_declspecs;
+
 /* 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 = NULL_TREE;
+static tree prefix_attributes;
 
 /* When defining an aggregate, this is the most recent one being defined.  */
 static tree current_aggr;
@@ -400,23 +403,26 @@ extdef:
                { push_namespace (NULL_TREE); }
          extdefs_opt '}'
                { pop_namespace (); }
-       | NAMESPACE identifier '=' any_id ';'
-               { do_namespace_alias ($2, $4); }
+       | namespace_alias
        | using_decl ';'
                { do_toplevel_using_decl ($1); }
-       | USING NAMESPACE any_id ';'
-               {
-                 /* 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 ($3) == IDENTIFIER_NODE && lastiddecl)
-                   $3 = lastiddecl;
-                 do_using_directive ($3);
-               }
+       | 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);
+               }
+       ;
+
 using_decl:
          USING qualified_id
                { $$ = $2; }
@@ -426,6 +432,45 @@ using_decl:
                { $$ = $3; }
        ;
 
+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 = $$;
+               }
+
 any_id:
          unqualified_id
        | qualified_id
@@ -874,6 +919,8 @@ template_arg_list:
 template_arg:
          type_id
                { $$ = groktypename ($1.t); }
+       | PTYPENAME
+               { $$ = lastiddecl; }
        | expr_no_commas  %prec ARITHCOMPARE
        ;
 
@@ -918,7 +965,6 @@ xcond:
          /* empty */
                { $$ = NULL_TREE; }
        | condition
-               { $$ = condition_conversion ($$); }
        | error
                { $$ = NULL_TREE; }
        ;
@@ -1031,19 +1077,32 @@ unary_expr:
        | new new_placement new_type_id new_initializer
                { $$ = build_new ($2, $3.t, $4, $1); 
                  check_for_new_type ("new", $3); }
-       | new '(' type_id ')'  %prec EMPTY
-               { $$ = build_new (NULL_TREE, groktypename($3.t),
+        /* 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", $3); }
-       | new '(' type_id ')' new_initializer
-               { $$ = build_new (NULL_TREE, groktypename($3.t), $5, $1); 
-                 check_for_new_type ("new", $3); }
-       | new new_placement '(' type_id ')'  %prec EMPTY
-               { $$ = build_new ($2, groktypename($4.t), NULL_TREE, $1); 
                  check_for_new_type ("new", $4); }
-       | new new_placement '(' type_id ')' new_initializer
-               { $$ = build_new ($2, groktypename($4.t), $6, $1); 
+       | 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); }
 
        | delete cast_expr  %prec UNARY
                { $$ = delete_sanity ($2, NULL_TREE, 0, $1); }
@@ -1061,16 +1120,24 @@ unary_expr:
                { $$ = build_x_unary_op (IMAGPART_EXPR, $2); }
        ;
 
+        /* 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 (); }
+
 new_placement:
-         '(' 
-                { $<itype>$ = begin_new_placement (); }
-            nonnull_exprlist ')'
-                { $$ = finish_new_placement ($3, $<itype>1); }
-       | '{' 
+         '(' .begin_new_placement nonnull_exprlist ')'
+                { $$ = finish_new_placement ($3, $2); }
+       | '{' .begin_new_placement nonnull_exprlist '}'
                 { cp_pedwarn ("old style placement syntax, use () instead");
-                 $<itype>$ = begin_new_placement (); }
-           nonnull_exprlist '}'
-                { $$ = finish_new_placement ($3, $<itype>1); }
+                 $$ = finish_new_placement ($3, $2); }
        ;
 
 new_initializer:
@@ -1206,7 +1273,7 @@ notype_unqualified_id:
        ;
 
 do_id:
-               { $$ = do_identifier ($<ttype>-1, 1); }
+               { $$ = do_identifier ($<ttype>-1, 1, NULL_TREE); }
 
 template_id:
           PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket 
@@ -1293,10 +1360,17 @@ primary:
                }
          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); }
        | primary '(' nonnull_exprlist ')'
-               { $$ = finish_call_expr ($1, $3); }
+               { $$ = finish_call_expr ($1, $3, 0); }
        | primary LEFT_RIGHT
-               { $$ = finish_call_expr ($1, NULL_TREE); }
+               { $$ = finish_call_expr ($1, NULL_TREE, 0); }
        | primary '[' expr ']'
                { $$ = grok_array_decl ($$, $3); }
        | primary PLUSPLUS
@@ -1375,6 +1449,8 @@ primary:
                  $$ = get_typeid (TYPE_MAIN_VARIANT (type)); }
        | global_scope IDENTIFIER
                { $$ = do_scoped_id ($2, 1); }
+       | global_scope template_id
+               { $$ = $2; }
        | global_scope operator_name
                {
                  got_scope = NULL_TREE;
@@ -2049,6 +2125,8 @@ aggr:
                { 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"); }
+       | aggr attributes
+               { $$ = build_decl_list ($2, $1); }
        ;
 
 named_class_head_sans_basetype:
@@ -2059,6 +2137,10 @@ named_class_head_sans_basetype:
 named_class_head_sans_basetype_defn:
          aggr identifier_defn  %prec EMPTY
                { current_aggr = $$; $$ = $2; }
+       | named_class_head_sans_basetype '{'
+               { yyungetc ('{', 1); }
+       | named_class_head_sans_basetype ':'
+               { yyungetc (':', 1); }
        ;
 
 named_complex_class_head_sans_basetype:
@@ -2155,7 +2237,14 @@ base_class_list:
 base_class:
          base_class.1
                {
-                 tree type = TREE_TYPE ($1);
+                 tree type;
+                 if ($1 == NULL_TREE)
+                   {
+                     error ("invalid base class");
+                     type = error_mark_node;
+                   }
+                 else
+                   type = TREE_TYPE ($1);
                  if (! is_aggr_type (type, 1))
                    $$ = NULL_TREE;
                  else if (current_aggr == signature_type_node
@@ -2180,10 +2269,17 @@ base_class:
                }
        | base_class_access_list see_typename base_class.1
                {
-                 tree type = TREE_TYPE ($3);
+                 tree type;
+                 if ($3 == NULL_TREE)
+                   {
+                     error ("invalid base class");
+                     type = error_mark_node;
+                   }
+                 else
+                   type = TREE_TYPE ($3);
                  if (current_aggr == signature_type_node)
                    error ("access and source specifiers not allowed in signature");
-                 if (! IS_AGGR_TYPE (type))
+                 if (! is_aggr_type (type, 1))
                    $$ = NULL_TREE;
                  else if (current_aggr == signature_type_node
                           && (! type) && (! IS_SIGNATURE (type)))
@@ -2372,15 +2468,7 @@ component_decl:
         | template_header component_decl
                 { $$ = finish_member_template_decl ($1, $2); }
        | template_header typed_declspecs ';'
-                {
-                 note_list_got_semicolon ($2.t);
-                 grok_x_components ($2.t, NULL_TREE); 
-                 if (TYPE_CONTEXT (TREE_VALUE ($2.t)) != current_class_type)
-                   /* The component was in fact a friend
-                      declaration.  */
-                   $2.t = NULL_TREE;
-                 $$ = finish_member_template_decl ($1, $2.t);
-               }
+                { $$ = finish_member_class_template ($1, $2.t); }
        ;
 
 component_decl_1:
@@ -2552,14 +2640,16 @@ new_type_id:
                { $$.t = build_decl_list ($1.t, NULL_TREE); 
                  $$.new_type_flag = $1.new_type_flag; }
        /* GNU extension to allow arrays of arbitrary types with
-          non-constant dimension.  */
-       | '(' type_id ')' '[' expr ']'
+          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 ']'
                {
                  if (pedantic)
                    pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new");
-                 $$.t = build_parse_node (ARRAY_REF, TREE_VALUE ($2.t), $5);
-                 $$.t = build_decl_list (TREE_PURPOSE ($2.t), $$.t);
-                 $$.new_type_flag = $2.new_type_flag;
+                 $$.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;
                }
        ;
 
@@ -2723,10 +2813,15 @@ complex_direct_notype_declarator:
        | direct_notype_declarator '[' ']'
                { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
        | notype_qualified_id
-               { if (OP0 ($$) != current_class_type)
+               { if (TREE_CODE (OP0 ($1)) == NAMESPACE_DECL)
                    {
-                     push_nested_class (OP0 ($$), 3);
-                     TREE_COMPLEXITY ($$) = current_class_depth;
+                     push_decl_namespace (OP0 ($1));
+                     TREE_COMPLEXITY ($1) = -1;
+                   }
+                 else if (OP0 ($1) != current_class_type)
+                   {
+                     push_nested_class (OP0 ($1), 3);
+                     TREE_COMPLEXITY ($1) = current_class_depth;
                    }
                }
         | nested_name_specifier notype_template_declarator
@@ -2802,7 +2897,7 @@ nested_name_specifier_1:
                          && ! IDENTIFIER_CLASS_VALUE ($1))
                        pushdecl_class_level ($$);
                    }
-                 got_scope = $$ = TREE_TYPE ($$);
+                 got_scope = $$ = TYPE_MAIN_VARIANT (TREE_TYPE ($$));
                }
        | SELFNAME SCOPE
                {
@@ -3212,6 +3307,10 @@ simple_stmt:
        | ';'
                { finish_stmt (); }
        | try_block
+       | using_directive
+       | namespace_using_decl
+               { do_local_using_decl ($1); }
+       | namespace_alias
        ;
 
 function_try_block:
@@ -3224,14 +3323,12 @@ function_try_block:
          ctor_initializer_opt compstmt
                { 
                   expand_start_all_catch (); 
-                  expand_start_catch (NULL);
                 }
          handler_seq
                {
                  int nested = (hack_decl_function_context
                                (current_function_decl) != NULL_TREE);
                  expand_end_all_catch ();
-                  expand_end_catch ();
                  finish_function (lineno, (int)$3, nested);
                }
        ;