This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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: Several regressions


This patch fixes:

PR c++/18001

  Incorrect quoting in lvalue_or_else.   Fixed by sharing code with
  the C front end, which already got this right.

PR c++/18556

  C++ debug problem on IA64.  Fixed by reinstating code that tried to
  avoid emitting debug information for undefined variables with static
  storage duration, but using DECL_IGNORED_P instead of clearing
  DECL_RTL.

PR c++/18445

  A crash on overload resolution while in a template.  Fixed by
  teaching the front end that a NON_DEPENDENT_EXPR cannot be used to
  resolve overloading.

PR c++/18625

  Duplicate error messages on a redundant typedef.  Fixed by making
  duplicate_decls do as it is specified to do: return
  error_mark_node, not NULL_TREE, to indicate errors.

PR c++/18466

  Check that a qualified name is not used to declare a name in its own
  namespace, i.e., you cannot write "N::x" to declare "x" if you are
  within "N".

PR c++/18545

  Use error_operand_p to test for erroneous operands to "return",
  rather than just checking error_mark_node.

Tested on i686-pc-linux-gnu, applied on the mainline.  Some of these
patches may also apply to the 3.4 branch; I will backport those later,
and retest.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-11-25  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18001
	* c-common.h (lvalue_use): Move here from c-ctypeck.c.
	(lvalue_or_else): Declare.
	* c-common.c (lvalue_or_else): Move here from c-typeck.c.
	* c-typeck.c (lvalue_use): Remove.
	(lvalue_or_else): Remove.

	PR c++/18556
	* toplev.c (check_global_declarations): Set DECL_IGNORED_P on
	unemitted variables with static storage duration.

2004-11-25  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18445
	* class.c (instantiate_type): Treat NON_DEPENDENT_EXPRs with
	unknown_type as non matching.  Tidy up.
	* pt.c (build_non_dependent_expr): Do not build a
	NON_DEPENDENT_EXPR for a VAR_DECL.

	PR c++/18001
	* cp-tree.h (lvalue_or_else): Remove declaration.
	* tree.c (lvalue_or_else): Remove.
	* typeck.c (build_unary_op): Adjust call to lvalue_or_else.
	(build_modify_expr): Likewise.

	PR c++/18625
	* decl.c (duplicate_decls): Return error_mark_node on error, as
	specified.

	PR c++/18466
	* decl.c (grokvardecl): Keep track of whether or not a there was
	explicit qualification.
	* name-lookup.c (set_decl_namespace): Complain about explicit
	qualification of a name within its own namespace.

	PR c++/18545
	* typeck.c (check_return_expr): Robustify.

2004-11-25  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18445
	* g++.dg/template/crash28.C: Likewise.

	PR c++/18001
	* g++.dg/expr/unary2.C: Adjust lvalue messages.
	* g++.dg/ext/lvaddr.C: Likewise.
	* g++.dg/opt/pr7503-3.C: Likewise.

	PR c++/18466
	* g++.dg/parse/qualified3.C: New test.
	* g++.old-deja/g++.other/friend7.C: Remove bogus qualification.
	
	PR c++/18545
	* g++.dg/expr/return1.C: New test. 

Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.587
diff -c -5 -p -r1.587 c-common.c
*** c-common.c	15 Nov 2004 22:13:14 -0000	1.587
--- c-common.c	25 Nov 2004 16:56:07 -0000
*************** fold_offsetof (tree expr)
*** 5615,5620 ****
--- 5615,5656 ----
  {
    /* Convert back from the internal sizetype to size_t.  */
    return convert (size_type_node, fold_offsetof_1 (expr));
  }
  
