OSDN Git Service

* c-common.c (builtin_define_float_constants): Define
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 30 Jan 2003 07:24:02 +0000 (07:24 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 30 Jan 2003 07:24:02 +0000 (07:24 +0000)
__<TYPE>_HAS_INFINITY__ and __<TYPE>_HAS_QUIET_NAN__.

* call.c (build_field_call): Use build_new_op, not build_opfncall.
(prep_operand): New function.
(build_new_op): Use it.  Remove dead code.
* class.c (pushclass): Change "modify" parameter type from int to
bool.
(currently_open_class): Use same_type_p, not pointer equality.
(push_nested_class): Adjust calls to pushclass, remove modify
parameter.
* cp-tree.h (INTEGRAL_OR_ENUMERATION_TYPE_P): New macro.
(pushclass): Change prototype.
(push_nested_class): Likewise.
(grokoptypename): Remove.
(build_opfncall): Remove.
(value_dependent_expression_p): Declare.
(resolve_typename_type): Likewise.
(resolve_typename_type_in_current_instantiation): Likewise.
(enter_scope_of): Remove.
(tsubst): Remove.
(tsubst_expr): Likewise.
(tsubst_copy): Likewise.
(tsubst_copy_and_build): Likewise.
* decl.c (warn_about_implicit_typename_lookup): Remove.
(finish_case_label): Return error_mark_node for erroneous labels.
(start_decl): Adjust calls to push_nested_class.
(grokfndecl): Call push_scope/pop_scope around call to
duplicate_decls.
(grokdeclarator): Do not call tsubst.
(start_function): Adjust calls to push_nested_class.
* decl2.c (grok_array_decl): Use build_new_op, not build_opfncall.
(check_classfn): Use push_scope/pop_scope around type comparisions.
(grokoptypename): Remove.
(push_sscope): Adjust call to push_nested_class.
* error.c (dump_type): Show cv-qualification of typename types.
* init.c (build_member_call): Use build_new_op, not
build_opfncall.
* method.c (build_opfncall): Remove.
* parser.c (cp_parser): Add allow_non_constant_expression_p and
non_constant_expression_p.
(cp_parser_constant_expression): Adjust prototype.
(cp_parser_resolve_typename_type): Remove.
(cp_parser_non_constant_expression): New function.
(cp_parser_non_constant_id_expression): Likewise.
(cp_parser_new): Set allow_non_constant_expression_p and
non_constant_expression_p.
(cp_parser_primary_expression): Reject `this' and `va_arg' in
constant-expressions.  Note that dependent names aren't really
constant.
(cp_parser_postfix_expression): Reject conversions to non-integral
types in constant-expressions.  Neither are increments or
decrements.
(cp_parser_unary_expression): Reject increments and decrements in
constant-expressions.
(cp_parser_direct_new_declarator): Adjust call to
cp_parser_constant_expression.
(cp_parser_cast_expression): Reject conversions to non-integral
types in constant-expressions.
(cp_parser_assignment_expression): Rejects assignments in
constant-expressions.
(cp_parser_expression): Reject commas in constant-expressions.
(cp_parser_labeled_statement): Adjust call to
cp_parser_constant_expression.
(cp_parser_direct_declarator): Simplify array bounds, even in
templates, when they are non-dependent.  Use
resolve_typename_type, not cp_parser_resolve_typename_type.
(cp_parser_class_head): Use resolve_typename_type, not
cp_parser_resolve_typename_type.
(cp_parser_member_declaration): Adjust call to
cp_parser_constant_expression.
(cp_parser_constant_initializer): Likewise.
(cp_parser_constructor_declarator): Use resolve_typename_type, not
cp_parser_resolve_typename_type.
(cp_parser_late_parsing_default_args): Adjust call to
push_nested_class.
* pt.c (tsubst): Give it internal linkage.
(tsubst_expr): Likewise.
(tsubst_copy): Likewise.
(tsubst_copy_and_build): Likewise.
(push_access_scope_real): Likewise.
(tsubst_friend_class): Likewise.
(instantiate_class_template): Adjust call to pushclass.
(value_dependent_expression_p): Give it external linkage.
Robustify.
(resolve_typename_type): New function.
* semantics.c (finish_call_expr): Use build_new_op, not
build_opfncall.
(begin_constructor_declarator): Remove.
(begin_class_definition): Adjust call to pushclass.
(enter_scope_of): Remove.
* typeck.c (comptypes): Resolve typename types as appropriate.
(build_x_indirect_ref): Use build_new_op, not build_opfncall.
(build_x_compound_expr): Likewise.
(build_modify_expr): Likewise.
(build_x_modify_expr): Likewise.
* typeck2.c (build_x_arrow): Likewise.

* g++.dg/parser/constant1.C: New test.

* include/std/std_limits.h (numeric_limits<float>::has_infinity):
Use __FLT_HAS_INIFINITY__ to initialize.
(numeric_limits<float>::has_quiet_NaN): Likewise.
(numeric_limits<double>::has_infinity): Use __DBL_HAS_INIFINITY__
to initialize.
(numeric_limits<double>::has_quiet_NaN): Likewise.
(numeric_limits<long double>::has_infinity): Use
__LDBL_HAS_INIFINITY__ to initialize.
(numeric_limits<long_double>::has_quiet_NaN): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@62130 138bc75d-0d04-0410-961f-82ee72b054a4

20 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/constant1.C [new file with mode: 0644]
libstdc++-v3/ChangeLog
libstdc++-v3/include/std/std_limits.h

index d4a863a..54129c4 100644 (file)
@@ -1,3 +1,8 @@
+2003-01-29  Mark Mitchell  <mark@codesourcery.com>
+
+       * c-common.c (builtin_define_float_constants): Define
+       __<TYPE>_HAS_INFINITY__ and __<TYPE>_HAS_QUIET_NAN__.
+
 2003-01-30  Kazu Hirata  <kazu@cs.umass.edu>
 
        * config/sh/lib1funcs.asm: Fix comment typos.
index cf7fb07..7c6fc78 100644 (file)
@@ -4896,6 +4896,18 @@ builtin_define_float_constants (name_prefix, fp_suffix, type)
       sprintf (buf, "0.0%s", fp_suffix);
       builtin_define_with_value (name, buf, 0);
     }
+
+  /* For C++ std::numeric_limits<T>::has_infinity.  */
+  sprintf (name, "__%s_HAS_INFINITY__", name_prefix);
+  builtin_define_with_int_value (name, 
+                                MODE_HAS_INFINITIES (TYPE_MODE (type)));
+  /* For C++ std::numeric_limits<T>::has_quiet_NaN.  We do not have a
+     predicate to distinguish a target that has both quiet and
+     signalling NaNs from a target that has only quiet NaNs or only
+     signalling NaNs, so we assume that a target that has any kind of
+     NaN has quiet NaNs.  */
+  sprintf (name, "__%s_HAS_QUIET_NAN__", name_prefix);
+  builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type)));
 }
 
 /* Hook that registers front end and target-specific built-ins.  */
index 64adf91..1b00808 100644 (file)
@@ -1,3 +1,100 @@
+2003-01-29  Mark Mitchell  <mark@codesourcery.com>
+
+       * call.c (build_field_call): Use build_new_op, not build_opfncall.
+       (prep_operand): New function.
+       (build_new_op): Use it.  Remove dead code.
+       * class.c (pushclass): Change "modify" parameter type from int to
+       bool.
+       (currently_open_class): Use same_type_p, not pointer equality.
+       (push_nested_class): Adjust calls to pushclass, remove modify
+       parameter.
+       * cp-tree.h (INTEGRAL_OR_ENUMERATION_TYPE_P): New macro.
+       (pushclass): Change prototype.
+       (push_nested_class): Likewise.
+       (grokoptypename): Remove.
+       (build_opfncall): Remove.
+       (value_dependent_expression_p): Declare.
+       (resolve_typename_type): Likewise.
+       (resolve_typename_type_in_current_instantiation): Likewise.
+       (enter_scope_of): Remove.
+       (tsubst): Remove.
+       (tsubst_expr): Likewise.
+       (tsubst_copy): Likewise.
+       (tsubst_copy_and_build): Likewise.
+       * decl.c (warn_about_implicit_typename_lookup): Remove.
+       (finish_case_label): Return error_mark_node for erroneous labels.
+       (start_decl): Adjust calls to push_nested_class.
+       (grokfndecl): Call push_scope/pop_scope around call to
+       duplicate_decls.
+       (grokdeclarator): Do not call tsubst.
+       (start_function): Adjust calls to push_nested_class.
+       * decl2.c (grok_array_decl): Use build_new_op, not build_opfncall.
+       (check_classfn): Use push_scope/pop_scope around type comparisions.
+       (grokoptypename): Remove.
+       (push_sscope): Adjust call to push_nested_class.
+       * error.c (dump_type): Show cv-qualification of typename types.
+       * init.c (build_member_call): Use build_new_op, not
+       build_opfncall.
+       * method.c (build_opfncall): Remove.
+       * parser.c (cp_parser): Add allow_non_constant_expression_p and
+       non_constant_expression_p.
+       (cp_parser_constant_expression): Adjust prototype.
+       (cp_parser_resolve_typename_type): Remove.
+       (cp_parser_non_constant_expression): New function.
+       (cp_parser_non_constant_id_expression): Likewise.
+       (cp_parser_new): Set allow_non_constant_expression_p and
+       non_constant_expression_p.
+       (cp_parser_primary_expression): Reject `this' and `va_arg' in
+       constant-expressions.  Note that dependent names aren't really
+       constant.
+       (cp_parser_postfix_expression): Reject conversions to non-integral
+       types in constant-expressions.  Neither are increments or
+       decrements.
+       (cp_parser_unary_expression): Reject increments and decrements in
+       constant-expressions.
+       (cp_parser_direct_new_declarator): Adjust call to
+       cp_parser_constant_expression.
+       (cp_parser_cast_expression): Reject conversions to non-integral
+       types in constant-expressions.
+       (cp_parser_assignment_expression): Rejects assignments in
+       constant-expressions.
+       (cp_parser_expression): Reject commas in constant-expressions.
+       (cp_parser_labeled_statement): Adjust call to
+       cp_parser_constant_expression.
+       (cp_parser_direct_declarator): Simplify array bounds, even in
+       templates, when they are non-dependent.  Use
+       resolve_typename_type, not cp_parser_resolve_typename_type.
+       (cp_parser_class_head): Use resolve_typename_type, not
+       cp_parser_resolve_typename_type.
+       (cp_parser_member_declaration): Adjust call to
+       cp_parser_constant_expression.
+       (cp_parser_constant_initializer): Likewise.
+       (cp_parser_constructor_declarator): Use resolve_typename_type, not
+       cp_parser_resolve_typename_type.
+       (cp_parser_late_parsing_default_args): Adjust call to
+       push_nested_class.
+       * pt.c (tsubst): Give it internal linkage.
+       (tsubst_expr): Likewise.
+       (tsubst_copy): Likewise.
+       (tsubst_copy_and_build): Likewise.
+       (push_access_scope_real): Likewise.
+       (tsubst_friend_class): Likewise.
+       (instantiate_class_template): Adjust call to pushclass.
+       (value_dependent_expression_p): Give it external linkage.
+       Robustify.
+       (resolve_typename_type): New function.
+       * semantics.c (finish_call_expr): Use build_new_op, not
+       build_opfncall.
+       (begin_constructor_declarator): Remove.
+       (begin_class_definition): Adjust call to pushclass.
+       (enter_scope_of): Remove.
+       * typeck.c (comptypes): Resolve typename types as appropriate.
+       (build_x_indirect_ref): Use build_new_op, not build_opfncall.
+       (build_x_compound_expr): Likewise.
+       (build_modify_expr): Likewise.
+       (build_x_modify_expr): Likewise.
+       * typeck2.c (build_x_arrow): Likewise.
+       
 2003-01-29  Fariborz Jahanian  <fjahanian@apple.com>
 
         * pt.c (last_pending_template) Declare GTY().
