This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: Diagnose invalid constant-expressions


This patch does several things:

(1) Fixes a long-standing bug whereby G++ accepted code like this:

      void f () {
	switch (0) {
	case (3, 0): // { dg-error "" }
	  break;
	}
      }

      int g ();

      struct S {
	int i : (false ? g () : 1); // { dg-error "" }
      };
  
    Those are not constant-expressions.

(2) Removes uses of tsubst during declarator processing.  When seeing
    things like:

      template <typename T>
      struct S {
	typedef T X;

	T f();
      }

      template <typename T>
      typename S<T>::X f() {}

    the standard isn't clear on whether or not the declaration is
    valid, but the committee is moving towards making this
    definitively valid.  We supported that up until now by
    substituting into the return type, which is a pretty expensive
    trick.

    This patch avoids doing that, which was my original motivation for
    this work.  We want to make it an invariant that the only
    instantiations are full instantiations in which every template
    parameter is assigned a non-template value.

    This is also a key step towards correcting some bugs in our
    name-mangling code and two-phase name lookup.

    I'm going to keep working on these projects, but I know that I
    owe some regressions fixes as well.

(3) Removes numerous dead functions in the C++ front end, including
    grokoptypename, build_opfncall, and enter_scope_of.  Tidies a few
    other items in the code.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

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-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  Mark Mitchell  <mark@codesourcery.com>

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

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.

Index: gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.398
diff -c -5 -p -r1.398 c-common.c
*** gcc/c-common.c	24 Jan 2003 22:07:00 -0000	1.398
--- gcc/c-common.c	30 Jan 2003 07:12:21 -0000
*************** builtin_define_float_constants (name_pre
*** 4894,4903 ****
--- 4894,4915 ----
    else
      {
        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.  */
  void
  cb_register_builtins (pfile)
Index: gcc/cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.353
diff -c -5 -p -r1.353 call.c
*** gcc/cp/call.c	17 Jan 2003 22:51:02 -0000	1.353
--- gcc/cp/call.c	30 Jan 2003 07:12:26 -0000
*************** static tree convert_class_to_reference (
*** 101,110 ****
--- 101,111 ----
  static tree direct_reference_binding (tree, tree);
  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)
  {
    if (datum == error_mark_node)
*************** build_field_call (tree instance_ptr, tre
*** 143,154 ****
  
        if (instance == error_mark_node)
  	return error_mark_node;
  
        if (IS_AGGR_TYPE (TREE_TYPE (instance)))
! 	return build_opfncall (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)))
  		       == FUNCTION_TYPE)))
  	return build_function_call (instance, parms);
--- 144,155 ----
  
        if (instance == error_mark_node)
  	return error_mark_node;
  
        if (IS_AGGR_TYPE (TREE_TYPE (instance)))
! 	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)))
  		       == FUNCTION_TYPE)))
  	return build_function_call (instance, parms);
*************** build_conditional_expr (tree arg1, tree 
*** 3293,3302 ****
--- 3294,3324 ----
      result = build1 (NON_LVALUE_EXPR, result_type, result);
  
    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)
  {
    struct z_candidate *candidates = 0, *cand;
    tree fns, mem_arglist = NULL_TREE, arglist, fnname;
*************** build_new_op (enum tree_code code, int f
*** 3308,3341 ****
    if (error_operand_p (arg1) 
        || error_operand_p (arg2) 
        || 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);
        arg3 = NULL_TREE;
        fnname = ansi_assopname (code2);
      }
    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)));
    
    switch (code)
      {
      case NEW_EXPR:
      case VEC_NEW_EXPR:
--- 3330,3349 ----
    if (error_operand_p (arg1) 
        || error_operand_p (arg2) 
        || error_operand_p (arg3))
      return error_mark_node;
  
    if (code == MODIFY_EXPR)
      {
        code2 = TREE_CODE (arg3);
        arg3 = NULL_TREE;
        fnname = ansi_assopname (code2);
      }
    else
      fnname = ansi_opname (code);
  
!   arg1 = prep_operand (arg1);
    
    switch (code)
      {
      case NEW_EXPR:
      case VEC_NEW_EXPR:
*************** build_new_op (enum tree_code code, int f
*** 3349,3376 ****
  
      default:
        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)));