+ /* Return nonzero if REF is an lvalue valid for this language;
+    otherwise, print an error message and return zero.  USE says
+    how the lvalue is being used and so selects the error message.  */
+ 
+ int
+ lvalue_or_else (tree ref, enum lvalue_use use)
+ {
+   int win = lvalue_p (ref);
+ 
+   if (!win)
+     {
+       switch (use)
+ 	{
+ 	case lv_assign:
+ 	  error ("invalid lvalue in assignment");
+ 	  break;
+ 	case lv_increment:
+ 	  error ("invalid lvalue in increment");
+ 	  break;
+ 	case lv_decrement:
+ 	  error ("invalid lvalue in decrement");
+ 	  break;
+ 	case lv_addressof:
+ 	  error ("invalid lvalue in unary %<&%>");
+ 	  break;
+ 	case lv_asm:
+ 	  error ("invalid lvalue in asm statement");
+ 	  break;
+ 	default:
+ 	  gcc_unreachable ();
+ 	}
+     }
+ 
+   return win;
+ }
+ 
  #include "gt-c-common.h"
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.271
diff -c -5 -p -r1.271 c-common.h
*** c-common.h	17 Nov 2004 22:05:58 -0000	1.271
--- c-common.h	25 Nov 2004 16:56:07 -0000
*************** extern void c_warn_unused_result (tree *
*** 871,880 ****
--- 871,893 ----
  
  extern void verify_sequence_points (tree);
  
  extern tree fold_offsetof (tree);
  
+ /* Places where an lvalue, or modifiable lvalue, may be required.
+    Used to select diagnostic messages in lvalue_or_else and
+    readonly_error.  */
+ enum lvalue_use {
+   lv_assign,
+   lv_increment,
+   lv_decrement,
+   lv_addressof,
+   lv_asm
+ };
+ 
+ extern int lvalue_or_else (tree, enum lvalue_use);
+ 
  /* In c-gimplify.c  */
  extern void c_genericize (tree);
  extern int c_gimplify_expr (tree *, tree *, tree *);
  extern tree c_build_bind_expr (tree, tree);
  
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.400
diff -c -5 -p -r1.400 c-typeck.c
*** c-typeck.c	20 Nov 2004 20:31:43 -0000	1.400
--- c-typeck.c	25 Nov 2004 16:56:07 -0000
*************** Software Foundation, 59 Temple Place - S
*** 42,62 ****
  #include "ggc.h"
  #include "target.h"
  #include "tree-iterator.h"
  #include "tree-gimple.h"
  
- /* Places where an lvalue, or modifiable lvalue, may be required.
-    Used to select diagnostic messages in lvalue_or_else and
-    readonly_error.  */
- enum lvalue_use {
-   lv_assign,
-   lv_increment,
-   lv_decrement,
-   lv_addressof,
-   lv_asm
- };
- 
  /* Possible cases of implicit bad conversions.  Used to select
     diagnostic messages in convert_for_assignment.  */
  enum impl_conv {
    ic_argpass,
    ic_argpass_nonproto,
--- 42,51 ----
*************** static int set_designator (int);
*** 107,117 ****
  static void push_range_stack (tree);
  static void add_pending_init (tree, tree);
  static void set_nonincremental_init (void);
  static void set_nonincremental_init_from_string (tree);
  static tree find_init_member (tree);
- static int lvalue_or_else (tree, enum lvalue_use);
  static void readonly_error (tree, enum lvalue_use);
  static void record_maybe_used_decl (tree);
  
  /* Do `exp = require_complete_type (exp);' to make sure exp
     does not have an incomplete type.  (That includes void types.)  */
--- 96,105 ----
*************** lvalue_p (tree ref)
*** 2712,2758 ****
  
      default:
        return 0;
      }
  }
- 
- /* Return nonzero if REF is an lvalue valid for this language;
-    otherwise, print an error message and return zero.  USE says
-    how the lvalue is being used and so selects the error message.  */
- 
- static int
- lvalue_or_else (tree ref, enum lvalue_use use)
- {
-   int win = lvalue_p (ref);
- 
-   if (!win)
-     {
-       switch (use)
- 	{
- 	case lv_assign:
- 	  error ("invalid lvalue in assignment");
- 	  break;
- 	case lv_increment:
- 	  error ("invalid lvalue in increment");
- 	  break;
- 	case lv_decrement:
- 	  error ("invalid lvalue in decrement");
- 	  break;
- 	case lv_addressof:
- 	  error ("invalid lvalue in unary %<&%>");
- 	  break;
- 	case lv_asm:
- 	  error ("invalid lvalue in asm statement");
- 	  break;
- 	default:
- 	  gcc_unreachable ();
- 	}
-     }
- 
-   return win;
- }
- 
  
  /* Give an error for storing in something that is 'const'.  */
  
  static void
  readonly_error (tree arg, enum lvalue_use use)