index cb0d351..440d58a 100644 (file)
@@ -103,6 +103,7 @@ static bool promoted_arithmetic_type_p (tree);
 static tree conditional_conversion (tree, tree);
 static char *name_as_c_string (tree, tree, bool *);
 static tree call_builtin_trap (void);
+static tree prep_operand (tree);
 
 tree
 build_vfield_ref (tree datum, tree type)
@@ -145,8 +146,8 @@ build_field_call (tree instance_ptr, tree decl, tree parms)
        return error_mark_node;
 
       if (IS_AGGR_TYPE (TREE_TYPE (instance)))
-       return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
-                              instance, parms, NULL_TREE);
+       return build_new_op (CALL_EXPR, LOOKUP_NORMAL,
+                            instance, parms, NULL_TREE);
       else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE
               || (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE
                   && (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
@@ -3295,6 +3296,27 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
   return result;
 }
 
+/* OPERAND is an operand to an expression.  Perform necessary steps
+   required before using it.  If OPERAND is NULL_TREE, NULL_TREE is
+   returned.  */
+
+static tree
+prep_operand (tree operand)
+{
+  if (operand)
+    {
+      if (TREE_CODE (operand) == OFFSET_REF)
+       operand = resolve_offset_ref (operand);
+      operand = convert_from_reference (operand);
+      if (CLASS_TYPE_P (TREE_TYPE (operand))
+         && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand)))
+       /* Make sure the template type is instantiated now.  */
+       instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (operand)));
+    }
+
+  return operand;
+}
+
 tree
 build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
 {
@@ -3310,14 +3332,6 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
       || error_operand_p (arg3))
     return error_mark_node;
 
-  /* This can happen if a template takes all non-type parameters, e.g.
-     undeclared_template<1, 5, 72>a;  */
-  if (code == LT_EXPR && TREE_CODE (arg1) == TEMPLATE_DECL)
-    {
-      error ("`%D' must be declared before use", arg1);
-      return error_mark_node;
-    }
-
   if (code == MODIFY_EXPR)
     {
       code2 = TREE_CODE (arg3);
@@ -3327,13 +3341,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
   else
     fnname = ansi_opname (code);
 
-  if (TREE_CODE (arg1) == OFFSET_REF)
-    arg1 = resolve_offset_ref (arg1);
-  arg1 = convert_from_reference (arg1);
-  if (CLASS_TYPE_P (TREE_TYPE (arg1))
-      && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg1)))
-    /* Make sure the template type is instantiated now.  */
-    instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)));
+  arg1 = prep_operand (arg1);
   
   switch (code)
     {
@@ -3351,24 +3359,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
       break;
     }
 