!     }
    
    if (code == COND_EXPR)
      {
        if (arg2 == NULL_TREE
  	  || TREE_CODE (TREE_TYPE (arg2)) == VOID_TYPE
--- 3357,3368 ----
  
      default:
        break;
      }
  
!   arg2 = prep_operand (arg2);
!   arg3 = prep_operand (arg3);
    
    if (code == COND_EXPR)
      {
        if (arg2 == NULL_TREE
  	  || TREE_CODE (TREE_TYPE (arg2)) == VOID_TYPE
*************** build_new_op (enum tree_code code, int f
*** 3551,3561 ****
        return error_mark_node;
      }
  
    if (TREE_CODE (cand->fn) == FUNCTION_DECL)
      {
-       extern int warn_synth;
        if (warn_synth
  	  && fnname == ansi_assopname (NOP_EXPR)
  	  && DECL_ARTIFICIAL (cand->fn)
  	  && candidates->next
  	  && ! candidates->next->next)
--- 3543,3552 ----
Index: gcc/cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.516
diff -c -5 -p -r1.516 class.c
*** gcc/cp/class.c	27 Jan 2003 23:29:49 -0000	1.516
--- gcc/cp/class.c	30 Jan 2003 07:12:27 -0000
*************** init_class_processing (void)
*** 5756,5766 ****
     unmarks the marked types.  If a field or member function name
     appears in an ambiguous way, the IDENTIFIER_CLASS_VALUE of
     that name becomes `error_mark_node'.  */
  
  void
! pushclass (tree type, int modify)
  {
    type = TYPE_MAIN_VARIANT (type);
  
    /* Make sure there is enough room for the new entry on the stack.  */
    if (current_class_depth + 1 >= current_class_stack_size) 
--- 5756,5766 ----
     unmarks the marked types.  If a field or member function name
     appears in an ambiguous way, the IDENTIFIER_CLASS_VALUE of
     that name becomes `error_mark_node'.  */
  
  void
! pushclass (tree type, bool modify)
  {
    type = TYPE_MAIN_VARIANT (type);
  
    /* Make sure there is enough room for the new entry on the stack.  */
    if (current_class_depth + 1 >= current_class_stack_size) 
*************** popclass (void)
*** 5878,5891 ****
  
  int
  currently_open_class (tree t)
  {
    int i;
!   if (t == current_class_type)
      return 1;
    for (i = 1; i < current_class_depth; ++i)
!     if (current_class_stack [i].type == t)
        return 1;
    return 0;
  }
  
  /* If either current_class_type or one of its enclosing classes are derived
--- 5878,5892 ----
  
  int
  currently_open_class (tree t)
  {
    int i;
!   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
! 	&& same_type_p (current_class_stack [i].type, t))
        return 1;
    return 0;
  }
  
  /* If either current_class_type or one of its enclosing classes are derived
*************** currently_open_derived_class (tree t)
*** 5910,5927 ****
  
    return NULL_TREE;
  }
  
  /* 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.  */
  
  void
! push_nested_class (tree type, int modify)
  {
    tree context;
  
    /* A namespace might be passed in error cases, like A::B:C.  */
    if (type == NULL_TREE 
--- 5911,5927 ----
  
    return NULL_TREE;
  }
  
  /* 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.  */
  
  void
! push_nested_class (tree type)
  {
    tree context;
  
    /* A namespace might be passed in error cases, like A::B:C.  */
    if (type == NULL_TREE 
*************** push_nested_class (tree type, int modify
*** 5933,5944 ****
      return;
    
    context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
  
    if (context && CLASS_TYPE_P (context))
!     push_nested_class (context, 2);
!   pushclass (type, modify);
  }
  
  /* Undoes a push_nested_class call.  */
  
  void
--- 5933,5944 ----
      return;
    
    context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
  
    if (context && CLASS_TYPE_P (context))
!     push_nested_class (context);
!   pushclass (type, true);
  }
  
  /* Undoes a push_nested_class call.  */
  
  void
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.806
diff -c -5 -p -r1.806 cp-tree.h
*** gcc/cp/cp-tree.h	25 Jan 2003 16:28:24 -0000	1.806
--- gcc/cp/cp-tree.h	30 Jan 2003 07:12:29 -0000
*************** struct lang_decl GTY(())
*** 2475,2484 ****
--- 2475,2488 ----
     types as well, which is incorrect in C++.  */
  #define CP_INTEGRAL_TYPE_P(TYPE)		\
    (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
     types.  */
  #define ARITHMETIC_TYPE_P(TYPE) \
*************** extern void duplicate_tag_error			(tree)
*** 3640,3652 ****
  extern tree finish_struct			(tree, tree);
  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 popclass				(void);
! extern void push_nested_class			(tree, int);
  extern void pop_nested_class			(void);
  extern int current_lang_depth			(void);
  extern void push_lang_context			(tree);
  extern void pop_lang_context			(void);
  extern tree instantiate_type			(tree, tree, tsubst_flags_t);
--- 3644,3656 ----
  extern tree finish_struct			(tree, tree);
  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, bool);
  extern void popclass				(void);
! extern void push_nested_class			(tree);
  extern void pop_nested_class			(void);
  extern int current_lang_depth			(void);
  extern void push_lang_context			(tree);
  extern void pop_lang_context			(void);
  extern tree instantiate_type			(tree, tree, tsubst_flags_t);
*************** extern tree delete_sanity (tree, tree, i
*** 3852,3862 ****
  extern tree check_classfn (tree, tree);
  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);
  extern bool constructor_name_p                  (tree, tree);
  extern void defer_fn (tree);
--- 3856,3865 ----
*************** extern void cxx_finish (void);
*** 4007,4017 ****
  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);
  extern void use_thunk (tree, bool);
  extern void synthesize_method (tree);
--- 4010,4019 ----
*************** extern bool calls_setjmp_p (tree);
*** 4024,4037 ****
  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);
  extern void begin_template_parm_list		(void);
  extern void begin_specialization                (void);
--- 4026,4035 ----
*************** extern tree maybe_get_template_decl_from
*** 4084,4093 ****
--- 4082,4094 ----
  extern int processing_template_parmlist;
  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);
  extern void repo_template_instantiated (tree, bool);
  extern void init_repo (const char *);
*************** extern tree finish_qualified_object_call
*** 4224,4234 ****
  extern tree finish_pseudo_destructor_expr       (tree, tree, tree);
  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);
  extern tree finish_template_template_parm       (tree, tree);
  extern tree finish_parmlist                     (tree, int);
--- 4225,4234 ----
*************** extern tree begin_class_definition      
*** 4236,4246 ****
  extern tree finish_class_definition             (tree, tree, int, int);
  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);
  extern tree finish_typeof			(tree);
  extern tree finish_sizeof			(tree);
--- 4236,4245 ----
Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.991
diff -c -5 -p -r1.991 decl.c
*** gcc/cp/decl.c	17 Jan 2003 23:59:10 -0000	1.991
--- gcc/cp/decl.c	30 Jan 2003 07:12:31 -0000
*************** static int lookup_flags (int, int);
*** 103,113 ****
  static tree qualify_lookup (tree, int);
  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*);
  static void add_decl_to_level (tree, struct cp_binding_level *);
  static tree make_label_decl (tree, int);
--- 103,112 ----
*************** finish_case_label (tree low_value, tree 
*** 5070,5081 ****
    cond = SWITCH_COND (switch_stack->switch_stmt);
    if (cond && TREE_CODE (cond) == TREE_LIST)
      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);
  
    /* After labels, make any new cleanups in the function go into their
       own new (temporary) binding contour.  */
--- 5069,5078 ----
*************** qualify_lookup (tree val, int flags)
*** 5783,5816 ****
    if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
      return NULL_TREE;
    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.  
  
     Returns a DECL (or OVERLOAD, or BASELINK) representing the
--- 5780,5789 ----
*************** start_decl (tree declarator, 
*** 7076,7086 ****
      warning_with_decl (decl,
  		       "inline function `%s' given attribute noinline");
  
    if (context && COMPLETE_TYPE_P (complete_type (context)))
      {
!       push_nested_class (context, 2);
  
        if (TREE_CODE (decl) == VAR_DECL)
  	{
  	  tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
  	  if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
--- 7049,7059 ----
      warning_with_decl (decl,
  		       "inline function `%s' given attribute noinline");
  
    if (context && COMPLETE_TYPE_P (complete_type (context)))
      {
!       push_nested_class (context);
  
        if (TREE_CODE (decl) == VAR_DECL)
  	{
  	  tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
  	  if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
*************** grokfndecl (tree ctype, 
*** 9084,9096 ****
--- 9057,9071 ----
  	  if (TREE_CODE (decl) == TEMPLATE_DECL)
  	    decl = DECL_TEMPLATE_RESULT (decl);
  
  	  /* 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;
  	}
      }
  
    if (DECL_CONSTRUCTOR_P (decl) && !grok_ctor_properties (ctype, decl))
*************** grokdeclarator (tree declarator,
*** 11053,11091 ****
  	*attrlist = chainon (returned_attrs, *attrlist);
        else
  	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?  */
  
    if (TREE_CODE (type) == ARRAY_TYPE
--- 11028,11037 ----
*************** start_function (tree declspecs, tree dec
*** 13468,13480 ****
      cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
  
    /* Set up current_class_type, and enter the scope of the class, if
       appropriate.  */
    if (ctype)
!     push_nested_class (ctype, 1);
    else if (DECL_STATIC_FUNCTION_P (decl1))
!     push_nested_class (DECL_CONTEXT (decl1), 2);
  
    /* Now that we have entered the scope of the class, we must restore
       the bindings for any template parameters surrounding DECL1, if it
       is an inline member template.  (Order is important; consider the
       case where a template parameter has the same name as a field of
--- 13414,13426 ----
      cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
  
    /* Set up current_class_type, and enter the scope of the class, if
       appropriate.  */
    if (ctype)
!     push_nested_class (ctype);
    else if (DECL_STATIC_FUNCTION_P (decl1))
!     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
       is an inline member template.  (Order is important; consider the
       case where a template parameter has the same name as a field of
Index: gcc/cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.596
diff -c -5 -p -r1.596 decl2.c
*** gcc/cp/decl2.c	16 Jan 2003 20:30:36 -0000	1.596
--- gcc/cp/decl2.c	30 Jan 2003 07:12:32 -0000
*************** grok_array_decl (tree array_expr, tree i
*** 421,432 ****
        || TREE_CODE (type) == REFERENCE_TYPE)
      type = TREE_TYPE (type);
  
    /* 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);
  
    /* 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
       int, you can write `i[a]', which means the same thing as `a[i]'.  */
  
--- 421,432 ----
        || TREE_CODE (type) == REFERENCE_TYPE)
      type = TREE_TYPE (type);
  
    /* If they have an `operator[]', use that.  */
    if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
!     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
       int, you can write `i[a]', which means the same thing as `a[i]'.  */
  
*************** check_classfn (tree ctype, tree function
*** 683,692 ****
--- 683,693 ----
        tree methods = CLASSTYPE_METHOD_VEC (ctype);
        tree fndecls, fndecl = 0;
        bool is_conv_op;
        const char *format = NULL;
        
+       push_scope (ctype);
        for (fndecls = TREE_VEC_ELT (methods, ix);
  	   fndecls; fndecls = OVL_NEXT (fndecls))
  	{
  	  tree p1, p2;
  	  
*************** check_classfn (tree ctype, tree function
*** 711,722 ****
  	      && (DECL_TEMPLATE_SPECIALIZATION (function)
  		  == DECL_TEMPLATE_SPECIALIZATION (fndecl))
  	      && (!DECL_TEMPLATE_SPECIALIZATION (function)
  		  || (DECL_TI_TEMPLATE (function) 
  		      == DECL_TI_TEMPLATE (fndecl))))
! 	    return fndecl;
  	}
        error ("prototype for `%#D' does not match any in class `%T'",
  	     function, ctype);
        is_conv_op = DECL_CONV_FN_P (fndecl);
  
        if (is_conv_op)
--- 712,726 ----
  	      && (DECL_TEMPLATE_SPECIALIZATION (function)
  		  == DECL_TEMPLATE_SPECIALIZATION (fndecl))
  	      && (!DECL_TEMPLATE_SPECIALIZATION (function)
  		  || (DECL_TI_TEMPLATE (function) 
  		      == DECL_TI_TEMPLATE (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);
  
        if (is_conv_op)
*************** grokbitfield (tree declarator, tree decl
*** 1069,1102 ****
  
    DECL_IN_AGGR_P (value) = 1;
    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:
  
     class B
     {
--- 1073,1082 ----
*************** void
*** 3747,3757 ****
  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);
  }
  
  /* Leave scope pushed by push_scope.  */
  
  void
--- 3727,3737 ----
  push_scope (tree t)
  {
    if (TREE_CODE (t) == NAMESPACE_DECL)
      push_decl_namespace (t);
    else if CLASS_TYPE_P (t)
!     push_nested_class (t);
  }
  
  /* Leave scope pushed by push_scope.  */
  
  void
Index: gcc/cp/error.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/error.c,v
retrieving revision 1.197
diff -c -5 -p -r1.197 error.c
*** gcc/cp/error.c	23 Jan 2003 00:17:31 -0000	1.197
--- gcc/cp/error.c	30 Jan 2003 07:12:32 -0000
*************** dump_type (t, flags)
*** 452,461 ****
--- 452,462 ----
        dump_type_prefix (t, flags);
        dump_type_suffix (t, flags);
        break;
      }
      case TYPENAME_TYPE:
+       dump_qualifiers (t, after);
        output_add_string (scratch_buffer, "typename ");
        dump_typename (t, flags);
        break;
  
      case UNBOUND_CLASS_TEMPLATE:
Index: gcc/cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.307
diff -c -5 -p -r1.307 init.c
*** gcc/cp/init.c	23 Jan 2003 06:05:18 -0000	1.307
--- gcc/cp/init.c	30 Jan 2003 07:12:33 -0000
*************** build_member_call (type, name, parmlist)
*** 1509,1520 ****
  	{
  	  error ("invalid use of member `%D'", t);
  	  return error_mark_node;
  	}
        if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
! 	return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl,
! 			       parmlist, NULL_TREE);
        return build_function_call (decl, parmlist);
      }
    else
      {
        error ("no method `%T::%D'", type, name);
--- 1509,1520 ----
  	{
  	  error ("invalid use of member `%D'", t);
  	  return error_mark_node;
  	}
        if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
! 	return build_new_op (CALL_EXPR, LOOKUP_NORMAL, decl,
! 			     parmlist, NULL_TREE);
        return build_function_call (decl, parmlist);
      }
    else
      {
        error ("no method `%T::%D'", type, name);
Index: gcc/cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.244
diff -c -5 -p -r1.244 method.c
*** gcc/cp/method.c	10 Jan 2003 02:22:17 -0000	1.244
--- gcc/cp/method.c	30 Jan 2003 07:12:33 -0000
*************** set_mangled_name_for_decl (tree decl)
*** 83,122 ****
  
    mangle_decl (decl);
  }
  
  
- /* 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);
- }
- 
  /* 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:
  
     1) not in a class's scope
--- 83,92 ----
Index: gcc/cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.41
diff -c -5 -p -r1.41 parser.c
*** gcc/cp/parser.c	29 Jan 2003 14:25:05 -0000	1.41
--- gcc/cp/parser.c	30 Jan 2003 07:12:36 -0000
*************** typedef struct cp_parser GTY(())
*** 1273,1285 ****
       them permissable.  */
    bool default_arg_ok_p;
    
    /* 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 local variable names and `this' are forbidden in the
       current context.  */
    bool local_variables_forbidden_p;
  
    /* TRUE if the declaration we are parsing is part of a
--- 1273,1294 ----
       them permissable.  */
    bool default_arg_ok_p;
    
    /* TRUE if we are parsing an integral constant-expression.  See
       [expr.const] for a precise definition.  */
    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;
  
    /* TRUE if the declaration we are parsing is part of a
*************** static tree cp_parser_assignment_express
*** 1420,1430 ****
  static enum tree_code cp_parser_assignment_operator_opt
    (cp_parser *);
  static tree cp_parser_expression
    (cp_parser *);
  static tree cp_parser_constant_expression
!   (cp_parser *);
  
  /* Statements [gram.stmt.stmt]  */
  
  static void cp_parser_statement
    (cp_parser *);
--- 1429,1439 ----
  static enum tree_code cp_parser_assignment_operator_opt
    (cp_parser *);
  static tree cp_parser_expression
    (cp_parser *);
  static tree cp_parser_constant_expression
!   (cp_parser *, bool, bool *);
  
  /* Statements [gram.stmt.stmt]  */
  
  static void cp_parser_statement
    (cp_parser *);
*************** static void cp_parser_label_declaration
*** 1656,1667 ****
  
  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
    (cp_parser *, tree);
  static bool cp_parser_check_template_parameters
--- 1665,1674 ----
*************** static void cp_parser_error
*** 1726,1735 ****
--- 1733,1746 ----
    (cp_parser *, const char *);
  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
    (cp_parser *);
  static bool cp_parser_skip_to_closing_parenthesis_or_comma
*************** cp_parser_check_type_definition (cp_pars
*** 1873,1882 ****
--- 1884,1913 ----
      /* Use `%s' to print the string in case there are any escape
         characters in the message.  */
      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.  */
  
  static bool
*************** cp_parser_new (void)
*** 2180,2189 ****
--- 2211,2222 ----
  
    parser->default_arg_ok_p = true;
    
    /* 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;
  
    /* We are not procesing an `extern "C"' declaration.  */
*************** cp_parser_primary_expression (cp_parser 
*** 2393,2402 ****
--- 2426,2442 ----
  	  if (parser->local_variables_forbidden_p)
  	    {
  	      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
  	     id-expression.  */
  	case RID_OPERATOR:
*************** cp_parser_primary_expression (cp_parser 
*** 2432,2442 ****
  	    cp_parser_require (parser, CPP_COMMA, "`,'");
  	    /* Parse the type-id.  */
  	    type = cp_parser_type_id (parser);
  	    /* Look for the closing `)'.  */
  	    cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
! 
  	    return build_x_va_arg (expression, type);
  	  }
  
  	default:
  	  cp_parser_error (parser, "expected primary-expression");
--- 2472,2489 ----
  	    cp_parser_require (parser, CPP_COMMA, "`,'");
  	    /* Parse the type-id.  */
  	    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);
  	  }
  
  	default:
  	  cp_parser_error (parser, "expected primary-expression");
*************** cp_parser_primary_expression (cp_parser 
*** 2479,2488 ****
--- 2526,2540 ----
  	       name.  */
  	    if (TREE_CODE (decl) == SCOPE_REF)
  	      {
  		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
  	       where that is forbidden.  */
  	    if (parser->local_variables_forbidden_p
*************** cp_parser_primary_expression (cp_parser 
*** 2702,2723 ****
--- 2754,2806 ----
  		/* Create a SCOPE_REF for qualified names.  */
  		if (parser->scope)
  		  {
  		    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);
  		  }
  		/* A TEMPLATE_ID already contains all the information
  		   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 
  			(decl, parser->scope, current_class_type));
  		if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
*************** cp_parser_postfix_expression (cp_parser 
*** 3518,3527 ****
--- 3601,3623 ----
  	/* And the expression which is being cast.  */
  	cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
  	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:
  	    postfix_expression
  	      = build_dynamic_cast (type, expression);
*************** cp_parser_postfix_expression (cp_parser 
*** 3643,3678 ****
  	if (cp_parser_parse_definitely (parser))
  	  break;
  
  	/* If the functional-cast didn't work out, try a
  	   compound-literal.  */
! 	if (cp_parser_allow_gnu_extensions_p (parser))
  	  {
  	    tree initializer_list = NULL_TREE;
  
  	    cp_parser_parse_tentatively (parser);
! 	    /* Look for the `('.  */
! 	    if (cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
  	      {
! 		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, "`}'");
! 		  }
  	      }
  	    /* If that worked, we're definitely looking at a
  	       compound-literal expression.  */
  	    if (cp_parser_parse_definitely (parser))
  	      {
--- 3739,3774 ----
  	if (cp_parser_parse_definitely (parser))
  	  break;
  
  	/* If the functional-cast didn't work out, try a
  	   compound-literal.  */
! 	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);
! 	    /* 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))
  	      {
! 		/* 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.  */
  	    if (cp_parser_parse_definitely (parser))
  	      {
*************** cp_parser_postfix_expression (cp_parser 
*** 3804,3813 ****
--- 3900,3917 ----
  	      args = cp_parser_expression_list (parser);
  	    else
  	      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)
  		    || DECL_P (postfix_expression)
  		    || TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
*************** cp_parser_postfix_expression (cp_parser 
*** 4027,4036 ****
--- 4131,4147 ----
  
  	case CPP_PLUS_PLUS:
  	  /* 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, 
  				     POSTINCREMENT_EXPR);
  	  idk = CP_PARSER_ID_KIND_NONE;
*************** cp_parser_postfix_expression (cp_parser 
*** 4038,4047 ****
--- 4149,4165 ----
  
  	case CPP_MINUS_MINUS:
  	  /* 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, 
  				     POSTDECREMENT_EXPR);
  	  idk = CP_PARSER_ID_KIND_NONE;
*************** cp_parser_unary_expression (cp_parser *p
*** 4339,4353 ****
  	  return build_x_indirect_ref (cast_expression, "unary *");
  	  
  	case ADDR_EXPR:
  	  return build_x_unary_op (ADDR_EXPR, cast_expression);
  	  
  	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:
  	  return build_x_unary_op (BIT_NOT_EXPR, cast_expression);
  
--- 4457,4480 ----
  	  return build_x_indirect_ref (cast_expression, "unary *");
  	  
  	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:
  	  return finish_unary_op_expr (unary_operator, cast_expression);
  
  	case BIT_NOT_EXPR:
  	  return build_x_unary_op (BIT_NOT_EXPR, cast_expression);
  
*************** cp_parser_direct_new_declarator (cp_pars
*** 4595,4605 ****
  		}
  	    }
  	}
        /* But all the other expressions must be.  */
        else
! 	expression = cp_parser_constant_expression (parser);
        /* Look for the closing `]'.  */
        cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
  
        /* Add this bound to the declarator.  */
        declarator = build_nt (ARRAY_REF, declarator, expression);
--- 4722,4735 ----
  		}
  	    }
  	}
        /* But all the other expressions must be.  */
        else
! 	expression 
! 	  = cp_parser_constant_expression (parser, 
! 					   /*allow_non_constant=*/false,
! 					   NULL);
        /* Look for the closing `]'.  */
        cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
  
        /* Add this bound to the declarator.  */
        declarator = build_nt (ARRAY_REF, declarator, expression);
*************** cp_parser_cast_expression (cp_parser *pa
*** 4764,4774 ****
  	  if (warn_old_style_cast 
  	      && !in_system_header 
  	      && !VOID_TYPE_P (type) 
  	      && current_lang_name != lang_name_c)
  	    warning ("use of old-style cast");
! 	  
  	  /* Perform the cast.  */
  	  expr = build_c_cast (type, expr);
  	  return expr;
  	}
      }
--- 4894,4916 ----
  	  if (warn_old_style_cast 
  	      && !in_system_header 
  	      && !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;
  	}
      }
*************** cp_parser_assignment_expression (cp_pars
*** 5174,5183 ****
--- 5316,5333 ----
  	    {
  	      tree rhs;
  
  	      /* 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, 
  					  rhs);
  	    }
*************** cp_parser_expression (cp_parser* parser)
*** 5332,5355 ****
  
    /* Build a COMPOUND_EXPR to represent the entire expression, if
       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));
  
    return expression;
  }
  
  /* Parse a constant-expression. 
  
     constant-expression:
!      conditional-expression  */
  
  static tree
! cp_parser_constant_expression (cp_parser* parser)
  {
    bool saved_constant_expression_p;
    tree expression;
  
    /* It might seem that we could simply parse the
       conditional-expression, and then check to see if it were
       TREE_CONSTANT.  However, an expression that is TREE_CONSTANT is
--- 5482,5522 ----
  
    /* Build a COMPOUND_EXPR to represent the entire expression, if
       necessary.  We built up the list in reverse order, so we must
       straighten it out here.  */
    if (saw_comma_p)
!     {
!       /* 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;
  }
  
  /* Parse a constant-expression. 
  
     constant-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, 
! 			       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
       conditional-expression, and then check to see if it were
       TREE_CONSTANT.  However, an expression that is TREE_CONSTANT is
*************** cp_parser_constant_expression (cp_parser
*** 5365,5382 ****
       is not a legal declaration, because `(2, 3)' is not a
       constant-expression.  The `,' operator is forbidden in a
       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.  */
    saved_constant_expression_p = parser->constant_expression_p;
    /* We are now parsing a constant-expression.  */
    parser->constant_expression_p = true;
    /* Parse the conditional-expression.  */
    expression = cp_parser_conditional_expression (parser);
!   /* Restore the old setting of CONSTANT_EXPRESSION_P.  */
    parser->constant_expression_p = saved_constant_expression_p;
  
    return expression;
  }
  
  /* Statements [gram.stmt.stmt]  */
--- 5532,5559 ----
       is not a legal declaration, because `(2, 3)' is not a
       constant-expression.  The `,' operator is forbidden in a
       constant-expression.  However, GCC's constant-folding machinery
       will fold this operation to an INTEGER_CST for `3'.  */
  
!   /* 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 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;
  }
  
  /* Statements [gram.stmt.stmt]  */
*************** cp_parser_labeled_statement (cp_parser* 
*** 5515,5525 ****
  	tree expr;
  
  	/* Consume the `case' token.  */
  	cp_lexer_consume_token (parser->lexer);
  	/* Parse the constant-expression.  */
! 	expr = cp_parser_constant_expression (parser);
  	/* Create the label.  */
  	statement = finish_case_label (expr, NULL_TREE);
        }
        break;
  
--- 5692,5704 ----
  	tree expr;
  
  	/* Consume the `case' token.  */
  	cp_lexer_consume_token (parser->lexer);
  	/* Parse the constant-expression.  */
! 	expr = cp_parser_constant_expression (parser, 
! 					      /*allow_non_constant=*/false,
! 					      NULL);
  	/* Create the label.  */
  	statement = finish_case_label (expr, NULL_TREE);
        }
        break;
  
*************** cp_parser_enumerator_definition (cp_pars
*** 8873,8883 ****
    if (token->type == CPP_EQ)
      {
        /* Consume the `=' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Parse the value.  */
!       value = cp_parser_constant_expression (parser);
      }
    else
      value = NULL_TREE;
  
    /* Create the enumerator.  */
--- 9052,9064 ----
    if (token->type == CPP_EQ)
      {
        /* Consume the `=' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Parse the value.  */
!       value = cp_parser_constant_expression (parser, 
! 					     /*allow_non_constant=*/false,
! 					     NULL);
      }
    else
      value = NULL_TREE;
  
    /* Create the enumerator.  */
*************** cp_parser_direct_declarator (cp_parser* 
*** 9868,9878 ****
  	  /* Peek at the next token.  */
  	  token = cp_lexer_peek_token (parser->lexer);
  	  /* If the next token is `]', then there is no
  	     constant-expression.  */
  	  if (token->type != CPP_CLOSE_SQUARE)
! 	    bounds = cp_parser_constant_expression (parser);
  	  else
  	    bounds = NULL_TREE;
  	  /* Look for the closing `]'.  */
  	  if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
  	    {
--- 10049,10086 ----
  	  /* Peek at the next token.  */
  	  token = cp_lexer_peek_token (parser->lexer);
  	  /* If the next token is `]', then there is no
  	     constant-expression.  */
  	  if (token->type != CPP_CLOSE_SQUARE)
! 	    {
! 	      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 `]'.  */
  	  if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
  	    {
*************** cp_parser_direct_declarator (cp_parser* 
*** 9922,9936 ****
  	     	 `S<T>::R' not a type.  However, if `S' is
  	     	 specialized, then this `i' will not be used, so there
  	     	 is no harm in resolving the types here.  */
  	      if (TREE_CODE (scope) == TYPENAME_TYPE)
  		{
  		  /* Resolve the TYPENAME_TYPE.  */
! 		  scope = cp_parser_resolve_typename_type (parser, scope);
  		  /* If that failed, the declarator is invalid.  */
! 		  if (scope == error_mark_node)
! 		    return error_mark_node;
  		  /* Build a new DECLARATOR.  */
  		  declarator = build_nt (SCOPE_REF, 
  					 scope,
  					 TREE_OPERAND (declarator, 1));
  		}
--- 10130,10147 ----
  	     	 `S<T>::R' not a type.  However, if `S' is
  	     	 specialized, then this `i' will not be used, so there
  	     	 is no harm in resolving the types here.  */
  	      if (TREE_CODE (scope) == TYPENAME_TYPE)
  		{
+ 		  tree type;
+ 
  		  /* Resolve the TYPENAME_TYPE.  */
! 		  type = resolve_typename_type (scope,
! 						 /*only_current_p=*/false);
  		  /* If that failed, the declarator is invalid.  */
! 		  if (type != error_mark_node)
! 		    scope = type;
  		  /* Build a new DECLARATOR.  */
  		  declarator = build_nt (SCOPE_REF, 
  					 scope,
  					 TREE_OPERAND (declarator, 1));
  		}
*************** cp_parser_class_head (cp_parser* parser,
*** 11547,11566 ****
        tree class_type;
  
        /* Given:
  
  	    template <typename T> struct S { struct T };
! 	    template <typename T> struct S::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);
  	}
  
        maybe_process_partial_specialization (TREE_TYPE (type));
        class_type = current_class_type;
        type = TREE_TYPE (handle_class_head (class_key, 
--- 11758,11783 ----
        tree class_type;
  
        /* Given:
  
  	    template <typename T> struct S { struct 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)
  	{
! 	  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));
        class_type = current_class_type;
        type = TREE_TYPE (handle_class_head (class_key, 
*************** cp_parser_member_declaration (cp_parser*
*** 11887,11897 ****
  		identifier = NULL_TREE;
  
  	      /* Consume the `:' token.  */
  	      cp_lexer_consume_token (parser->lexer);
  	      /* Get the width of the bitfield.  */
! 	      width = cp_parser_constant_expression (parser);
  
  	      /* Look for attributes that apply to the bitfield.  */
  	      attributes = cp_parser_attributes_opt (parser);
  	      /* Remember which attributes are prefix attributes and
  		 which are not.  */
--- 12104,12117 ----
  		identifier = NULL_TREE;
  
  	      /* Consume the `:' token.  */
  	      cp_lexer_consume_token (parser->lexer);
  	      /* Get the width of the bitfield.  */
! 	      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);
  	      /* Remember which attributes are prefix attributes and
  		 which are not.  */
*************** cp_parser_constant_initializer (cp_parse
*** 12110,12120 ****
        cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
        
        return error_mark_node;
      }
  
!   return cp_parser_constant_expression (parser);
  }
  
  /* Derived classes [gram.class.derived] */
  
  /* Parse a base-clause.
--- 12330,12342 ----
        cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
        
        return error_mark_node;
      }
  
!   return cp_parser_constant_expression (parser, 
! 					/*allow_non_constant=*/false,
! 					NULL);
  }
  
  /* Derived classes [gram.class.derived] */
  
  /* Parse a base-clause.
*************** cp_parser_lookup_name_simple (cp_parser*
*** 13146,13207 ****
  				/*is_type=*/false,
  				/*is_namespace=*/false,
  				/*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,
     or declared in an elaborated-type-specifier.
  
--- 13368,13377 ----
*************** cp_parser_constructor_declarator_p (cp_p
*** 13545,13555 ****
  	    type = NULL_TREE;
  	  else
  	    {
  	      type = TREE_TYPE (type_decl);
  	      if (TREE_CODE (type) == TYPENAME_TYPE)
! 		type = cp_parser_resolve_typename_type (parser, type);
  	      push_scope (type);
  	    }
  	  /* Look for the type-specifier.  */
  	  cp_parser_type_specifier (parser,
  				    CP_PARSER_FLAGS_NONE,
--- 13715,13733 ----
  	    type = NULL_TREE;
  	  else
  	    {
  	      type = TREE_TYPE (type_decl);
  	      if (TREE_CODE (type) == TYPENAME_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.  */
  	  cp_parser_type_specifier (parser,
  				    CP_PARSER_FLAGS_NONE,
*************** cp_parser_late_parsing_default_args (cp_
*** 13976,13986 ****
       	  in a default argument.  */
        saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
        parser->local_variables_forbidden_p = true;
         /* Parse the assignment-expression.  */
        if (DECL_CONTEXT (fn))
! 	push_nested_class (DECL_CONTEXT (fn), 1);
        TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
        if (DECL_CONTEXT (fn))
  	pop_nested_class ();
  
         /* Restore saved state.  */
--- 14154,14164 ----
       	  in a default argument.  */
        saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
        parser->local_variables_forbidden_p = true;
         /* Parse the assignment-expression.  */
        if (DECL_CONTEXT (fn))
! 	push_nested_class (DECL_CONTEXT (fn));
        TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
        if (DECL_CONTEXT (fn))
  	pop_nested_class ();
  
         /* Restore saved state.  */
Index: gcc/cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.655
diff -c -5 -p -r1.655 pt.c
*** gcc/cp/pt.c	29 Jan 2003 11:35:32 -0000	1.655
--- gcc/cp/pt.c	30 Jan 2003 07:12:38 -0000
*************** static tree for_each_template_parm_r PAR
*** 169,180 ****
  static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
  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);
  
  /* Make the current scope suitable for access checking when we are
     processing T.  T can be FUNCTION_DECL for instantiated function
     template, TEMPLATE_DECL for uninstantiated one, or VAR_DECL for
     static member variable (need by instantiate_decl).  ARGS is the 
--- 169,183 ----
  static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
  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 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
     template, TEMPLATE_DECL for uninstantiated one, or VAR_DECL for
     static member variable (need by instantiate_decl).  ARGS is the 
*************** push_access_scope_real (t, args, context
*** 213,223 ****
      }
  
    if (!context)
      context = DECL_CONTEXT (t);
    if (context && TYPE_P (context))
!     push_nested_class (context, 2);
    else
      push_to_top_level ();
      
    if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
      {
--- 216,226 ----
      }
  
    if (!context)
      context = DECL_CONTEXT (t);
    if (context && TYPE_P (context))
!     push_nested_class (context);
    else
      push_to_top_level ();
      
    if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
      {
*************** tsubst_friend_class (friend_tmpl, args)
*** 5041,5051 ****
    if (context)
      {
        if (TREE_CODE (context) == NAMESPACE_DECL)
  	push_nested_namespace (context);
        else
! 	push_nested_class (tsubst (context, args, tf_none, NULL_TREE), 2);
      }
  
    /* First, we look for a class template.  */
    tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0); 
  
--- 5044,5054 ----
    if (context)
      {
        if (TREE_CODE (context) == NAMESPACE_DECL)
  	push_nested_namespace (context);
        else
! 	push_nested_class (tsubst (context, args, tf_none, NULL_TREE)); 
      }
  
    /* First, we look for a class template.  */
    tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0); 
  
*************** instantiate_class_template (type)
*** 5326,5336 ****
    /* Now that our base classes are set up, enter the scope of the
       class, so that name lookups into base classes, etc. will work
       correctly.  This is precisely analogous to what we do in
       begin_class_definition when defining an ordinary non-template
       class.  */
!   pushclass (type, 1);
  
    /* Now members are processed in the order of declaration.  */
    for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member))
      {
        tree t = TREE_VALUE (member);
--- 5329,5339 ----
    /* Now that our base classes are set up, enter the scope of the
       class, so that name lookups into base classes, etc. will work
       correctly.  This is precisely analogous to what we do in
       begin_class_definition when defining an ordinary non-template
       class.  */
!   pushclass (type, true);
  
    /* Now members are processed in the order of declaration.  */
    for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member))
      {
        tree t = TREE_VALUE (member);
*************** tsubst_call_declarator_parms (parms, arg
*** 6465,6475 ****
     yet.
  
     This function is used for dealing with types, decls and the like;
     for expressions, use tsubst_expr or tsubst_copy.  */
  
! tree
  tsubst (t, args, complain, in_decl)
       tree t, args;
       tsubst_flags_t complain;
       tree in_decl;
  {
--- 6468,6478 ----
     yet.
  
     This function is used for dealing with types, decls and the like;
     for expressions, use tsubst_expr or tsubst_copy.  */
  
! static tree
  tsubst (t, args, complain, in_decl)
       tree t, args;
       tsubst_flags_t complain;
       tree in_decl;
  {
*************** tsubst (t, args, complain, in_decl)
*** 7101,7111 ****
  
  /* Like tsubst, but deals with expressions.  This function just replaces
     template parms; to finish processing the resultant expression, use
     tsubst_expr.  */
  
! tree
  tsubst_copy (t, args, complain, in_decl)
       tree t, args;
       tsubst_flags_t complain;
       tree in_decl;
  {
--- 7104,7114 ----
  
  /* Like tsubst, but deals with expressions.  This function just replaces
     template parms; to finish processing the resultant expression, use
     tsubst_expr.  */
  
! static tree
  tsubst_copy (t, args, complain, in_decl)
       tree t, args;
       tsubst_flags_t complain;
       tree in_decl;
  {
*************** tsubst_copy (t, args, complain, in_decl)
*** 7503,7513 ****
  }
  
  /* Like tsubst_copy for expressions, etc. but also does semantic
     processing.  */
  
! tree
  tsubst_expr (t, args, complain, in_decl)
       tree t, args;
       tsubst_flags_t complain;
       tree in_decl;
  {
--- 7506,7516 ----
  }
  
  /* Like tsubst_copy for expressions, etc. but also does semantic
     processing.  */
  
! static tree
  tsubst_expr (t, args, complain, in_decl)
       tree t, args;
       tsubst_flags_t complain;
       tree in_decl;
  {
*************** tsubst_expr (t, args, complain, in_decl)
*** 7830,7840 ****
  }
  
  /* Like tsubst but deals with expressions and performs semantic
     analysis.  */
  
! tree
  tsubst_copy_and_build (t, args, complain, in_decl)
       tree t, args;
       tsubst_flags_t complain;
       tree in_decl;
  {
--- 7833,7843 ----
  }
  
  /* Like tsubst but deals with expressions and performs semantic
     analysis.  */
  
! static tree
  tsubst_copy_and_build (t, args, complain, in_decl)
       tree t, args;
       tsubst_flags_t complain;
       tree in_decl;
  {
*************** dependent_type_p (type)
*** 11312,11330 ****
    return false;
  }
  
  /* Returns TRUE if the EXPRESSION is value-dependent.  */
  
! static 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)))
      return true;
    /* A non-type template parameter.  */
    if ((TREE_CODE (expression) == CONST_DECL
         && DECL_TEMPLATE_PARM_P (expression))
        || TREE_CODE (expression) == TEMPLATE_PARM_INDEX)
--- 11315,11334 ----
    return false;
  }
  
  /* Returns TRUE if the EXPRESSION is value-dependent.  */
  
! bool
  value_dependent_expression_p (tree expression)
  {
    if (!processing_template_decl)
      return false;
  
    /* A name declared with a dependent type.  */
!   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
         && DECL_TEMPLATE_PARM_P (expression))
        || TREE_CODE (expression) == TEMPLATE_PARM_INDEX)
*************** value_dependent_expression_p (tree expre
*** 11368,11382 ****
  		  || (value_dependent_expression_p 
  		      (TREE_OPERAND (expression, 1))));
  	case 'e':
  	  {
  	    int i;
! 	    for (i = 0; 
! 		 i < TREE_CODE_LENGTH (TREE_CODE (expression));
! 		 ++i)
! 	      if (value_dependent_expression_p
! 		  (TREE_OPERAND (expression, i)))
  		return true;
  	    return false;
  	  }
  	}
      }
--- 11372,11389 ----
  		  || (value_dependent_expression_p 
  		      (TREE_OPERAND (expression, 1))));
  	case 'e':
  	  {
  	    int 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;
  	  }
  	}
      }
*************** dependent_template_p (tree tmpl)
*** 11474,11481 ****
--- 11481,11572 ----
      return true;
    /* So are member templates of dependent classes.  */
    if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
      return dependent_type_p (DECL_CONTEXT (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: gcc/cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.296
diff -c -5 -p -r1.296 semantics.c
*** gcc/cp/semantics.c	25 Jan 2003 18:02:41 -0000	1.296
--- gcc/cp/semantics.c	30 Jan 2003 07:12:38 -0000
*************** finish_call_expr (tree fn, tree args, bo
*** 1432,1442 ****
    else if (CLASS_TYPE_P (TREE_TYPE (fn)))
      {
        /* 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);
        if (result)
  	return result;
      }
  
    /* A call where the function is unknown.  */
--- 1432,1442 ----
    else if (CLASS_TYPE_P (TREE_TYPE (fn)))
      {
        /* If the "function" is really an object of class type, it might
  	 have an overloaded `operator ()'.  */
        tree result;
!       result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
        if (result)
  	return result;
      }
  
    /* A call where the function is unknown.  */
*************** begin_function_definition (decl_specs, a
*** 1663,1685 ****
    reset_specialization ();
  
    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
  finish_declarator (declarator, declspecs, attributes,
  		   prefix_attributes, initialized)
--- 1663,1672 ----
*************** begin_class_definition (t)
*** 1829,1839 ****
      {
        t = make_aggr_type (TREE_CODE (t));
        pushtag (TYPE_IDENTIFIER (t), t, 0);
      }
    maybe_process_partial_specialization (t);
!   pushclass (t, 1);
    TYPE_BEING_DEFINED (t) = 1;
    TYPE_PACKED (t) = flag_pack_struct;
    /* Reset the interface data, at the earliest possible
       moment, as it might have been set via a class foo;
       before.  */
--- 1816,1826 ----
      {
        t = make_aggr_type (TREE_CODE (t));
        pushtag (TYPE_IDENTIFIER (t), t, 0);
      }
    maybe_process_partial_specialization (t);
!   pushclass (t, true);
    TYPE_BEING_DEFINED (t) = 1;
    TYPE_PACKED (t) = flag_pack_struct;
    /* Reset the interface data, at the earliest possible
       moment, as it might have been set via a class foo;
       before.  */
*************** finish_template_type (name, args, enteri
*** 2040,2077 ****
  	                        entering_scope, /*complain=*/1);
    if (decl != error_mark_node)
      decl = TYPE_STUB_DECL (decl);
  
    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
--- 2027,2036 ----
Index: gcc/cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.445
diff -c -5 -p -r1.445 typeck.c
*** gcc/cp/typeck.c	17 Jan 2003 03:43:52 -0000	1.445
--- gcc/cp/typeck.c	30 Jan 2003 07:12:40 -0000
*************** comptypes (t1, t2, strict)
*** 944,953 ****
--- 944,960 ----
    if (TYPE_PTRMEMFUNC_P (t1))
      t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
    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;
  
    /* Qualifiers must match.  */
*************** build_x_indirect_ref (ptr, errorstring)
*** 2299,2310 ****
    tree rval;
  
    if (processing_template_decl)
      return build_min_nt (INDIRECT_REF, ptr);
  
!   rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
! 			 NULL_TREE);
    if (rval)
      return rval;
    return build_indirect_ref (ptr, errorstring);
  }
  
--- 2306,2317 ----
    tree rval;
  
    if (processing_template_decl)
      return build_min_nt (INDIRECT_REF, ptr);
  
!   rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE,
! 		       NULL_TREE);
    if (rval)
      return rval;
    return build_indirect_ref (ptr, errorstring);
  }
  
*************** build_x_binary_op (code, arg1, arg2)
*** 2971,2980 ****
--- 2978,3164 ----
      return build_min_nt (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:
     the data type of the result is computed and recorded in it,
     warnings are generated if arg data types are invalid,
*************** build_x_compound_expr (list)
*** 4600,4611 ****
      return build_min_nt (COMPOUND_EXPR, list, NULL_TREE);
  
    if (rest == NULL_TREE)
      return build_compound_expr (list);
  
!   result = build_opfncall (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)));
  
    if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
--- 4784,4795 ----
      return build_min_nt (COMPOUND_EXPR, list, NULL_TREE);
  
    if (rest == NULL_TREE)
      return build_compound_expr (list);
  
!   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)));
  
    if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
*************** build_modify_expr (lhs, modifycode, rhs)
*** 5233,5244 ****
  	  /* `operator=' is not an inheritable operator.  */
  	  if (! IS_AGGR_TYPE (lhstype))
  	    /* Do the default thing */;
  	  else
  	    {
! 	      result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
! 				       lhs, rhs, make_node (NOP_EXPR));
  	      if (result == NULL_TREE)
  		return error_mark_node;
  	      return result;
  	    }
  	  lhstype = olhstype;
--- 5417,5428 ----
  	  /* `operator=' is not an inheritable operator.  */
  	  if (! IS_AGGR_TYPE (lhstype))
  	    /* Do the default thing */;
  	  else
  	    {
! 	      result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
! 				     lhs, rhs, make_node (NOP_EXPR));
  	      if (result == NULL_TREE)
  		return error_mark_node;
  	      return result;
  	    }
  	  lhstype = olhstype;
*************** build_x_modify_expr (lhs, modifycode, rh
*** 5486,5497 ****
      return build_min_nt (MODOP_EXPR, lhs,
  			 build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs);
  
    if (modifycode != NOP_EXPR)
      {
!       tree rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
! 				  make_node (modifycode));
        if (rval)
  	return rval;
      }
    return build_modify_expr (lhs, modifycode, rhs);
  }