--- 2700,2709 ----
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.932
diff -c -5 -p -r1.932 toplev.c
*** toplev.c	12 Nov 2004 16:37:40 -0000	1.932
--- toplev.c	25 Nov 2004 16:56:10 -0000
*************** check_global_declarations (tree *vec, in
*** 817,826 ****
--- 817,833 ----
  
    for (i = 0; i < len; i++)
      {
        decl = vec[i];
  
+       /* Do not emit debug information about variables that are in
+ 	 static storage, but not defined.  */
+       if (TREE_CODE (decl) == VAR_DECL
+ 	  && TREE_STATIC (decl)
+ 	  && !TREE_ASM_WRITTEN (decl))
+ 	DECL_IGNORED_P (decl) = 1;
+  
        /* Warn about any function
  	 declared static but not defined.
  	 We don't warn about variables,
  	 because many programs have static variables
  	 that exist only to get some text into the object file.  */
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.689
diff -c -5 -p -r1.689 class.c
*** cp/class.c	9 Nov 2004 10:12:28 -0000	1.689
--- cp/class.c	25 Nov 2004 16:56:16 -0000
*************** instantiate_type (tree lhstype, tree rhs
*** 5862,5871 ****
--- 5862,5880 ----
      }
  
    if (TREE_CODE (rhs) == BASELINK)
      rhs = BASELINK_FUNCTIONS (rhs);
  
+   /* If we are in a template, and have a NON_DEPENDENT_EXPR, we cannot
+      deduce any type information.  */
+   if (TREE_CODE (rhs) == NON_DEPENDENT_EXPR)
+     {
+       if (flags & tf_error)
+ 	error ("not enough type information");
+       return error_mark_node;
+     }
+ 
    /* We don't overwrite rhs if it is an overloaded function.
       Copying it would destroy the tree link.  */
    if (TREE_CODE (rhs) != OVERLOAD)
      rhs = copy_node (rhs);
  
*************** instantiate_type (tree lhstype, tree rhs
*** 5902,5919 ****
        TREE_TYPE (rhs) = unknown_type_node;
        return instantiate_type (lhstype, rhs, flags);
  
      case COMPONENT_REF:
        {
! 	tree addr = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
  
! 	if (addr != error_mark_node
  	    && TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
  	  /* Do not lose object's side effects.  */
! 	  addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr),
! 			 TREE_OPERAND (rhs, 0), addr);
! 	return addr;
        }
  
      case OFFSET_REF:
        rhs = TREE_OPERAND (rhs, 1);
        if (BASELINK_P (rhs))
--- 5911,5929 ----
        TREE_TYPE (rhs) = unknown_type_node;
        return instantiate_type (lhstype, rhs, flags);
  
      case COMPONENT_REF:
        {
! 	tree member = TREE_OPERAND (rhs, 1);
  
! 	member = instantiate_type (lhstype, member, flags);
! 	if (member != error_mark_node
  	    && TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
  	  /* Do not lose object's side effects.  */
! 	  return build2 (COMPOUND_EXPR, TREE_TYPE (member),
! 			 TREE_OPERAND (rhs, 0), member);
! 	return member;
        }
  
      case OFFSET_REF:
        rhs = TREE_OPERAND (rhs, 1);
        if (BASELINK_P (rhs))
*************** instantiate_type (tree lhstype, tree rhs
*** 5941,5956 ****
        return 
  	resolve_address_of_overloaded_function (lhstype, rhs, flags_in,
  						/*template_only=*/false,
  						/*explicit_targs=*/NULL_TREE);
  
-     case TREE_LIST:
-       /* Now we should have a baselink.  */
-       gcc_assert (BASELINK_P (rhs));
- 
-       return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags);
- 
      case CALL_EXPR:
        /* This is too hard for now.  */
        gcc_unreachable ();
  
      case PLUS_EXPR:
--- 5951,5960 ----
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1072
diff -c -5 -p -r1.1072 cp-tree.h
*** cp/cp-tree.h	24 Nov 2004 17:56:44 -0000	1.1072
--- cp/cp-tree.h	25 Nov 2004 16:56:16 -0000
*************** extern int zero_init_p				(tree);
*** 4184,4194 ****
  extern tree canonical_type_variant              (tree);
  extern tree copy_binfo				(tree, tree, tree,
  						 tree *, int);
  extern int member_p				(tree);
  extern cp_lvalue_kind real_lvalue_p             (tree);
- extern int lvalue_or_else			(tree, const char *);
  extern tree build_min				(enum tree_code, tree, ...);
  extern tree build_min_nt			(enum tree_code, ...);
  extern tree build_min_non_dep			(enum tree_code, tree, ...);
  extern tree build_cplus_new			(tree, tree);
  extern tree get_target_expr			(tree);
--- 4184,4193 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1331
diff -c -5 -p -r1.1331 decl.c
*** cp/decl.c	24 Nov 2004 17:56:47 -0000	1.1331
--- cp/decl.c	25 Nov 2004 16:56:16 -0000
*************** duplicate_decls (tree newdecl, tree oldd
*** 1415,1425 ****
        else
  	{
  	  error ("conflicting declaration %q#D", newdecl);
  	  cp_error_at ("%qD has a previous declaration as %q#D",
                         olddecl, olddecl);
!           return NULL_TREE;
  	}
      }
    else if (TREE_CODE (newdecl) == FUNCTION_DECL
  	    && ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
  		 && (!DECL_TEMPLATE_INFO (newdecl)
--- 1415,1425 ----
        else
  	{
  	  error ("conflicting declaration %q#D", newdecl);
  	  cp_error_at ("%qD has a previous declaration as %q#D",
                         olddecl, olddecl);
!           return error_mark_node;
  	}
      }
    else if (TREE_CODE (newdecl) == FUNCTION_DECL
  	    && ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
  		 && (!DECL_TEMPLATE_INFO (newdecl)
*************** grokvardecl (tree type,
*** 5922,5935 ****
               int initialized,
               int constp,
               tree scope)
  {
    tree decl;
  
    gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE);
  
!   /* Compute the scope in which to place the variable.  */
    if (!scope)
      {
        /* An explicit "extern" specifier indicates a namespace-scope
  	 variable.  */
        if (declspecs->storage_class == sc_extern)
--- 5922,5938 ----
               int initialized,
               int constp,
               tree scope)
  {
    tree decl;
+   tree explicit_scope;
  
    gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE);
  
!   /* Compute the scope in which to place the variable, but remember
!      whether or not that scope was explicitly specified by the user.   */
!   explicit_scope = scope;
    if (!scope)
      {
        /* An explicit "extern" specifier indicates a namespace-scope
  	 variable.  */
        if (declspecs->storage_class == sc_extern)
*************** grokvardecl (tree type,
*** 5950,5961 ****
  	  || TYPE_P (scope)))
      decl = build_lang_decl (VAR_DECL, name, type);
    else
      decl = build_decl (VAR_DECL, name, type);
  
!   if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
!     set_decl_namespace (decl, scope, 0);
    else
      DECL_CONTEXT (decl) = scope;
  
    if (declspecs->storage_class == sc_extern)
      {
--- 5953,5964 ----
  	  || TYPE_P (scope)))
      decl = build_lang_decl (VAR_DECL, name, type);
    else
      decl = build_decl (VAR_DECL, name, type);
  
!   if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL)
!     set_decl_namespace (decl, explicit_scope, 0);
    else
      DECL_CONTEXT (decl) = scope;
  
    if (declspecs->storage_class == sc_extern)
      {
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.93
diff -c -5 -p -r1.93 name-lookup.c
*** cp/name-lookup.c	24 Nov 2004 23:18:51 -0000	1.93
--- cp/name-lookup.c	25 Nov 2004 16:56:16 -0000
*************** set_decl_namespace (tree decl, tree scop
*** 3006,3051 ****
    /* It is ok for friends to be qualified in parallel space.  */
    if (!friendp && !is_ancestor (current_namespace, scope))
      error ("declaration of %qD not in a namespace surrounding %qD",
             decl, scope);
    DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
!   if (scope != current_namespace)
      {
!       /* See whether this has been declared in the namespace.  */
!       old = namespace_binding (DECL_NAME (decl), scope);
!       if (!old)
! 	/* No old declaration at all.  */
! 	goto complain;
!       /* A template can be explicitly specialized in any namespace.  */
!       if (processing_explicit_instantiation)
! 	return;
!       if (!is_overloaded_fn (decl))
! 	/* Don't compare non-function decls with decls_match here,
! 	   since it can't check for the correct constness at this
! 	   point. pushdecl will find those errors later.  */
! 	return;
!       /* Since decl is a function, old should contain a function decl.  */
!       if (!is_overloaded_fn (old))
! 	goto complain;
!       if (processing_template_decl || processing_specialization)
! 	/* We have not yet called push_template_decl to turn a
! 	   FUNCTION_DECL into a TEMPLATE_DECL, so the declarations
! 	   won't match.  But, we'll check later, when we construct the
! 	   template.  */
! 	return;
!       if (is_overloaded_fn (old))
! 	{
! 	  for (; old; old = OVL_NEXT (old))
! 	    if (decls_match (decl, OVL_CURRENT (old)))
! 	      return;
! 	}
!       else
! 	if (decls_match (decl, old))
! 	  return;
      }
!   else
      return;
   complain:
    error ("%qD should have been declared inside %qD", decl, scope);
  } 
  
  /* Return the namespace where the current declaration is declared.  */
--- 3006,3055 ----
    /* It is ok for friends to be qualified in parallel space.  */
    if (!friendp && !is_ancestor (current_namespace, scope))
      error ("declaration of %qD not in a namespace surrounding %qD",
             decl, scope);
    DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
! 
!   /* Writing "int N::i" to declare a variable within "N" is invalid.  */ 
!   if (scope == current_namespace) 
      {
!       if (at_namespace_scope_p ())
! 	error ("explicit qualification in declaration of `%D'",
! 	       decl);
!       return;
      }
! 
!   /* See whether this has been declared in the namespace.  */
!   old = namespace_binding (DECL_NAME (decl), scope);
!   if (!old)
!     /* No old declaration at all.  */
!     goto complain;
!   /* A template can be explicitly specialized in any namespace.  */
!   if (processing_explicit_instantiation)
!     return;
!   if (!is_overloaded_fn (decl))
!     /* Don't compare non-function decls with decls_match here, since
!        it can't check for the correct constness at this
!        point. pushdecl will find those errors later.  */
      return;
+   /* Since decl is a function, old should contain a function decl.  */
+   if (!is_overloaded_fn (old))
+     goto complain;
+   if (processing_template_decl || processing_specialization)
+     /* We have not yet called push_template_decl to turn a
+        FUNCTION_DECL into a TEMPLATE_DECL, so the declarations won't
+        match.  But, we'll check later, when we construct the
+        template.  */
+     return;
+   if (is_overloaded_fn (old))
+     {
+       for (; old; old = OVL_NEXT (old))
+ 	if (decls_match (decl, OVL_CURRENT (old)))
+ 	  return;
+     }
+   else if (decls_match (decl, old))
+       return;
   complain:
    error ("%qD should have been declared inside %qD", decl, scope);
  } 
  
  /* Return the namespace where the current declaration is declared.  */
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.947
diff -c -5 -p -r1.947 pt.c
*** cp/pt.c	24 Nov 2004 18:45:31 -0000	1.947
--- cp/pt.c	25 Nov 2004 16:56:16 -0000
*************** build_non_dependent_expr (tree expr)
*** 12293,12302 ****
--- 12293,12305 ----
    if (TREE_CODE (inner_expr) == OVERLOAD 
        || TREE_CODE (inner_expr) == FUNCTION_DECL
        || TREE_CODE (inner_expr) == TEMPLATE_DECL
        || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR)
      return expr;
+   /* There is no need to return a proxy for a variable.  */
+   if (TREE_CODE (expr) == VAR_DECL)
+     return expr;
    /* Preserve string constants; conversions from string constants to
       "char *" are allowed, even though normally a "const char *"
       cannot be used to initialize a "char *".  */
    if (TREE_CODE (expr) == STRING_CST)
      return expr;
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.419
diff -c -5 -p -r1.419 tree.c
*** cp/tree.c	12 Nov 2004 21:47:09 -0000	1.419
--- cp/tree.c	25 Nov 2004 16:56:16 -0000
*************** lvalue_p (tree ref)
*** 213,236 ****
  {
    return
      (lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
  }
  
- /* Return nonzero if REF is an lvalue valid for this language;
-    otherwise, print an error message and return zero.  */
- 
- int
- lvalue_or_else (tree ref, const char* string)
- {
-   if (!lvalue_p (ref))
-     {
-       error ("non-lvalue in %s", string);
-       return 0;
-     }
-   return 1;
- }
- 
  /* Build a TARGET_EXPR, initializing the DECL with the VALUE.  */
  
  static tree
  build_target_expr (tree decl, tree value)
  {
--- 213,222 ----
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.598
diff -c -5 -p -r1.598 typeck.c
*** cp/typeck.c	24 Nov 2004 10:06:46 -0000	1.598
--- cp/typeck.c	25 Nov 2004 16:56:16 -0000
*************** build_unary_op (enum tree_code code, tre
*** 3954,3964 ****
  	  }
  
  	/* Complain about anything else that is not a true lvalue.  */
  	if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
  				    || code == POSTINCREMENT_EXPR)
! 				   ? "increment" : "decrement")))
  	  return error_mark_node;
  
  	/* Forbid using -- on `bool'.  */
  	if (TREE_TYPE (arg) == boolean_type_node)
  	  {
--- 3954,3964 ----
  	  }
  
  	/* Complain about anything else that is not a true lvalue.  */
  	if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
  				    || code == POSTINCREMENT_EXPR)
! 				   ? lv_increment : lv_decrement)))
  	  return error_mark_node;
  
  	/* Forbid using -- on `bool'.  */
  	if (TREE_TYPE (arg) == boolean_type_node)
  	  {
*************** build_unary_op (enum tree_code code, tre
*** 4098,4108 ****
  	;
        /* Anything not already handled and not a true memory reference
  	 is an error.  */
        else if (TREE_CODE (argtype) != FUNCTION_TYPE
  	       && TREE_CODE (argtype) != METHOD_TYPE
! 	       && !lvalue_or_else (arg, "unary %<&$>"))
  	return error_mark_node;
  
        if (argtype != error_mark_node)
  	argtype = build_pointer_type (argtype);
  
--- 4098,4108 ----
  	;
        /* Anything not already handled and not a true memory reference
  	 is an error.  */
        else if (TREE_CODE (argtype) != FUNCTION_TYPE
  	       && TREE_CODE (argtype) != METHOD_TYPE
! 	       && !lvalue_or_else (arg, lv_addressof))
  	return error_mark_node;
  
        if (argtype != error_mark_node)
  	argtype = build_pointer_type (argtype);
  
*************** build_modify_expr (tree lhs, enum tree_c
*** 5292,5302 ****
  
      case MIN_EXPR:
      case MAX_EXPR:
        /* MIN_EXPR and MAX_EXPR are currently only permitted as lvalues,
  	 when neither operand has side-effects.  */
!       if (!lvalue_or_else (lhs, "assignment"))
  	return error_mark_node;
  
        gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))
  		  && !TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 1)));
  