-  if (arg2)
-    {
-      if (TREE_CODE (arg2) == OFFSET_REF)
-       arg2 = resolve_offset_ref (arg2);
-      arg2 = convert_from_reference (arg2);
-      if (CLASS_TYPE_P (TREE_TYPE (arg2))
-         && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg2)))
-       instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg2)));
-    }
-  if (arg3)
-    {
-      if (TREE_CODE (arg3) == OFFSET_REF)
-       arg3 = resolve_offset_ref (arg3);
-      arg3 = convert_from_reference (arg3);
-      if (CLASS_TYPE_P (TREE_TYPE (arg3))
-         && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg3)))
-       instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg3)));
-    }
+  arg2 = prep_operand (arg2);
+  arg3 = prep_operand (arg3);
   
   if (code == COND_EXPR)
     {
@@ -3553,7 +3545,6 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
 
   if (TREE_CODE (cand->fn) == FUNCTION_DECL)
     {
-      extern int warn_synth;
       if (warn_synth
          && fnname == ansi_assopname (NOP_EXPR)
          && DECL_ARTIFICIAL (cand->fn)
index 6cdcb9a..378c637 100644 (file)
@@ -5758,7 +5758,7 @@ init_class_processing (void)
    that name becomes `error_mark_node'.  */
 
 void
-pushclass (tree type, int modify)
+pushclass (tree type, bool modify)
 {
   type = TYPE_MAIN_VARIANT (type);
 
@@ -5880,10 +5880,11 @@ int
 currently_open_class (tree t)
 {
   int i;
-  if (t == current_class_type)
+  if (current_class_type && same_type_p (t, current_class_type))
     return 1;
   for (i = 1; i < current_class_depth; ++i)
-    if (current_class_stack [i].type == t)
+    if (current_class_stack[i].type
+       && same_type_p (current_class_stack [i].type, t))
       return 1;
   return 0;
 }
@@ -5912,14 +5913,13 @@ currently_open_derived_class (tree t)
 }
 
 /* When entering a class scope, all enclosing class scopes' names with
-   static meaning (static variables, static functions, types and enumerators)
-   have to be visible.  This recursive function calls pushclass for all
-   enclosing class contexts until global or a local scope is reached.
-   TYPE is the enclosed class and MODIFY is equivalent with the pushclass
-   formal of the same name.  */
+   static meaning (static variables, static functions, types and
+   enumerators) have to be visible.  This recursive function calls
+   pushclass for all enclosing class contexts until global or a local
+   scope is reached.  TYPE is the enclosed class.  */
 
 void
-push_nested_class (tree type, int modify)
+push_nested_class (tree type)
 {
   tree context;
 
@@ -5935,8 +5935,8 @@ push_nested_class (tree type, int modify)
   context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
 
   if (context && CLASS_TYPE_P (context))
-    push_nested_class (context, 2);
-  pushclass (type, modify);
+    push_nested_class (context);
+  pushclass (type, true);
 }
 
 /* Undoes a push_nested_class call.  */
index fa73d67..e8d8acf 100644 (file)
@@ -2477,6 +2477,10 @@ struct lang_decl GTY(())
   (TREE_CODE (TYPE) == BOOLEAN_TYPE            \
    || TREE_CODE (TYPE) == INTEGER_TYPE)
 
+/* Returns true if TYPE is an integral or enumeration name.  */
+#define INTEGRAL_OR_ENUMERATION_TYPE_P(TYPE) \
+  (CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == ENUMERAL_TYPE)
+
 /* [basic.fundamental]
 
    Integral and floating types are collectively called arithmetic
@@ -3642,9 +3646,9 @@ extern void finish_struct_1                       (tree);
 extern int resolves_to_fixed_type_p            (tree, int *);
 extern void init_class_processing              (void);
 extern int is_empty_class                      (tree);
-extern void pushclass                          (tree, int);
+extern void pushclass                          (tree, bool);
 extern void popclass                           (void);
-extern void push_nested_class                  (tree, int);
+extern void push_nested_class                  (tree);
 extern void pop_nested_class                   (void);
 extern int current_lang_depth                  (void);
 extern void push_lang_context                  (tree);
@@ -3854,7 +3858,6 @@ extern void check_member_template (tree);
 extern tree grokfield (tree, tree, tree, tree, tree);
 extern tree grokbitfield (tree, tree, tree);
 extern tree groktypefield                      (tree, tree);
-extern tree grokoptypename (tree, tree, tree);
 extern void cplus_decl_attributes (tree *, tree, int);
 extern tree constructor_name_full              (tree);
 extern tree constructor_name (tree);
@@ -4009,7 +4012,6 @@ extern void cxx_init_options (void);
 /* in method.c */
 extern void init_method        (void);
 extern void set_mangled_name_for_decl (tree);
-extern tree build_opfncall (enum tree_code, int, tree, tree, tree);
 extern tree hack_identifier (tree, tree);
 extern tree make_thunk (tree, bool, tree, tree);
 extern void finish_thunk (tree);
@@ -4026,10 +4028,6 @@ extern bool maybe_clone_body (tree);
 /* in pt.c */
 extern void check_template_shadow              (tree);
 extern tree get_innermost_template_args         (tree, int);
-extern tree tsubst                             (tree, tree, tsubst_flags_t, tree);
-extern tree tsubst_expr                                (tree, tree, tsubst_flags_t, tree);
-extern tree tsubst_copy                                (tree, tree, tsubst_flags_t, tree);
-extern tree tsubst_copy_and_build              (tree, tree, tsubst_flags_t, tree);
 extern void maybe_begin_member_template_processing (tree);
 extern void maybe_end_member_template_processing (void);
 extern tree finish_member_template_decl         (tree);
@@ -4086,6 +4084,9 @@ extern bool dependent_type_p                    (tree);
 extern bool dependent_template_arg_p            (tree);
 extern bool dependent_template_p                (tree);
 extern bool type_dependent_expression_p         (tree);
+extern bool value_dependent_expression_p        (tree);
+extern tree resolve_typename_type               (tree, bool);
+extern tree resolve_typename_type_in_current_instantiation (tree);
 
 /* in repo.c */
 extern void repo_template_used (tree);
@@ -4226,7 +4227,6 @@ extern tree finish_unary_op_expr                (enum tree_code, tree);
 extern tree finish_compound_literal             (tree, tree);
 extern tree finish_fname                        (tree);
 extern int begin_function_definition            (tree, tree, tree);
-extern tree begin_constructor_declarator        (tree, tree);
 extern tree finish_declarator                   (tree, tree, tree, tree, int);
 extern void finish_translation_unit             (void);
 extern tree finish_template_type_parm           (tree, tree);
@@ -4238,7 +4238,6 @@ extern void finish_default_args                 (void);
 extern tree finish_member_class_template        (tree);
 extern void finish_template_decl                (tree);
 extern tree finish_template_type                (tree, tree, int);
-extern void enter_scope_of                      (tree);
 extern tree finish_base_specifier               (tree, tree);
 extern void finish_member_declaration           (tree);
 extern void check_multiple_declarators          (void);
index d2b7527..9078da6 100644 (file)
@@ -105,7 +105,6 @@ static tree record_builtin_java_type (const char *, int);
 static const char *tag_name (enum tag_types code);
 static void find_class_binding_level (void);
 static struct cp_binding_level *innermost_nonclass_level (void);
-static void warn_about_implicit_typename_lookup (tree, tree);
 static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
 static int walk_globals_r (tree, void*);
 static int walk_vtables_r (tree, void*);
@@ -5072,8 +5071,6 @@ finish_case_label (tree low_value, tree high_value)
     cond = TREE_VALUE (cond);
 
   r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
-  if (r == error_mark_node)
-    r = NULL_TREE;
 
   check_switch_goto (switch_stack->level);
 
@@ -5785,30 +5782,6 @@ qualify_lookup (tree val, int flags)
   return val;
 }
 
-/* Any other BINDING overrides an implicit TYPENAME.  Warn about
-   that.  */
-
-static void
-warn_about_implicit_typename_lookup (tree typename, tree binding)
-{
-  tree subtype = TREE_TYPE (TREE_TYPE (typename));
-  tree name = DECL_NAME (typename);
-
-  if (! (TREE_CODE (binding) == TEMPLATE_DECL
-        && CLASSTYPE_TEMPLATE_INFO (subtype)
-        && CLASSTYPE_TI_TEMPLATE (subtype) == binding)
-      && ! (TREE_CODE (binding) == TYPE_DECL
-           && same_type_p (TREE_TYPE (binding), subtype)))
-    {
-      warning ("lookup of `%D' finds `%#D'",
-                 name, binding);
-      warning ("  instead of `%D' from dependent base class",
-                 typename);
-      warning ("  (use `typename %T::%D' if that's what you meant)",
-                 constructor_name (current_class_type), name);
-    }
-}
-
 /* Look up NAME (an IDENTIFIER_NODE) in SCOPE (either a NAMESPACE_DECL
    or a class TYPE).  If IS_TYPE_P is TRUE, then ignore non-type
    bindings.  
@@ -7078,7 +7051,7 @@ start_decl (tree declarator,
 
   if (context && COMPLETE_TYPE_P (complete_type (context)))
     {
-      push_nested_class (context, 2);
+      push_nested_class (context);
 
       if (TREE_CODE (decl) == VAR_DECL)
        {
@@ -9086,9 +9059,11 @@ grokfndecl (tree ctype,
 
          /* Attempt to merge the declarations.  This can fail, in
             the case of some invalid specialization declarations.  */
+         push_scope (ctype);
          if (!duplicate_decls (decl, old_decl))
            error ("no `%#D' member function declared in class `%T'",
                      decl, ctype);
+         pop_scope (ctype);
          return old_decl;
        }
     }
@@ -11055,35 +11030,6 @@ grokdeclarator (tree declarator,
        attrlist = &returned_attrs;
     }
 
-  /* Resolve any TYPENAME_TYPEs from the decl-specifier-seq that refer
-     to ctype.  They couldn't be resolved earlier because we hadn't
-     pushed into the class yet.  
-
-     For example, consider:
-
-       template <typename T>
-       struct S {
-         typedef T X;
-         X f();
-       };
-
-       template <typename T>
-       typename S<T>::X f() {}
-
-       When parsing the decl-specifier-seq for the definition of `f',
-       we construct a TYPENAME_TYPE for `S<T>::X'.  By substituting
-       here, we resolve it to the correct type.  */
-  if (scope && CLASS_TYPE_P (scope)
-      && current_template_parms
-      && uses_template_parms (scope))
-    {
-      tree args = current_template_args ();
-      push_scope (scope);
-      type = tsubst (type, args, tf_error | tf_warning,
-                    NULL_TREE);
-      pop_scope (scope);
-    }
-
   /* Now TYPE has the actual type.  */
 
   /* Did array size calculations overflow?  */
@@ -13470,9 +13416,9 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
   /* Set up current_class_type, and enter the scope of the class, if
      appropriate.  */
   if (ctype)
-    push_nested_class (ctype, 1);
+    push_nested_class (ctype);
   else if (DECL_STATIC_FUNCTION_P (decl1))
-    push_nested_class (DECL_CONTEXT (decl1), 2);
+    push_nested_class (DECL_CONTEXT (decl1));
 
   /* Now that we have entered the scope of the class, we must restore
      the bindings for any template parameters surrounding DECL1, if it
index 4401dcc..63240dd 100644 (file)
@@ -423,8 +423,8 @@ grok_array_decl (tree array_expr, tree index_exp)
 
   /* If they have an `operator[]', use that.  */
   if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
-    return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
-                          array_expr, index_exp, NULL_TREE);
+    return build_new_op (ARRAY_REF, LOOKUP_NORMAL,
+                        array_expr, index_exp, NULL_TREE);
 
   /* Otherwise, create an ARRAY_REF for a pointer or array type.  It
      is a little-known fact that, if `a' is an array and `i' is an
@@ -685,6 +685,7 @@ check_classfn (tree ctype, tree function)
       bool is_conv_op;
       const char *format = NULL;
       
+      push_scope (ctype);
       for (fndecls = TREE_VEC_ELT (methods, ix);
           fndecls; fndecls = OVL_NEXT (fndecls))
        {
@@ -713,8 +714,11 @@ check_classfn (tree ctype, tree function)
              && (!DECL_TEMPLATE_SPECIALIZATION (function)
                  || (DECL_TI_TEMPLATE (function) 
                      == DECL_TI_TEMPLATE (fndecl))))
-           return fndecl;
+           break;
        }
+      pop_scope (ctype);
+      if (fndecls)
+       return OVL_CURRENT (fndecls);
       error ("prototype for `%#D' does not match any in class `%T'",
             function, ctype);
       is_conv_op = DECL_CONV_FN_P (fndecl);
@@ -1071,30 +1075,6 @@ grokbitfield (tree declarator, tree declspecs, tree width)
   return value;
 }
 
-/* Convert a conversion operator name to an identifier. SCOPE is the
-   scope of the conversion operator, if explicit.  */
-
-tree
-grokoptypename (tree declspecs, tree declarator, tree scope)
-{
-  tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL);
-
-  /* Resolve any TYPENAME_TYPEs that refer to SCOPE, before mangling
-     the name, so that we mangle the right thing.  */
-  if (scope && current_template_parms
-      && uses_template_parms (t)
-      && uses_template_parms (scope))
-    {
-      tree args = current_template_args ();
-      
-      push_scope (scope);
-      t = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
-      pop_scope (scope);
-    }
-  
-  return mangle_conv_op_name_for_type (t);
-}
-
 /* When a function is declared with an initializer,
    do the right thing.  Currently, there are two possibilities:
 
@@ -3749,7 +3729,7 @@ push_scope (tree t)
   if (TREE_CODE (t) == NAMESPACE_DECL)
     push_decl_namespace (t);
   else if CLASS_TYPE_P (t)
-    push_nested_class (t, 2);
+    push_nested_class (t);
 }
 
 /* Leave scope pushed by push_scope.  */
index d53943f..9fe4167 100644 (file)
@@ -454,6 +454,7 @@ dump_type (t, flags)
       break;
     }
     case TYPENAME_TYPE:
+      dump_qualifiers (t, after);
       output_add_string (scratch_buffer, "typename ");
       dump_typename (t, flags);
       break;
index 493f9b8..c2661e8 100644 (file)
@@ -1511,8 +1511,8 @@ build_member_call (type, name, parmlist)
          return error_mark_node;
        }
       if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
-       return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl,
-                              parmlist, NULL_TREE);
+       return build_new_op (CALL_EXPR, LOOKUP_NORMAL, decl,
+                            parmlist, NULL_TREE);
       return build_function_call (decl, parmlist);
     }
   else
index 883a81f..a60b75f 100644 (file)
@@ -85,36 +85,6 @@ set_mangled_name_for_decl (tree decl)
 }
 
 \f
-/* Given a tree_code CODE, and some arguments (at least one),
-   attempt to use an overloaded operator on the arguments.
-
-   For unary operators, only the first argument need be checked.
-   For binary operators, both arguments may need to be checked.
-
-   Member functions can convert class references to class pointers,
-   for one-level deep indirection.  More than that is not supported.
-   Operators [](), ()(), and ->() must be member functions.
-
-   We call function call building calls with LOOKUP_COMPLAIN if they
-   are our only hope.  This is true when we see a vanilla operator
-   applied to something of aggregate type.  If this fails, we are free
-   to return `error_mark_node', because we will have reported the
-   error.
-
-   Operators NEW and DELETE overload in funny ways: operator new takes
-   a single `size' parameter, and operator delete takes a pointer to the
-   storage being deleted.  When overloading these operators, success is
-   assumed.  If there is a failure, report an error message and return
-   `error_mark_node'.  */
-
-/* NOSTRICT */
-tree
-build_opfncall (enum tree_code code, int flags,
-                tree xarg1, tree xarg2, tree arg3)
-{
-  return build_new_op (code, flags, xarg1, xarg2, arg3);
-}
-\f
 /* This function takes an identifier, ID, and attempts to figure out what
    it means. There are a number of possible scenarios, presented in increasing
    order of hair:
index da9a92f..fab1ef4 100644 (file)
@@ -1275,9 +1275,18 @@ typedef struct cp_parser GTY(())
   
   /* TRUE if we are parsing an integral constant-expression.  See
      [expr.const] for a precise definition.  */
-  /* FIXME: Need to implement code that checks this flag.  */
   bool constant_expression_p;
 
+  /* TRUE if we are parsing an integral constant-expression -- but a
+     non-constant expression should be permitted as well.  This flag
+     is used when parsing an array bound so that GNU variable-length
+     arrays are tolerated.  */
+  bool allow_non_constant_expression_p;
+
+  /* TRUE if ALLOW_NON_CONSTANT_EXPRESSION_P is TRUE and something has
+     been seen that makes the expression non-constant.  */
+  bool non_constant_expression_p;
+
   /* TRUE if local variable names and `this' are forbidden in the
      current context.  */
   bool local_variables_forbidden_p;
@@ -1422,7 +1431,7 @@ static enum tree_code cp_parser_assignment_operator_opt
 static tree cp_parser_expression
   (cp_parser *);
 static tree cp_parser_constant_expression
-  (cp_parser *);
+  (cp_parser *, bool, bool *);
 
 /* Statements [gram.stmt.stmt]  */
 
@@ -1658,8 +1667,6 @@ static tree cp_parser_lookup_name
   (cp_parser *, tree, bool, bool, bool, bool);
 static tree cp_parser_lookup_name_simple
   (cp_parser *, tree);
-static tree cp_parser_resolve_typename_type
-  (cp_parser *, tree);
 static tree cp_parser_maybe_treat_template_as_class
   (tree, bool);
 static bool cp_parser_check_declarator_template_parameters
@@ -1728,6 +1735,10 @@ static bool cp_parser_simulate_error
   (cp_parser *);
 static void cp_parser_check_type_definition
   (cp_parser *);
+static tree cp_parser_non_constant_expression
+  (const char *);
+static tree cp_parser_non_constant_id_expression
+  (tree);
 static bool cp_parser_diagnose_invalid_type_name
   (cp_parser *);
 static bool cp_parser_skip_to_closing_parenthesis
@@ -1875,6 +1886,26 @@ cp_parser_check_type_definition (cp_parser* parser)
     error ("%s", parser->type_definition_forbidden_message);
 }
 
+/* Issue an eror message about the fact that THING appeared in a
+   constant-expression.  Returns ERROR_MARK_NODE.  */
+
+static tree
+cp_parser_non_constant_expression (const char *thing)
+{
+  error ("%s cannot appear in a constant-expression", thing);
+  return error_mark_node;
+}
+
+/* Issue an eror message about the fact that DECL appeared in a
+   constant-expression.  Returns ERROR_MARK_NODE.  */
+
+static tree
+cp_parser_non_constant_id_expression (tree decl)
+{
+  error ("`%D' cannot appear in a constant-expression", decl);
+  return error_mark_node;
+}
+
 /* Check for a common situation where a type-name should be present,
    but is not, and issue a sensible error message.  Returns true if an
    invalid type-name was detected.  */
@@ -2182,6 +2213,8 @@ cp_parser_new (void)
   
   /* We are not parsing a constant-expression.  */
   parser->constant_expression_p = false;
+  parser->allow_non_constant_expression_p = false;
+  parser->non_constant_expression_p = false;
 
   /* Local variable names are not forbidden.  */
   parser->local_variables_forbidden_p = false;
@@ -2395,6 +2428,13 @@ cp_parser_primary_expression (cp_parser *parser,
              error ("`this' may not be used in this context");
              return error_mark_node;
            }
+         /* Pointers cannot appear in constant-expressions.  */
+         if (parser->constant_expression_p)
+           {
+             if (!parser->allow_non_constant_expression_p)
+               return cp_parser_non_constant_expression ("`this'");
+             parser->non_constant_expression_p = true;
+           }
          return finish_this_expr ();
 
          /* The `operator' keyword can be the beginning of an
@@ -2434,7 +2474,14 @@ cp_parser_primary_expression (cp_parser *parser,
            type = cp_parser_type_id (parser);
            /* Look for the closing `)'.  */
            cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-
+           /* Using `va_arg' in a constant-expression is not
+              allowed.  */
+           if (parser->constant_expression_p)
+             {
+               if (!parser->allow_non_constant_expression_p)
+                 return cp_parser_non_constant_expression ("`va_arg'");
+               parser->non_constant_expression_p = true;
+             }
            return build_x_va_arg (expression, type);
          }
 