--- 5670,5681 ----
      return build_min_nt (MODOP_EXPR, lhs,
  			 build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs);
  
    if (modifycode != NOP_EXPR)
      {
!       tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
! 				make_node (modifycode));
        if (rval)
  	return rval;
      }
    return build_modify_expr (lhs, modifycode, rhs);
  }
Index: gcc/cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.135
diff -c -5 -p -r1.135 typeck2.c
*** gcc/cp/typeck2.c	25 Jan 2003 16:28:24 -0000	1.135
--- gcc/cp/typeck2.c	30 Jan 2003 07:12:40 -0000
*************** build_x_arrow (datum)
*** 1042,1053 ****
        type = TREE_TYPE (rval);
      }
  
    if (IS_AGGR_TYPE (type))
      {
!       while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval,
! 				     NULL_TREE, NULL_TREE)))
  	{
  	  if (rval == error_mark_node)
  	    return error_mark_node;
  
  	  if (value_member (TREE_TYPE (rval), types_memoized))
--- 1042,1053 ----
        type = TREE_TYPE (rval);
      }
  
    if (IS_AGGR_TYPE (type))
      {
!       while ((rval = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, rval,
! 				   NULL_TREE, NULL_TREE)))
  	{
  	  if (rval == error_mark_node)
  	    return error_mark_node;
  
  	  if (value_member (TREE_TYPE (rval), types_memoized))
Index: gcc/testsuite/g++.dg/parse/constant1.C
===================================================================
RCS file: gcc/testsuite/g++.dg/parse/constant1.C
diff -N gcc/testsuite/g++.dg/parse/constant1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/parse/constant1.C	30 Jan 2003 07:12:43 -0000
***************
*** 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: libstdc++-v3/include/std/std_limits.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/std/std_limits.h,v
retrieving revision 1.20
diff -c -5 -p -r1.20 std_limits.h
*** libstdc++-v3/include/std/std_limits.h	16 Dec 2002 19:52:37 -0000	1.20
--- libstdc++-v3/include/std/std_limits.h	30 Jan 2003 07:13:00 -0000
***************
*** 1,8 ****
  // The template and inlines for the -*- C++ -*- numeric_limits classes.
  
! // Copyright (C) 1999, 2000, 2001, 2002 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
  // terms of the GNU General Public License as published by the
  // Free Software Foundation; either version 2, or (at your option)
--- 1,8 ----
  // The template and inlines for the -*- C++ -*- numeric_limits classes.
  
! // 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
  // terms of the GNU General Public License as published by the
  // Free Software Foundation; either version 2, or (at your option)
*************** namespace std
*** 891,904 ****
        static const int min_exponent = __FLT_MIN_EXP__;
        static const int min_exponent10 = __FLT_MIN_10_EXP__;
        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_signaling_NaN = has_quiet_NaN;
        static const float_denorm_style has_denorm
  	= __FLT_DENORM_MIN__ ? denorm_present : denorm_absent;
        static const bool has_denorm_loss = __glibcpp_float_has_denorm_loss;
  
--- 891,902 ----
        static const int min_exponent = __FLT_MIN_EXP__;
        static const int min_exponent10 = __FLT_MIN_10_EXP__;
        static const int max_exponent = __FLT_MAX_EXP__;
        static const int max_exponent10 = __FLT_MAX_10_EXP__;
  
!       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;
        static const bool has_denorm_loss = __glibcpp_float_has_denorm_loss;
  
*************** namespace std
*** 949,962 ****
        static const int min_exponent = __DBL_MIN_EXP__;
        static const int min_exponent10 = __DBL_MIN_10_EXP__;
        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_signaling_NaN = has_quiet_NaN;
        static const float_denorm_style has_denorm
  	= __DBL_DENORM_MIN__ ? denorm_present : denorm_absent;
        static const bool has_denorm_loss = __glibcpp_double_has_denorm_loss;
  
--- 947,958 ----
        static const int min_exponent = __DBL_MIN_EXP__;
        static const int min_exponent10 = __DBL_MIN_10_EXP__;
        static const int max_exponent = __DBL_MAX_EXP__;
        static const int max_exponent10 = __DBL_MAX_10_EXP__;
  
!       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;
        static const bool has_denorm_loss = __glibcpp_double_has_denorm_loss;
  
*************** namespace std
*** 1007,1020 ****
        static const int min_exponent = __LDBL_MIN_EXP__;
        static const int min_exponent10 = __LDBL_MIN_10_EXP__;
        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_signaling_NaN = has_quiet_NaN;
        static const float_denorm_style has_denorm
  	= __LDBL_DENORM_MIN__ ? denorm_present : denorm_absent;
        static const bool has_denorm_loss
  	= __glibcpp_long_double_has_denorm_loss;
--- 1003,1014 ----
        static const int min_exponent = __LDBL_MIN_EXP__;
        static const int min_exponent10 = __LDBL_MIN_10_EXP__;
        static const int max_exponent = __LDBL_MAX_EXP__;
        static const int max_exponent10 = __LDBL_MAX_10_EXP__;
  
!       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;
        static const bool has_denorm_loss
  	= __glibcpp_long_double_has_denorm_loss;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]