--- 5292,5302 ----
  
      case MIN_EXPR:
      case MAX_EXPR:
        /* MIN_EXPR and MAX_EXPR are currently only permitted as lvalues,
  	 when neither operand has side-effects.  */
!       if (!lvalue_or_else (lhs, lv_assign))
  	return error_mark_node;
  
        gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))
  		  && !TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 1)));
  
*************** build_modify_expr (tree lhs, enum tree_c
*** 5320,5330 ****
  
  	rhs = stabilize_expr (rhs, &preeval);
  	
  	/* Check this here to avoid odd errors when trying to convert
  	   a throw to the type of the COND_EXPR.  */
! 	if (!lvalue_or_else (lhs, "assignment"))
  	  return error_mark_node;
  
  	cond = build_conditional_expr
  	  (TREE_OPERAND (lhs, 0),
  	   build_modify_expr (cp_convert (TREE_TYPE (lhs),
--- 5320,5330 ----
  
  	rhs = stabilize_expr (rhs, &preeval);
  	
  	/* Check this here to avoid odd errors when trying to convert
  	   a throw to the type of the COND_EXPR.  */
! 	if (!lvalue_or_else (lhs, lv_assign))
  	  return error_mark_node;
  
  	cond = build_conditional_expr
  	  (TREE_OPERAND (lhs, 0),
  	   build_modify_expr (cp_convert (TREE_TYPE (lhs),
*************** build_modify_expr (tree lhs, enum tree_c
*** 5419,5429 ****
        gcc_assert (TREE_CODE (lhstype) != REFERENCE_TYPE);
        gcc_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE);
      }
  
    /* The left-hand side must be an lvalue.  */
!   if (!lvalue_or_else (lhs, "assignment"))
      return error_mark_node;
  
    /* Warn about modifying something that is `const'.  Don't warn if
       this is initialization.  */
    if (modifycode != INIT_EXPR
--- 5419,5429 ----
        gcc_assert (TREE_CODE (lhstype) != REFERENCE_TYPE);
        gcc_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE);
      }
  
    /* The left-hand side must be an lvalue.  */
!   if (!lvalue_or_else (lhs, lv_assign))
      return error_mark_node;
  
    /* Warn about modifying something that is `const'.  Don't warn if
       this is initialization.  */
    if (modifycode != INIT_EXPR
*************** check_return_expr (tree retval)
*** 6228,6237 ****
--- 6228,6246 ----
      current_function_returns_null = 1;
    else
      /* Remember that this function did return a value.  */
      current_function_returns_value = 1;
  
+   /* Check for errnoneous operands -- but after giving ourselves a
+      chance to provide an error about returning a value from a void
+      function.  */
+   if (error_operand_p (retval))
+     {
+       current_function_return_value = error_mark_node;
+       return error_mark_node;
+     }
+ 
    /* Only operator new(...) throw(), can return NULL [expr.new/13].  */
    if ((DECL_OVERLOADED_OPERATOR_P (current_function_decl) == NEW_EXPR
         || DECL_OVERLOADED_OPERATOR_P (current_function_decl) == VEC_NEW_EXPR)
        && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
        && ! flag_check_new
*************** check_return_expr (tree retval)
*** 6303,6314 ****
  	current_function_return_value = error_mark_node;
      }
  
    /* We don't need to do any conversions when there's nothing being
       returned.  */
!   if (!retval || retval == error_mark_node)
!     return retval;
  
    /* Do any required conversions.  */
    if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl))
      /* No conversions are required.  */
      ;
--- 6312,6323 ----
  	current_function_return_value = error_mark_node;
      }
  
    /* We don't need to do any conversions when there's nothing being
       returned.  */
!   if (!retval)
!     return NULL_TREE;
  
    /* Do any required conversions.  */
    if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl))
      /* No conversions are required.  */
      ;
Index: testsuite/g++.dg/expr/return1.C
===================================================================
RCS file: testsuite/g++.dg/expr/return1.C
diff -N testsuite/g++.dg/expr/return1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/return1.C	25 Nov 2004 16:56:28 -0000
***************
*** 0 ****
--- 1,9 ----
+ // PR c++/18545
+ 
+ struct A;
+ 
+ A foo()  // { dg-error "" }
+ {
+   A a; // { dg-error "" }
+   return a;
+ }
Index: testsuite/g++.dg/expr/unary2.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/expr/unary2.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 unary2.C
*** testsuite/g++.dg/expr/unary2.C	14 Nov 2004 10:58:50 -0000	1.1
--- testsuite/g++.dg/expr/unary2.C	25 Nov 2004 16:56:28 -0000
***************
*** 6,20 ****
  
  int n;
  
  void f(void)
  {
!   -n = 0;        // { dg-error "non-lvalue" }
!   +n = 0;        // { dg-error "non-lvalue" }
  }
  
  template <int>
  void g(void)
  {
!   -n = 0;        // { dg-error "non-lvalue" "" { xfail *-*-* } }
!   +n = 0;        // { dg-error "non-lvalue" "" { xfail *-*-* } }
  }
--- 6,20 ----
  
  int n;
  
  void f(void)
  {
!   -n = 0;        // { dg-error "lvalue" }
!   +n = 0;        // { dg-error "lvalue" }
  }
  
  template <int>
  void g(void)
  {
!   -n = 0;        // { dg-error "lvalue" "" { xfail *-*-* } }
!   +n = 0;        // { dg-error "lvalue" "" { xfail *-*-* } }
  }
Index: testsuite/g++.dg/ext/lvaddr.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/ext/lvaddr.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 lvaddr.C
*** testsuite/g++.dg/ext/lvaddr.C	25 Aug 2002 04:57:16 -0000	1.1
--- testsuite/g++.dg/ext/lvaddr.C	25 Nov 2004 16:56:28 -0000
***************
*** 4,10 ****
  // { dg-do compile }
  
  void f()
  {
    int n;
!   char* p = &(char) n;		// { dg-error "non-lvalue" }
  }
--- 4,10 ----
  // { dg-do compile }
  
  void f()
  {
    int n;
!   char* p = &(char) n;		// { dg-error "lvalue" }
  }
Index: testsuite/g++.dg/opt/pr7503-3.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/opt/pr7503-3.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 pr7503-3.C
*** testsuite/g++.dg/opt/pr7503-3.C	21 Sep 2004 16:20:12 -0000	1.1
--- testsuite/g++.dg/opt/pr7503-3.C	25 Nov 2004 16:56:28 -0000
***************
*** 4,26 ****
  
  extern int A, B;
  
  void test1()
  {
!   (A++ <? B) = 0;  // { dg-error "non-lvalue in assignment" }
  }
  
  void test2()
  {
!   (A <? B++) = 0;  // { dg-error "non-lvalue in assignment" }
  }
  
  void test3()
  {
!   (A++ >? B) = 0;  // { dg-error "non-lvalue in assignment" }
  }
  
  void test4()
  {
!   (A >? B++) = 0;  // { dg-error "non-lvalue in assignment" }
  }
  
--- 4,26 ----
  
  extern int A, B;
  
  void test1()
  {
!   (A++ <? B) = 0;  // { dg-error "lvalue in assignment" }
  }
  
  void test2()
  {
!   (A <? B++) = 0;  // { dg-error "lvalue in assignment" }
  }
  
  void test3()
  {
!   (A++ >? B) = 0;  // { dg-error "lvalue in assignment" }
  }
  
  void test4()
  {
!   (A >? B++) = 0;  // { dg-error "lvalue in assignment" }
  }
  
Index: testsuite/g++.dg/parse/qualified3.C
===================================================================
RCS file: testsuite/g++.dg/parse/qualified3.C
diff -N testsuite/g++.dg/parse/qualified3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/qualified3.C	25 Nov 2004 16:56:28 -0000
***************
*** 0 ****
--- 1,8 ----
+ // PR c++/18466
+ 
+ int ::i; // { dg-error "" }
+ void ::f(); // { dg-error "" }
+ namespace N {
+   int N::j; // { dg-error "" }
+   void N::g(); // { dg-error "" }
+ }
Index: testsuite/g++.dg/template/crash28.C
===================================================================
RCS file: testsuite/g++.dg/template/crash28.C
diff -N testsuite/g++.dg/template/crash28.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/crash28.C	25 Nov 2004 16:56:28 -0000
***************
*** 0 ****
--- 1,13 ----
+ // PR c++/18445
+ 
+ struct a
+ {
+   int what();
+ };
+ void g(void*);
+ template<class T>
+ void f()
+ {
+   a ex;
+   g(ex.what); // { dg-error "" }
+ }
Index: testsuite/g++.old-deja/g++.other/friend7.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.other/friend7.C,v
retrieving revision 1.2
diff -c -5 -p -r1.2 friend7.C
*** testsuite/g++.old-deja/g++.other/friend7.C	1 May 2003 02:02:49 -0000	1.2
--- testsuite/g++.old-deja/g++.other/friend7.C	25 Nov 2004 16:56:34 -0000
*************** class S {
*** 13,21 ****
    void Fn(); 
    static S s;
  };
  } 
  
! void (::foo)(M::S *ptr) {
    M::S::s.Fn();
    ptr->Fn();
  } 
--- 13,21 ----
    void Fn(); 
    static S s;
  };
  } 
  
! void (foo)(M::S *ptr) {
    M::S::s.Fn();
    ptr->Fn();
  } 


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