@@ -2481,6 +2528,11 @@ cp_parser_primary_expression (cp_parser *parser,
              {
                if (TYPE_P (TREE_OPERAND (decl, 0)))
                  *qualifying_class = TREE_OPERAND (decl, 0);
+               /* Since this name was dependent, the expression isn't
+                  constant -- yet.  No error is issued because it
+                  might be constant when things are instantiated.  */
+               if (parser->constant_expression_p)
+                 parser->non_constant_expression_p = true;
                return decl;
              }
            /* Check to see if DECL is a local variable in a context
@@ -2704,6 +2756,11 @@ cp_parser_primary_expression (cp_parser *parser,
                  {
                    if (TYPE_P (parser->scope))
                      *qualifying_class = parser->scope;
+                   /* Since this name was dependent, the expression isn't
+                      constant -- yet.  No error is issued because it
+                      might be constant when things are instantiated.  */
+                   if (parser->constant_expression_p)
+                     parser->non_constant_expression_p = true;
                    return build_nt (SCOPE_REF, 
                                     parser->scope, 
                                     id_expression);
@@ -2712,10 +2769,36 @@ cp_parser_primary_expression (cp_parser *parser,
                   we need.  */
                if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
                  return id_expression;
+               /* Since this name was dependent, the expression isn't
+                  constant -- yet.  No error is issued because it
+                  might be constant when things are instantiated.  */
+               if (parser->constant_expression_p)
+                 parser->non_constant_expression_p = true;
                /* Create a LOOKUP_EXPR for other unqualified names.  */
                return build_min_nt (LOOKUP_EXPR, id_expression);
              }
 
+           /* Only certain kinds of names are allowed in constant
+              expression.  Enumerators have already been handled
+              above.  */
+           if (parser->constant_expression_p
+               /* Non-type template parameters of integral or
+                  enumeration type.  */
+               && !(TREE_CODE (decl) == TEMPLATE_PARM_INDEX
+                    && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
+               /* Const variables or static data members of integral
+                  or enumeration types initialized with constant
+                  expressions.  */
+               && !(TREE_CODE (decl) == VAR_DECL
+                    && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
+                    && DECL_INITIAL (decl)
+                    && TREE_CONSTANT (DECL_INITIAL (decl))))
+             {
+               if (!parser->allow_non_constant_expression_p)
+                 return cp_parser_non_constant_id_expression (decl);
+               parser->non_constant_expression_p = true;
+             }
+
            if (parser->scope)
              {
                decl = (adjust_result_of_qualified_name_lookup 
@@ -3520,6 +3603,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
        expression = cp_parser_expression (parser);
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
+       /* Only type conversions to integral or enumeration types
+          can be used in constant-expressions.  */
+       if (parser->constant_expression_p
+           && !dependent_type_p (type)
+           && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+         {
+           if (!parser->allow_non_constant_expression_p)
+             return (cp_parser_non_constant_expression 
+                     ("a cast to a type other than an integral or "
+                      "enumeration type"));
+           parser->non_constant_expression_p = true;
+         }
+
        switch (keyword)
          {
          case RID_DYNCAST:
@@ -3645,32 +3741,32 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
 
        /* If the functional-cast didn't work out, try a
           compound-literal.  */
-       if (cp_parser_allow_gnu_extensions_p (parser))
+       if (cp_parser_allow_gnu_extensions_p (parser)
+           && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
          {
            tree initializer_list = NULL_TREE;
 
            cp_parser_parse_tentatively (parser);
-           /* Look for the `('.  */
-           if (cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+           /* Consume the `('.  */
+           cp_lexer_consume_token (parser->lexer);
+           /* Parse the type.  */
+           type = cp_parser_type_id (parser);
+           /* Look for the `)'.  */
+           cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+           /* Look for the `{'.  */
+           cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+           /* If things aren't going well, there's no need to
+              keep going.  */
+           if (!cp_parser_error_occurred (parser))
              {
-               type = cp_parser_type_id (parser);
-               /* Look for the `)'.  */
-               cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-               /* Look for the `{'.  */
-               cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
-               /* If things aren't going well, there's no need to
-                  keep going.  */
-               if (!cp_parser_error_occurred (parser))
-                 {
-                   /* Parse the initializer-list.  */
-                   initializer_list 
-                     = cp_parser_initializer_list (parser);
-                   /* Allow a trailing `,'.  */
-                   if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-                     cp_lexer_consume_token (parser->lexer);
-                   /* Look for the final `}'.  */
-                   cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
-                 }
+               /* Parse the initializer-list.  */
+               initializer_list 
+                 = cp_parser_initializer_list (parser);
+               /* Allow a trailing `,'.  */
+               if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+                 cp_lexer_consume_token (parser->lexer);
+               /* Look for the final `}'.  */
+               cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
              }
            /* If that worked, we're definitely looking at a
               compound-literal expression.  */
@@ -3806,6 +3902,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
              args = NULL_TREE;
            /* Look for the closing `)'.  */
            cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+           /* Function calls are not permitted in
+              constant-expressions.  */
+           if (parser->constant_expression_p)
+             {
+               if (!parser->allow_non_constant_expression_p)
+                 return cp_parser_non_constant_expression ("a function call");
+               parser->non_constant_expression_p = true;
+             }
 
            if (idk == CP_PARSER_ID_KIND_UNQUALIFIED
                && (is_overloaded_fn (postfix_expression)
@@ -4029,6 +4133,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
          /* postfix-expression ++  */
          /* Consume the `++' token.  */
          cp_lexer_consume_token (parser->lexer);
+         /* Increments may not appear in constant-expressions.  */
+         if (parser->constant_expression_p)
+           {
+             if (!parser->allow_non_constant_expression_p)
+               return cp_parser_non_constant_expression ("an increment");
+             parser->non_constant_expression_p = true;
+           }
          /* Generate a reprsentation for the complete expression.  */
          postfix_expression 
            = finish_increment_expr (postfix_expression, 
@@ -4040,6 +4151,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
          /* postfix-expression -- */
          /* Consume the `--' token.  */
          cp_lexer_consume_token (parser->lexer);
+         /* Decrements may not appear in constant-expressions.  */
+         if (parser->constant_expression_p)
+           {
+             if (!parser->allow_non_constant_expression_p)
+               return cp_parser_non_constant_expression ("a decrement");
+             parser->non_constant_expression_p = true;
+           }
          /* Generate a reprsentation for the complete expression.  */
          postfix_expression 
            = finish_increment_expr (postfix_expression, 
@@ -4341,11 +4459,20 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
        case ADDR_EXPR:
          return build_x_unary_op (ADDR_EXPR, cast_expression);
          
+       case PREINCREMENT_EXPR:
+       case PREDECREMENT_EXPR:
+         if (parser->constant_expression_p)
+           {
+             if (!parser->allow_non_constant_expression_p)
+               return cp_parser_non_constant_expression (PREINCREMENT_EXPR
+                                                         ? "an increment"
+                                                         : "a decrement");
+             parser->non_constant_expression_p = true;
+           }
+         /* Fall through.  */
        case CONVERT_EXPR:
        case NEGATE_EXPR:
        case TRUTH_NOT_EXPR:
-       case PREINCREMENT_EXPR:
-       case PREDECREMENT_EXPR:
          return finish_unary_op_expr (unary_operator, cast_expression);
 
        case BIT_NOT_EXPR:
@@ -4597,7 +4724,10 @@ cp_parser_direct_new_declarator (cp_parser* parser)
        }
       /* But all the other expressions must be.  */
       else
-       expression = cp_parser_constant_expression (parser);
+       expression 
+         = cp_parser_constant_expression (parser, 
+                                          /*allow_non_constant=*/false,
+                                          NULL);
       /* Look for the closing `]'.  */
       cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
 
@@ -4766,7 +4896,19 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
              && !VOID_TYPE_P (type) 
              && current_lang_name != lang_name_c)
            warning ("use of old-style cast");
-         
+
+         /* Only type conversions to integral or enumeration types
+            can be used in constant-expressions.  */
+         if (parser->constant_expression_p
+             && !dependent_type_p (type)
+             && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+           {
+             if (!parser->allow_non_constant_expression_p)
+               return (cp_parser_non_constant_expression 
+                       ("a casts to a type other than an integral or "
+                        "enumeration type"));
+             parser->non_constant_expression_p = true;
+           }
          /* Perform the cast.  */
          expr = build_c_cast (type, expr);
          return expr;
@@ -5176,6 +5318,14 @@ cp_parser_assignment_expression (cp_parser* parser)
 
              /* Parse the right-hand side of the assignment.  */
              rhs = cp_parser_assignment_expression (parser);
+             /* An assignment may not appear in a
+                constant-expression.  */
+             if (parser->constant_expression_p)
+               {
+                 if (!parser->allow_non_constant_expression_p)
+                   return cp_parser_non_constant_expression ("an assignment");
+                 parser->non_constant_expression_p = true;
+               }
              /* Build the asignment expression.  */
              expr = build_x_modify_expr (expr, 
                                          assignment_operator, 
@@ -5334,7 +5484,16 @@ cp_parser_expression (cp_parser* parser)
      necessary.  We built up the list in reverse order, so we must
      straighten it out here.  */
   if (saw_comma_p)
-    expression = build_x_compound_expr (nreverse (expression));
+    {
+      /* A comma operator cannot appear in a constant-expression.  */
+      if (parser->constant_expression_p)
+       {
+         if (!parser->allow_non_constant_expression_p)
+           return cp_parser_non_constant_expression ("a comma operator");
+         parser->non_constant_expression_p = true;
+       }
+      expression = build_x_compound_expr (nreverse (expression));
+    }
 
   return expression;
 }
@@ -5342,12 +5501,20 @@ cp_parser_expression (cp_parser* parser)
 /* Parse a constant-expression. 
 
    constant-expression:
-     conditional-expression  */
+     conditional-expression  
+
+  If ALLOW_NON_CONSTANT_P a non-constant expression is silently
+  accepted.  In that case *NON_CONSTANT_P is set to TRUE.  If
+  ALLOW_NON_CONSTANT_P is false, NON_CONSTANT_P should be NULL.  */
 
 static tree
-cp_parser_constant_expression (cp_parser* parser)
+cp_parser_constant_expression (cp_parser* parser, 
+                              bool allow_non_constant_p,
+                              bool *non_constant_p)
 {
   bool saved_constant_expression_p;
+  bool saved_allow_non_constant_expression_p;
+  bool saved_non_constant_expression_p;
   tree expression;
 
   /* It might seem that we could simply parse the
@@ -5367,14 +5534,24 @@ cp_parser_constant_expression (cp_parser* parser)
      constant-expression.  However, GCC's constant-folding machinery
      will fold this operation to an INTEGER_CST for `3'.  */
 
-  /* Save the old setting of CONSTANT_EXPRESSION_P.  */
+  /* Save the old settings.  */
   saved_constant_expression_p = parser->constant_expression_p;
+  saved_allow_non_constant_expression_p 
+    = parser->allow_non_constant_expression_p;
+  saved_non_constant_expression_p = parser->non_constant_expression_p;
   /* We are now parsing a constant-expression.  */
   parser->constant_expression_p = true;
+  parser->allow_non_constant_expression_p = allow_non_constant_p;
+  parser->non_constant_expression_p = false;
   /* Parse the conditional-expression.  */
   expression = cp_parser_conditional_expression (parser);
-  /* Restore the old setting of CONSTANT_EXPRESSION_P.  */
+  /* Restore the old settings.  */
   parser->constant_expression_p = saved_constant_expression_p;
+  parser->allow_non_constant_expression_p 
+    = saved_allow_non_constant_expression_p;
+  if (allow_non_constant_p)
+    *non_constant_p = parser->non_constant_expression_p;
+  parser->non_constant_expression_p = saved_non_constant_expression_p;
 
   return expression;
 }
@@ -5517,7 +5694,9 @@ cp_parser_labeled_statement (cp_parser* parser)
        /* Consume the `case' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Parse the constant-expression.  */
-       expr = cp_parser_constant_expression (parser);
+       expr = cp_parser_constant_expression (parser, 
+                                             /*allow_non_constant=*/false,
+                                             NULL);
        /* Create the label.  */
        statement = finish_case_label (expr, NULL_TREE);
       }
@@ -8875,7 +9054,9 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
       /* Consume the `=' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the value.  */
-      value = cp_parser_constant_expression (parser);
+      value = cp_parser_constant_expression (parser, 
+                                            /*allow_non_constant=*/false,
+                                            NULL);
     }
   else
     value = NULL_TREE;
@@ -9870,7 +10051,34 @@ cp_parser_direct_declarator (cp_parser* parser,
          /* If the next token is `]', then there is no
             constant-expression.  */
          if (token->type != CPP_CLOSE_SQUARE)
-           bounds = cp_parser_constant_expression (parser);
+           {
+             bool non_constant_p;
+
+             bounds 
+               = cp_parser_constant_expression (parser,
+                                                /*allow_non_constant=*/true,
+                                                &non_constant_p);
+             /* If we're in a template, but the constant-expression
+                isn't value dependent, simplify it.  We're supposed
+                to treat:
+
+                  template <typename T> void f(T[1 + 1]);
+                  template <typename T> void f(T[2]);
+                  
+                as two declarations of the same function, for
+                example.  */
+             if (processing_template_decl
+                 && !non_constant_p
+                 && !value_dependent_expression_p (bounds))
+               {
+                 HOST_WIDE_INT saved_processing_template_decl;
+
+                 saved_processing_template_decl = processing_template_decl;
+                 processing_template_decl = 0;
+                 bounds = build_expr_from_tree (bounds);
+                 processing_template_decl = saved_processing_template_decl;
+               }
+           }
          else
            bounds = NULL_TREE;
          /* Look for the closing `]'.  */
@@ -9924,11 +10132,14 @@ cp_parser_direct_declarator (cp_parser* parser,
                 is no harm in resolving the types here.  */
              if (TREE_CODE (scope) == TYPENAME_TYPE)
                {
+                 tree type;
+
                  /* Resolve the TYPENAME_TYPE.  */
-                 scope = cp_parser_resolve_typename_type (parser, scope);
+                 type = resolve_typename_type (scope,
+                                                /*only_current_p=*/false);
                  /* If that failed, the declarator is invalid.  */
-                 if (scope == error_mark_node)
-                   return error_mark_node;
+                 if (type != error_mark_node)
+                   scope = type;
                  /* Build a new DECLARATOR.  */
                  declarator = build_nt (SCOPE_REF, 
                                         scope,
@@ -11549,16 +11760,22 @@ cp_parser_class_head (cp_parser* parser,
       /* Given:
 
            template <typename T> struct S { struct T };
-           template <typename T> struct S::T { };
+           template <typename T> struct S<T>::T { };
 
         we will get a TYPENAME_TYPE when processing the definition of
         `S::T'.  We need to resolve it to the actual type before we
         try to define it.  */
       if (TREE_CODE (TREE_TYPE (type)) == TYPENAME_TYPE)
        {
-         type = cp_parser_resolve_typename_type (parser, TREE_TYPE (type));
-         if (type != error_mark_node)
-           type = TYPE_NAME (type);
+         class_type = resolve_typename_type (TREE_TYPE (type),
+                                             /*only_current_p=*/false);
+         if (class_type != error_mark_node)
+           type = TYPE_NAME (class_type);
+         else
+           {
+             cp_parser_error (parser, "could not resolve typename type");
+             type = error_mark_node;
+           }
        }
 
       maybe_process_partial_specialization (TREE_TYPE (type));
@@ -11889,7 +12106,10 @@ cp_parser_member_declaration (cp_parser* parser)
              /* Consume the `:' token.  */
              cp_lexer_consume_token (parser->lexer);
              /* Get the width of the bitfield.  */
-             width = cp_parser_constant_expression (parser);
+             width 
+               = cp_parser_constant_expression (parser,
+                                                /*allow_non_constant=*/false,
+                                                NULL);
 
              /* Look for attributes that apply to the bitfield.  */
              attributes = cp_parser_attributes_opt (parser);
@@ -12112,7 +12332,9 @@ cp_parser_constant_initializer (cp_parser* parser)
       return error_mark_node;
     }
 
-  return cp_parser_constant_expression (parser);
+  return cp_parser_constant_expression (parser, 
+                                       /*allow_non_constant=*/false,
+                                       NULL);
 }
 
 /* Derived classes [gram.class.derived] */
@@ -13148,58 +13370,6 @@ cp_parser_lookup_name_simple (cp_parser* parser, tree name)
                                /*check_dependency=*/true);
 }
 
-/* TYPE is a TYPENAME_TYPE.  Returns the ordinary TYPE to which the
-   TYPENAME_TYPE corresponds.  Note that this function peers inside
-   uninstantiated templates and therefore should be used only in
-   extremely limited situations.  */
-
-static tree
-cp_parser_resolve_typename_type (cp_parser* parser, tree type)
-{
-  tree scope;
-  tree name;
-  tree decl;
-
-  my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE,
-                     20010702);
-
-  scope = TYPE_CONTEXT (type);
-  name = TYPE_IDENTIFIER (type);
-
-  /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
-     it first before we can figure out what NAME refers to.  */
-  if (TREE_CODE (scope) == TYPENAME_TYPE)
-    scope = cp_parser_resolve_typename_type (parser, scope);
-  /* If we don't know what SCOPE refers to, then we cannot resolve the
-     TYPENAME_TYPE.  */
-  if (scope == error_mark_node || TREE_CODE (scope) == TYPENAME_TYPE)
-    return error_mark_node;
-  /* If the SCOPE is a template type parameter, we have no way of
-     resolving the name.  */
-  if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM)
-    return type;
-  /* Enter the SCOPE so that name lookup will be resolved as if we
-     were in the class definition.  In particular, SCOPE will no
-     longer be considered a dependent type.  */
-  push_scope (scope);
-  /* Look up the declaration.  */
-  decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/1);
-  /* If all went well, we got a TYPE_DECL for a non-typename.  */
-  if (!decl 
-      || TREE_CODE (decl) != TYPE_DECL 
-      || TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
-    {
-      cp_parser_error (parser, "could not resolve typename type");
-      type = error_mark_node;
-    }
-  else
-    type = TREE_TYPE (decl);
-  /* Leave the SCOPE.  */
-  pop_scope (scope);
-
-  return type;
-}
-
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
    the current context, return the TYPE_DECL.  If TAG_NAME_P is
    true, the DECL indicates the class being defined in a class-head,
@@ -13547,7 +13717,15 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
            {
              type = TREE_TYPE (type_decl);
              if (TREE_CODE (type) == TYPENAME_TYPE)
-               type = cp_parser_resolve_typename_type (parser, type);
+               {
+                 type = resolve_typename_type (type, 
+                                               /*only_current_p=*/false);
+                 if (type == error_mark_node)
+                   {
+                     cp_parser_abort_tentative_parse (parser);
+                     return false;
+                   }
+               }
              push_scope (type);
            }
          /* Look for the type-specifier.  */
@@ -13978,7 +14156,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       parser->local_variables_forbidden_p = true;
        /* Parse the assignment-expression.  */
       if (DECL_CONTEXT (fn))
-       push_nested_class (DECL_CONTEXT (fn), 1);
+       push_nested_class (DECL_CONTEXT (fn));
       TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
       if (DECL_CONTEXT (fn))
        pop_nested_class ();
index b3b8106..2429f7f 100644 (file)
@@ -171,8 +171,11 @@ static void copy_default_args_to_explicit_spec PARAMS ((tree));
 static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
 static int eq_local_specializations (const void *, const void *);
 static tree template_for_substitution (tree);
-static bool value_dependent_expression_p (tree);
 static bool dependent_template_id_p (tree, tree);
+static tree tsubst (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_expr        (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_copy        (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -215,7 +218,7 @@ push_access_scope_real (t, args, context)
   if (!context)
     context = DECL_CONTEXT (t);
   if (context && TYPE_P (context))
-    push_nested_class (context, 2);
+    push_nested_class (context);
   else
     push_to_top_level ();
     
@@ -5043,7 +5046,7 @@ tsubst_friend_class (friend_tmpl, args)
       if (TREE_CODE (context) == NAMESPACE_DECL)
        push_nested_namespace (context);
       else
-       push_nested_class (tsubst (context, args, tf_none, NULL_TREE), 2);
+       push_nested_class (tsubst (context, args, tf_none, NULL_TREE)); 
     }
 
   /* First, we look for a class template.  */
@@ -5328,7 +5331,7 @@ instantiate_class_template (type)
      correctly.  This is precisely analogous to what we do in
      begin_class_definition when defining an ordinary non-template
      class.  */
-  pushclass (type, 1);
+  pushclass (type, true);
 
   /* Now members are processed in the order of declaration.  */
   for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member))
@@ -6467,7 +6470,7 @@ tsubst_call_declarator_parms (parms, args, complain, in_decl)
    This function is used for dealing with types, decls and the like;
    for expressions, use tsubst_expr or tsubst_copy.  */
 
-tree
+static tree
 tsubst (t, args, complain, in_decl)
      tree t, args;
      tsubst_flags_t complain;
@@ -7103,7 +7106,7 @@ tsubst (t, args, complain, in_decl)
    template parms; to finish processing the resultant expression, use
    tsubst_expr.  */
 
-tree
+static tree
 tsubst_copy (t, args, complain, in_decl)
      tree t, args;
      tsubst_flags_t complain;
@@ -7505,7 +7508,7 @@ tsubst_copy (t, args, complain, in_decl)
 /* Like tsubst_copy for expressions, etc. but also does semantic
    processing.  */
 
-tree
+static tree
 tsubst_expr (t, args, complain, in_decl)
      tree t, args;
      tsubst_flags_t complain;
@@ -7832,7 +7835,7 @@ tsubst_expr (t, args, complain, in_decl)
 /* Like tsubst but deals with expressions and performs semantic
    analysis.  */
 
-tree
+static tree
 tsubst_copy_and_build (t, args, complain, in_decl)
      tree t, args;
      tsubst_flags_t complain;
@@ -11314,15 +11317,16 @@ dependent_type_p (type)
 
 /* Returns TRUE if the EXPRESSION is value-dependent.  */
 
-static bool
+bool
 value_dependent_expression_p (tree expression)
 {
   if (!processing_template_decl)
     return false;
 
   /* A name declared with a dependent type.  */
-  if (DECL_P (expression)
-      && dependent_type_p (TREE_TYPE (expression)))
+  if (TREE_CODE (expression) == LOOKUP_EXPR
+      || (DECL_P (expression)
+         && dependent_type_p (TREE_TYPE (expression))))
     return true;
   /* A non-type template parameter.  */
   if ((TREE_CODE (expression) == CONST_DECL
@@ -11370,11 +11374,14 @@ value_dependent_expression_p (tree expression)
        case 'e':
          {
            int i;
-           for (i = 0; 
-                i < TREE_CODE_LENGTH (TREE_CODE (expression));
-                ++i)
-             if (value_dependent_expression_p
-                 (TREE_OPERAND (expression, i)))
+           for (i = 0; i < first_rtl_op (TREE_CODE (expression)); ++i)
+             /* In some cases, some of the operands may be missing.
+                (For example, in the case of PREDECREMENT_EXPR, the
+                amount to increment by may be missing.)  That doesn't
+                make the expression dependent.  */
+             if (TREE_OPERAND (expression, i)
+                 && (value_dependent_expression_p
+                     (TREE_OPERAND (expression, i))))
                return true;
            return false;
          }
@@ -11478,4 +11485,88 @@ dependent_template_p (tree tmpl)
   return false;
 }
 
+/* TYPE is a TYPENAME_TYPE.  Returns the ordinary TYPE to which the
+   TYPENAME_TYPE corresponds.  Returns ERROR_MARK_NODE if no such TYPE
+   can be found.  Note that this function peers inside uninstantiated
+   templates and therefore should be used only in extremely limited
+   situations.  */
+
+tree
+resolve_typename_type (tree type, bool only_current_p)
+{
+  tree scope;
+  tree name;
+  tree decl;
+  int quals;
+
+  my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE,
+                     20010702);
+
+  scope = TYPE_CONTEXT (type);
+  name = TYPE_IDENTIFIER (type);
+
+  /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
+     it first before we can figure out what NAME refers to.  */
+  if (TREE_CODE (scope) == TYPENAME_TYPE)
+    scope = resolve_typename_type (scope, only_current_p);
+  /* If we don't know what SCOPE refers to, then we cannot resolve the
+     TYPENAME_TYPE.  */
+  if (scope == error_mark_node || TREE_CODE (scope) == TYPENAME_TYPE)
+    return error_mark_node;
+  /* If the SCOPE is a template type parameter, we have no way of
+     resolving the name.  */
+  if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM)
+    return type;
+  /* If the SCOPE is not the current instantiation, there's no reason
+     to look inside it.  */
+  if (only_current_p && !currently_open_class (scope))
+    return error_mark_node;
+  /* Enter the SCOPE so that name lookup will be resolved as if we
+     were in the class definition.  In particular, SCOPE will no
+     longer be considered a dependent type.  */
+  push_scope (scope);
+  /* Look up the declaration.  */
+  decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/1);
+  /* Obtain the set of qualifiers applied to the TYPE.  */
+  quals = cp_type_quals (type);
+  /* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
+     find a TEMPLATE_DECL.  Otherwise, we want to find a TYPE_DECL.  */
+  if (!decl)
+    type = error_mark_node;
+  else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == IDENTIFIER_NODE
+          && TREE_CODE (decl) == TYPE_DECL)
+    type = TREE_TYPE (decl);
+  else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_EXPR
+          && DECL_CLASS_TEMPLATE_P (decl))
+    {
+      tree tmpl;
+      tree args;
+      /* Obtain the template and the arguments.  */
+      tmpl = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 0);
+      args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1);
+      /* Instantiate the template.  */
+      type = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
+                                   /*entering_scope=*/0, 
+                                   tf_error);
+    }
+  else
+    type = error_mark_node;
+  /* Qualify the resulting type.  */
+  if (type != error_mark_node && quals)
+    type = cp_build_qualified_type (type, quals);
+  /* Leave the SCOPE.  */
+  pop_scope (scope);
+
+  return type;
+}
+
+tree
+resolve_typename_type_in_current_instantiation (tree type)
+{
+  tree t;
+
+  t = resolve_typename_type (type, /*only_current_p=*/true);
+  return (t != error_mark_node) ? t : type;
+}
+
 #include "gt-cp-pt.h"
index fb6f25d..9c0b28b 100644 (file)
@@ -1434,7 +1434,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
       /* If the "function" is really an object of class type, it might
         have an overloaded `operator ()'.  */
       tree result;
-      result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
+      result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
       if (result)
        return result;
     }
@@ -1665,19 +1665,6 @@ begin_function_definition (decl_specs, attributes, declarator)
   return 1;
 }
 
-/* Begin a constructor declarator of the form `SCOPE::NAME'.  Returns
-   a SCOPE_REF.  */
-
-tree 
-begin_constructor_declarator (scope, name)
-     tree scope;
-     tree name;
-{
-  tree result = build_nt (SCOPE_REF, scope, name);
-  enter_scope_of (result);
-  return result;
-}
-
 /* Finish an init-declarator.  Returns a DECL.  */
 
 tree
@@ -1831,7 +1818,7 @@ begin_class_definition (t)
       pushtag (TYPE_IDENTIFIER (t), t, 0);
     }
   maybe_process_partial_specialization (t);
-  pushclass (t, 1);
+  pushclass (t, true);
   TYPE_BEING_DEFINED (t) = 1;
   TYPE_PACKED (t) = flag_pack_struct;
   /* Reset the interface data, at the earliest possible
@@ -2044,34 +2031,6 @@ finish_template_type (name, args, entering_scope)
   return decl;
 }
 
-/* SR is a SCOPE_REF node.  Enter the scope of SR, whether it is a
-   namespace scope or a class scope.  */
-
-void
-enter_scope_of (sr)
-     tree sr;
-{
-  tree scope = TREE_OPERAND (sr, 0);
-
-  if (TREE_CODE (scope) == NAMESPACE_DECL)
-    {
-      push_decl_namespace (scope);
-      TREE_COMPLEXITY (sr) = -1;
-    }
-  else if (scope != current_class_type)
-    {
-      if (TREE_CODE (scope) == TYPENAME_TYPE)
-       {
-         /* In a declarator for a template class member, the scope will
-            get here as an implicit typename, a TYPENAME_TYPE with a type.  */
-         scope = TREE_TYPE (scope);
-         TREE_OPERAND (sr, 0) = scope;
-       }
-      push_nested_class (scope, 3);
-      TREE_COMPLEXITY (sr) = current_class_depth;
-    }
-}
-
 /* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.
    Return a TREE_LIST containing the ACCESS_SPECIFIER and the
    BASE_CLASS, or NULL_TREE if an error occurred.  The
index 57d95ad..9d11262 100644 (file)
@@ -946,6 +946,13 @@ comptypes (t1, t2, strict)
   if (TYPE_PTRMEMFUNC_P (t2))
     t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
 
+  /* TYPENAME_TYPEs should be resolved if the qualifying scope is the
+     current instantiation.  */
+  if (TREE_CODE (t1) == TYPENAME_TYPE)
+    t1 = resolve_typename_type_in_current_instantiation (t1);
+  if (TREE_CODE (t2) == TYPENAME_TYPE)
+    t2 = resolve_typename_type_in_current_instantiation (t2);
+
   /* Different classes of types can't be compatible.  */
   if (TREE_CODE (t1) != TREE_CODE (t2))
     return 0;
@@ -2301,8 +2308,8 @@ build_x_indirect_ref (ptr, errorstring)
   if (processing_template_decl)
     return build_min_nt (INDIRECT_REF, ptr);
 
-  rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
-                        NULL_TREE);
+  rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
+                      NULL_TREE);
   if (rval)
     return rval;
   return build_indirect_ref (ptr, errorstring);
@@ -2973,6 +2980,183 @@ build_x_binary_op (code, arg1, arg2)
   return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
 }
 
+#if 0
+
+tree
+build_template_expr (enum tree_code code, tree op0, tree op1, tree op2)
+{
+  tree type;
+
+  /* If any of the operands is erroneous the result is erroneous too.  */
+  if (error_operand_p (op0)
+      || (op1 && error_operand_p (op1))
+      || (op2 && error_operand_p (op2)))
+    return error_mark_node;
+      
+  if (dependent_type_p (TREE_TYPE (op0))
+      || (op1 && dependent_type_p (TREE_TYPE (op1)))
+      || (op2 && dependent_type_p (TREE_TYPE (op2))))
+    /* If at least one operand has a dependent type, we cannot
+       determine the type of the expression until instantiation time.  */
+    type = NULL_TREE;
+  else
+    {
+      struct z_candidate *cand;
+      tree op0_type;
+      tree op1_type;
+      tree op2_type;
+
+      /* None of the operands is dependent, so we can compute the type
+        of the expression at this point.  We must compute the type so
+        that in things like:
+
+          template <int I>
+          void f() { S<sizeof(I + 3)> s; ... }
+
+        we can tell that the type of "s" is non-dependent.
+
+        If we're processing a template argument, we do not want to
+        actually change the operands in any way.  Adding conversions,
+        performing constant folding, etc., would all change mangled
+        names.  For example, in:
+        
+          template <int I>
+          void f(S<sizeof(3 + 4 + I)>);
+        
+        we need to determine that "3 + 4 + I" has type "int", without
+        actually turning the expression into "7 + I".  */
+      cand = find_overloaded_op (code, op0, op1, op2);
+      if (cand) 
+       /* If an overloaded operator was found, the expression will
+          have the type returned by the function.  */
+       type = non_reference (TREE_TYPE (cand->fn));
+      else
+       {
+         /* There is no overloaded operator so we can just use the
+            default rules for determining the type of the operand.  */
+         op0_type = TREE_TYPE (op0);
+         op1_type = op1 ? TREE_TYPE (op1) : NULL_TREE;
+         op2_type = op2 ? TREE_TYPE (op2) : NULL_TREE;
+         type = NULL_TREE;
+
+         switch (code)
+           {
+           case MODIFY_EXPR:
+             /* [expr.ass]
+
+                The result of the assignment operation is the value
+                stored in the left operand.  */
+             type = op0_type;
+             break;
+           case COMPONENT_REF:
+             /* Implement this case.  */
+             break;
+           case POSTINCREMENT_EXPR:
+           case POSTDECREMENT_EXPR:
+             /* [expr.post.incr]
+
+                The type of the result is the cv-unqualified version
+                of the type of the operand.  */
+             type = TYPE_MAIN_VARIANT (op0_type);
+             break;
+           case PREINCREMENT_EXPR:
+           case PREDECREMENT_EXPR:
+             /* [expr.pre.incr]
+
+                The value is the new value of the operand.  */
+             type = op0_type;
+             break;
+           case INDIRECT_REF:
+             /* [expr.unary.op]
+
+                If the type of the expression is "pointer to T", the
+                type of the result is "T".  */
+             type = TREE_TYPE (op0_type);
+             break;
+           case ADDR_EXPR:
+             /* [expr.unary.op]
+
+                If the type of the expression is "T", the type of the
+                result is "pointer to T".  */
+             /* FIXME: Handle the pointer-to-member case.  */
+             break;
+           case MEMBER_REF:
+             /* FIXME: Implement this case.  */
+             break;
+           case LSHIFT_EXPR:
+           case RSHIFT_EXPR:
+             /* [expr.shift]
+
+                The type of the result is that of the promoted left
+                operand.  */
+             break;
+           case PLUS_EXPR:
+           case MINUS_EXPR:
+             /* FIXME: Be careful of special pointer-arithmetic
+                cases.  */
+             /* Fall through. */
+           case MAX_EXPR:
+           case MIN_EXPR:
+             /* These are GNU extensions; the result type is computed
+                as it would be for other arithmetic operators.  */
+             /* Fall through. */
+           case BIT_AND_EXPR:
+           case BIT_XOR_EXPR:
+           case BIT_IOR_EXPR:
+           case MULT_EXPR:
+           case TRUNC_DIV_EXPR:
+           case TRUNC_MOD_EXPR:
+             /* [expr.bit.and], [expr.xor], [expr.or], [expr.mul]
+
+                The usual arithmetic conversions are performed on the
+                operands and determine the type of the result.  */
+             /* FIXME: Check that this is possible.  */
+             type = type_after_usual_arithmetic_conversions (t1, t2);
+             break;
+           case GT_EXPR:
+           case LT_EXPR:
+           case GE_EXPR:
+           case LE_EXPR:
+           case EQ_EXPR:
+           case NE_EXPR:
+             /* [expr.rel]
+
+                The type of the result is bool.  */
+             type = boolean_type_node;
+             break;
+           case TRUTH_ANDIF_EXPR:
+           case TRUTH_ORIF_EXPR:
+             /* [expr.log.and], [expr.log.org]
+                
+                The result is a bool.  */
+             type = boolean_type_node;
+             break;
+           case COND_EXPR:
+             /* FIXME: Handle special rules for conditioanl
+                expressions.  */
+             break;
+           case COMPOUND_EXPR:
+             type = op1_type;
+             break;
+           default:
+             abort ();
+           }
+         /* If the type of the expression could not be determined,
+            something is wrong.  */
+         if (!type)
+           abort ();
+         /* If the type is erroneous, the expression is erroneous
+            too.  */
+         if (type == error_mark_node)
+           return error_mark_node;
+       }
+    }
+  
+  return build_min (code, type, op0, op1, op2, NULL_TREE);
+}
+
+#endif
+
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
    This function differs from `build' in several ways:
@@ -4602,8 +4786,8 @@ build_x_compound_expr (list)
   if (rest == NULL_TREE)
     return build_compound_expr (list);
 
-  result = build_opfncall (COMPOUND_EXPR, LOOKUP_NORMAL,
-                          TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
+  result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL,
+                        TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
   if (result)
     return build_x_compound_expr (tree_cons (NULL_TREE, result,
                                                  TREE_CHAIN (rest)));
@@ -5235,8 +5419,8 @@ build_modify_expr (lhs, modifycode, rhs)
            /* Do the default thing */;
          else
            {
-             result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
-                                      lhs, rhs, make_node (NOP_EXPR));
+             result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
+                                    lhs, rhs, make_node (NOP_EXPR));
              if (result == NULL_TREE)
                return error_mark_node;
              return result;
@@ -5488,8 +5672,8 @@ build_x_modify_expr (lhs, modifycode, rhs)
 
   if (modifycode != NOP_EXPR)
     {
-      tree rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
-                                 make_node (modifycode));
+      tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
+                               make_node (modifycode));
       if (rval)
        return rval;
     }
index 0a5b4dc..c7dcb52 100644 (file)
@@ -1044,8 +1044,8 @@ build_x_arrow (datum)
 
   if (IS_AGGR_TYPE (type))
     {
-      while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval,
-                                    NULL_TREE, NULL_TREE)))
+      while ((rval = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, rval,
+                                  NULL_TREE, NULL_TREE)))
        {
          if (rval == error_mark_node)
            return error_mark_node;
index fc39840..8704a8d 100644 (file)
@@ -1,3 +1,7 @@
+2003-01-29  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/parser/constant1.C: New test.
+
 2003-01-29  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        PR c++/8591
diff --git a/gcc/testsuite/g++.dg/parse/constant1.C b/gcc/testsuite/g++.dg/parse/constant1.C
new file mode 100644 (file)
index 0000000..0a88928
--- /dev/null
@@ -0,0 +1,13 @@
+void f () {
+  switch (0) {
+  case (3, 0): // { dg-error "" }
+    break;
+  }
+}
+
+int g ();
+
+struct S {
+  int i : (false ? g () : 1); // { dg-error "" }
+};
+
index 8f3c1bc..fd0d93f 100644 (file)
@@ -1,3 +1,15 @@
+2003-01-29  Mark Mitchell  <mark@codesourcery.com>
+
+       * include/std/std_limits.h (numeric_limits<float>::has_infinity):
+       Use __FLT_HAS_INIFINITY__ to initialize.
+       (numeric_limits<float>::has_quiet_NaN): Likewise.
+       (numeric_limits<double>::has_infinity): Use __DBL_HAS_INIFINITY__
+       to initialize.
+       (numeric_limits<double>::has_quiet_NaN): Likewise.
+       (numeric_limits<long double>::has_infinity): Use
+       __LDBL_HAS_INIFINITY__ to initialize.
+       (numeric_limits<long_double>::has_quiet_NaN): Likewise.
+
 2003-01-28  Nathan Sidwell  <nathan@codesourcery.com>
 
        PR c++/9433
index 9be6947..2248071 100644 (file)
@@ -1,6 +1,6 @@
 // The template and inlines for the -*- C++ -*- numeric_limits classes.
 
-// Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -893,10 +893,8 @@ namespace std
       static const int max_exponent = __FLT_MAX_EXP__;
       static const int max_exponent10 = __FLT_MAX_10_EXP__;
 
-      static const bool has_infinity
-       = __builtin_huge_valf () / 2 == __builtin_huge_valf ();
-      static const bool has_quiet_NaN
-       = __builtin_nanf ("") != __builtin_nanf ("");
+      static const bool has_infinity = __FLT_HAS_INFINITY__;
+      static const bool has_quiet_NaN = __FLT_HAS_QUIET_NAN__;
       static const bool has_signaling_NaN = has_quiet_NaN;
       static const float_denorm_style has_denorm
        = __FLT_DENORM_MIN__ ? denorm_present : denorm_absent;
@@ -951,10 +949,8 @@ namespace std
       static const int max_exponent = __DBL_MAX_EXP__;
       static const int max_exponent10 = __DBL_MAX_10_EXP__;
 
-      static const bool has_infinity
-       = __builtin_huge_val () / 2 == __builtin_huge_val ();
-      static const bool has_quiet_NaN
-       = __builtin_nan ("") != __builtin_nan ("");
+      static const bool has_infinity = __DBL_HAS_INFINITY__;
+      static const bool has_quiet_NaN = __DBL_HAS_QUIET_NAN__;
       static const bool has_signaling_NaN = has_quiet_NaN;
       static const float_denorm_style has_denorm
        = __DBL_DENORM_MIN__ ? denorm_present : denorm_absent;
@@ -1009,10 +1005,8 @@ namespace std
       static const int max_exponent = __LDBL_MAX_EXP__;
       static const int max_exponent10 = __LDBL_MAX_10_EXP__;
 
-      static const bool has_infinity
-       = __builtin_huge_vall () / 2 == __builtin_huge_vall ();
-      static const bool has_quiet_NaN
-       = __builtin_nanl ("") != __builtin_nanl ("");
+      static const bool has_infinity = __LDBL_HAS_INFINITY__;
+      static const bool has_quiet_NaN = __LDBL_HAS_QUIET_NAN__;
       static const bool has_signaling_NaN = has_quiet_NaN;
       static const float_denorm_style has_denorm
        = __LDBL_DENORM_MIN__ ? denorm_present : denorm_absent;