diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f59688e0fe733fee36d6a0d82f98c671cb89e441..3c622f75512ad054e126b6e1a9b6075322b59bd0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,27 @@
+2009-04-21  Eric Botcazou  <ebotcazou@adacore.com>
+
+	* c-common.c (c_common_truthvalue_conversion): Use LOCATION to build
+	NE_EXPR operations as well.
+	* c-parser.c (c_parser_condition): Do not set location information on
+	the condition.
+	(c_parser_conditional_expression): Likewise.
+	(c_parser_binary_expression): Set location information on operators.
+	* c-typeck.c (build_unary_op) <TRUTH_NOT_EXPR>: Reset the location if
+	TRUTH_NOT_EXPR has been folded.
+	* fold-const.c (fold_truth_not_expr): Copy location information from
+	the incoming expression to the outgoing one.
+	* gimplify.c (shortcut_cond_r): Add locus parameter.  Pass it to
+	recursive calls on the LHS of the operator but pass that of the
+	operator to recursive calls on the RHS of the operator.  Set it
+	on the COND_EXPR.
+	(shortcut_cond_expr): Set the locus of the operator on the second
+	COND_EXPR and that of the expression on the first in degenerate cases.
+	Pass the locus of the expression to calls to shortcut_cond_r.
+	Set the locus of the 'then' block on the associated jump, if any.
+	(gimplify_boolean_expr): Add locus parameter.  Set it on the COND_EXPR.
+	(gimplify_expr) <TRUTH_ANDIF_EXPR>: Pass the locus of the outer
+	expression to call to gimplify_boolean_expr.
+
 2009-04-21  Kai Tietz  <kai.tietz@onevision.com>
 
 	* config.gcc: Add additional configuration for
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index a8e01f0eae766de979bf9b545bffec15af21fef1..6f31dbd3e3d29b729e844a4c478466e2ee390dd0 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,7 @@
+2009-04-21  Eric Botcazou  <ebotcazou@adacore.com>
+
+	* gcc-interface/trans.c (gnat_to_gnu): Do not overwrite location info.
+
 2009-04-21  Eric Botcazou  <ebotcazou@adacore.com>
 
 	* gcc-interface/ada-tree.h (TYPE_RM_SIZE_NUM): Delete.
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 50e3fca20e19aadd2c667f641c8c7ff9712b0c19..84aa3963910a080cd20982d84d7ecfa3e7437b98 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -5303,7 +5303,8 @@ gnat_to_gnu (Node_Id gnat_node)
   if (gnu_result
       && EXPR_P (gnu_result)
       && TREE_CODE (gnu_result) != NOP_EXPR
-      && !REFERENCE_CLASS_P (gnu_result))
+      && !REFERENCE_CLASS_P (gnu_result)
+      && !EXPR_HAS_LOCATION (gnu_result))
     set_expr_location_from_node (gnu_result, gnat_node);
 
   /* If we're supposed to return something of void_type, it means we have
diff --git a/gcc/c-common.c b/gcc/c-common.c
index eab4582b8e08de3dd8b7716e558013fdf243ea91..3595e552966f0f20e709a5dc514cdd12611edd05 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -4114,12 +4114,10 @@ c_common_truthvalue_conversion (location_t location, tree expr)
       tree fixed_zero_node = build_fixed (TREE_TYPE (expr),
 					  FCONST0 (TYPE_MODE
 						   (TREE_TYPE (expr))));
-      return build_binary_op (EXPR_LOCATION (expr),
-			      NE_EXPR, expr, fixed_zero_node, 1);
+      return build_binary_op (location, NE_EXPR, expr, fixed_zero_node, 1);
     }
 
-  return build_binary_op (EXPR_LOCATION (expr),
-			  NE_EXPR, expr, integer_zero_node, 1);
+  return build_binary_op (location, NE_EXPR, expr, integer_zero_node, 1);
 }
 
 static void def_builtin_1  (enum built_in_function fncode,
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index ca51d95eed50ea5c8dd1a3821e216d70d8bad25b..676c709cdf2f179a3c7c142c35808fbd76ad8949 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -3835,7 +3835,6 @@ c_parser_condition (c_parser *parser)
   cond = c_parser_expression_conv (parser).value;
   cond = c_objc_common_truthvalue_conversion (loc, cond);
   cond = c_fully_fold (cond, false, NULL);
-  protected_set_expr_location (cond, loc);
   if (warn_sequence_point)
     verify_sequence_points (cond);
   return cond;
@@ -4479,7 +4478,6 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
 
   cond_loc = c_parser_peek_token (parser)->location;
   cond = c_parser_binary_expression (parser, after);
-  protected_set_expr_location (cond.value, cond_loc);
 
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
@@ -4651,6 +4649,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
     enum prec prec;
     /* The operation on its left.  */
     enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
   } stack[NUM_PRECS];
   int sp;
   /* Location of the binary operator.  */
@@ -4672,13 +4672,14 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
       = default_function_array_conversion (stack[sp - 1].expr);		      \
     stack[sp].expr							      \
       = default_function_array_conversion (stack[sp].expr);		      \
-    stack[sp - 1].expr = parser_build_binary_op (binary_loc,		      \
+    stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,		      \
 						 stack[sp].op,		      \
 						 stack[sp - 1].expr,	      \
 						 stack[sp].expr);	      \
     sp--;								      \
   } while (0)
   gcc_assert (!after || c_dialect_objc ());
+  stack[0].loc = c_parser_peek_token (parser)->location;
   stack[0].expr = c_parser_cast_expression (parser, after);
   stack[0].prec = PREC_NONE;
   sp = 0;
@@ -4777,20 +4778,21 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after)
 	  stack[sp].expr
 	    = default_function_array_conversion (stack[sp].expr);
 	  stack[sp].expr.value = c_objc_common_truthvalue_conversion
-	    (binary_loc, default_conversion (stack[sp].expr.value));
+	    (stack[sp].loc, default_conversion (stack[sp].expr.value));
 	  skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
 	  break;
 	case TRUTH_ORIF_EXPR:
 	  stack[sp].expr
 	    = default_function_array_conversion (stack[sp].expr);
 	  stack[sp].expr.value = c_objc_common_truthvalue_conversion
-	    (binary_loc, default_conversion (stack[sp].expr.value));
+	    (stack[sp].loc, default_conversion (stack[sp].expr.value));
 	  skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
 	  break;
 	default:
 	  break;
 	}
       sp++;
+      stack[sp].loc = binary_loc;
       stack[sp].expr = c_parser_cast_expression (parser, NULL);
       stack[sp].prec = oprec;
       stack[sp].op = ocode;
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index f5cfc6440d382f5f1f53cb1ff8fbe84cbc5fa455..1ff6e9b744d62cf7c9805ab524008f0ee70a4c6c 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -3209,6 +3209,9 @@ build_unary_op (location_t location,
 	}
       arg = c_objc_common_truthvalue_conversion (location, arg);
       ret = invert_truthvalue (arg);
+      /* If the TRUTH_NOT_EXPR has been folded, reset the location.  */
+      if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret))
+	location = EXPR_LOCATION (ret);
       goto return_build_unary_op;
 
     case REALPART_EXPR:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index bd5e97df4a92b622ae27c6620ee500b197ecf6d1..ca07cf16720427edfad48c1e39044ede0fccbdc9 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3641,7 +3641,7 @@ omit_two_operands (tree type, tree result, tree omitted1, tree omitted2)
 tree
 fold_truth_not_expr (tree arg)
 {
-  tree type = TREE_TYPE (arg);
+  tree t, type = TREE_TYPE (arg);
   enum tree_code code = TREE_CODE (arg);
 
   /* If this is a comparison, we can simply invert it, except for
@@ -3656,16 +3656,15 @@ fold_truth_not_expr (tree arg)
 	  && code != ORDERED_EXPR && code != UNORDERED_EXPR
 	  && code != NE_EXPR && code != EQ_EXPR)
 	return NULL_TREE;
-      else
-	{
-	  code = invert_tree_comparison (code,
-					 HONOR_NANS (TYPE_MODE (op_type)));
-	  if (code == ERROR_MARK)
-	    return NULL_TREE;
-	  else
-	    return build2 (code, type,
-			   TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
-	}
+
+      code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (op_type)));
+      if (code == ERROR_MARK)
+	return NULL_TREE;
+
+      t = build2 (code, type, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
+      if (EXPR_HAS_LOCATION (arg))
+	SET_EXPR_LOCATION (t, EXPR_LOCATION (arg));
+      return t;
     }
 
   switch (code)
@@ -3674,14 +3673,16 @@ fold_truth_not_expr (tree arg)
       return constant_boolean_node (integer_zerop (arg), type);
 
     case TRUTH_AND_EXPR:
-      return build2 (TRUTH_OR_EXPR, type,
-		     invert_truthvalue (TREE_OPERAND (arg, 0)),
-		     invert_truthvalue (TREE_OPERAND (arg, 1)));
+      t = build2 (TRUTH_OR_EXPR, type,
+		  invert_truthvalue (TREE_OPERAND (arg, 0)),
+		  invert_truthvalue (TREE_OPERAND (arg, 1)));
+      break;
 
     case TRUTH_OR_EXPR:
-      return build2 (TRUTH_AND_EXPR, type,
-		     invert_truthvalue (TREE_OPERAND (arg, 0)),
-		     invert_truthvalue (TREE_OPERAND (arg, 1)));
+      t = build2 (TRUTH_AND_EXPR, type,
+		  invert_truthvalue (TREE_OPERAND (arg, 0)),
+		  invert_truthvalue (TREE_OPERAND (arg, 1)));
+      break;
 
     case TRUTH_XOR_EXPR:
       /* Here we can invert either operand.  We invert the first operand
@@ -3690,22 +3691,25 @@ fold_truth_not_expr (tree arg)
 	 negation of the second operand.  */
 
       if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
-	return build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
-		       TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
+	t = build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
+		    TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
       else
-	return build2 (TRUTH_XOR_EXPR, type,
-		       invert_truthvalue (TREE_OPERAND (arg, 0)),
-		       TREE_OPERAND (arg, 1));
+	t = build2 (TRUTH_XOR_EXPR, type,
+		    invert_truthvalue (TREE_OPERAND (arg, 0)),
+		    TREE_OPERAND (arg, 1));
+      break;
 
     case TRUTH_ANDIF_EXPR:
-      return build2 (TRUTH_ORIF_EXPR, type,
-		     invert_truthvalue (TREE_OPERAND (arg, 0)),
-		     invert_truthvalue (TREE_OPERAND (arg, 1)));
+      t = build2 (TRUTH_ORIF_EXPR, type,
+		  invert_truthvalue (TREE_OPERAND (arg, 0)),
+		  invert_truthvalue (TREE_OPERAND (arg, 1)));
+      break;
 
     case TRUTH_ORIF_EXPR:
-      return build2 (TRUTH_ANDIF_EXPR, type,
-		     invert_truthvalue (TREE_OPERAND (arg, 0)),
-		     invert_truthvalue (TREE_OPERAND (arg, 1)));
+      t = build2 (TRUTH_ANDIF_EXPR, type,
+		  invert_truthvalue (TREE_OPERAND (arg, 0)),
+		  invert_truthvalue (TREE_OPERAND (arg, 1)));
+      break;
 
     case TRUTH_NOT_EXPR:
       return TREE_OPERAND (arg, 0);
@@ -3717,47 +3721,61 @@ fold_truth_not_expr (tree arg)
 	/* A COND_EXPR may have a throw as one operand, which
 	   then has void type.  Just leave void operands
 	   as they are.  */
-	return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
-		       VOID_TYPE_P (TREE_TYPE (arg1))
-		       ? arg1 : invert_truthvalue (arg1),
-		       VOID_TYPE_P (TREE_TYPE (arg2))
-		       ? arg2 : invert_truthvalue (arg2));
+	t = build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
+		    VOID_TYPE_P (TREE_TYPE (arg1))
+		    ? arg1 : invert_truthvalue (arg1),
+		    VOID_TYPE_P (TREE_TYPE (arg2))
+		    ? arg2 : invert_truthvalue (arg2));
+	break;
       }
 
     case COMPOUND_EXPR:
-      return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
-		     invert_truthvalue (TREE_OPERAND (arg, 1)));
+      t = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
+		  invert_truthvalue (TREE_OPERAND (arg, 1)));
+      break;
 
     case NON_LVALUE_EXPR:
       return invert_truthvalue (TREE_OPERAND (arg, 0));
 
     case NOP_EXPR:
       if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
-	return build1 (TRUTH_NOT_EXPR, type, arg);
+	{
+	  t = build1 (TRUTH_NOT_EXPR, type, arg);
+	  break;
+	}
+
+      /* ... fall through ...  */
 
     case CONVERT_EXPR:
     case FLOAT_EXPR:
-      return build1 (TREE_CODE (arg), type,
-		     invert_truthvalue (TREE_OPERAND (arg, 0)));
+      t = build1 (TREE_CODE (arg), type,
+		  invert_truthvalue (TREE_OPERAND (arg, 0)));
+      break;
 
     case BIT_AND_EXPR:
       if (!integer_onep (TREE_OPERAND (arg, 1)))
-	break;
-      return build2 (EQ_EXPR, type, arg,
-		     build_int_cst (type, 0));
+	return NULL_TREE;
+      t = build2 (EQ_EXPR, type, arg, build_int_cst (type, 0));
+      break;
 
     case SAVE_EXPR:
-      return build1 (TRUTH_NOT_EXPR, type, arg);
+      t = build1 (TRUTH_NOT_EXPR, type, arg);
+      break;
 
     case CLEANUP_POINT_EXPR:
-      return build1 (CLEANUP_POINT_EXPR, type,
-		     invert_truthvalue (TREE_OPERAND (arg, 0)));
+      t = build1 (CLEANUP_POINT_EXPR, type,
+		  invert_truthvalue (TREE_OPERAND (arg, 0)));
+      break;
 
     default:
+      t = NULL_TREE;
       break;
     }
 
-  return NULL_TREE;
+  if (t && EXPR_HAS_LOCATION (arg))
+    SET_EXPR_LOCATION (t, EXPR_LOCATION (arg));
+
+  return t;
 }
 
 /* Return a simplified tree node for the truth-negation of ARG.  This
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 515c58ed57e9ead1a1dcd66f262daa2d7bb08116..993f7c2ae449bb698d4172c8cf0c3b1591e27dd6 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2449,12 +2449,15 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
    condition is true or false, respectively.  If null, we should generate
    our own to skip over the evaluation of this specific expression.
 
+   LOCUS is the source location of the COND_EXPR.
+
    This function is the tree equivalent of do_jump.
 
    shortcut_cond_r should only be called by shortcut_cond_expr.  */
 
 static tree
-shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
+shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
+		 location_t locus)
 {
   tree local_label = NULL_TREE;
   tree t, expr = NULL;
@@ -2464,6 +2467,8 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
      shortcut_cond_expr will append the real blocks later.  */
   if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
     {
+      location_t new_locus;
+
       /* Turn if (a && b) into
 
 	 if (a); else goto no;
@@ -2473,15 +2478,20 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
       if (false_label_p == NULL)
 	false_label_p = &local_label;
 
-      t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p);
+      /* Keep the original source location on the first 'if'.  */
+      t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus);
       append_to_statement_list (t, &expr);
 
-      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
-			   false_label_p);
+      /* Set the source location of the && on the second 'if'.  */
+      new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
+      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
+			   new_locus);
       append_to_statement_list (t, &expr);
     }
   else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
     {
+      location_t new_locus;
+
       /* Turn if (a || b) into
 
 	 if (a) goto yes;
@@ -2491,31 +2501,41 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
       if (true_label_p == NULL)
 	true_label_p = &local_label;
 
-      t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL);
+      /* Keep the original source location on the first 'if'.  */
+      t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus);
       append_to_statement_list (t, &expr);
 
-      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
-			   false_label_p);
+      /* Set the source location of the || on the second 'if'.  */
+      new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
+      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
+			   new_locus);
       append_to_statement_list (t, &expr);
     }
   else if (TREE_CODE (pred) == COND_EXPR)
     {
+      location_t new_locus;
+
       /* As long as we're messing with gotos, turn if (a ? b : c) into
 	 if (a)
 	   if (b) goto yes; else goto no;
 	 else
 	   if (c) goto yes; else goto no;  */
+
+      /* Keep the original source location on the first 'if'.  Set the source
+	 location of the ? on the second 'if'.  */
+      new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
       expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
 		     shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
-				      false_label_p),
+				      false_label_p, locus),
 		     shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
-				      false_label_p));
+				      false_label_p, new_locus));
     }
   else
     {
       expr = build3 (COND_EXPR, void_type_node, pred,
 		     build_and_jump (true_label_p),
 		     build_and_jump (false_label_p));
+      SET_EXPR_LOCATION (expr, locus);
     }
 
   if (local_label)
@@ -2547,14 +2567,24 @@ shortcut_cond_expr (tree expr)
   /* First do simple transformations.  */
   if (!else_se)
     {
-      /* If there is no 'else', turn (a && b) into if (a) if (b).  */
+      /* If there is no 'else', turn
+	   if (a && b) then c
+	 into
+	   if (a) if (b) then c.  */
       while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
 	{
+	  /* Keep the original source location on the first 'if'.  */
+	  location_t locus = EXPR_HAS_LOCATION (expr)
+			     ? EXPR_LOCATION (expr) : input_location;
 	  TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
+	  /* Set the source location of the && on the second 'if'.  */
+	  if (EXPR_HAS_LOCATION (pred))
+	    SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
 	  then_ = shortcut_cond_expr (expr);
 	  then_se = then_ && TREE_SIDE_EFFECTS (then_);
 	  pred = TREE_OPERAND (pred, 0);
 	  expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
+	  SET_EXPR_LOCATION (expr, locus);
 	}
     }
 
@@ -2566,11 +2596,18 @@ shortcut_cond_expr (tree expr)
 	   if (a); else if (b); else d.  */
       while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
 	{
+	  /* Keep the original source location on the first 'if'.  */
+	  location_t locus = EXPR_HAS_LOCATION (expr)
+			     ? EXPR_LOCATION (expr) : input_location;
 	  TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
+	  /* Set the source location of the || on the second 'if'.  */
+	  if (EXPR_HAS_LOCATION (pred))
+	    SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
 	  else_ = shortcut_cond_expr (expr);
 	  else_se = else_ && TREE_SIDE_EFFECTS (else_);
 	  pred = TREE_OPERAND (pred, 0);
 	  expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
+	  SET_EXPR_LOCATION (expr, locus);
 	}
     }
 
@@ -2624,17 +2661,19 @@ shortcut_cond_expr (tree expr)
 
   /* If there was nothing else in our arms, just forward the label(s).  */
   if (!then_se && !else_se)
-    return shortcut_cond_r (pred, true_label_p, false_label_p);
+    return shortcut_cond_r (pred, true_label_p, false_label_p,
+			    EXPR_HAS_LOCATION (expr)
+			    ? EXPR_LOCATION (expr) : input_location);
 
   /* If our last subexpression already has a terminal label, reuse it.  */
   if (else_se)
-    expr = expr_last (else_);
+    t = expr_last (else_);
   else if (then_se)
-    expr = expr_last (then_);
+    t = expr_last (then_);
   else
-    expr = NULL;
-  if (expr && TREE_CODE (expr) == LABEL_EXPR)
-    end_label = LABEL_EXPR_LABEL (expr);
+    t = NULL;
+  if (t && TREE_CODE (t) == LABEL_EXPR)
+    end_label = LABEL_EXPR_LABEL (t);
 
   /* If we don't care about jumping to the 'else' branch, jump to the end
      if the condition is false.  */
@@ -2655,7 +2694,9 @@ shortcut_cond_expr (tree expr)
      non-void function.  */
   jump_over_else = block_may_fallthru (then_);
 
-  pred = shortcut_cond_r (pred, true_label_p, false_label_p);
+  pred = shortcut_cond_r (pred, true_label_p, false_label_p,
+			  EXPR_HAS_LOCATION (expr)
+			  ? EXPR_LOCATION (expr) : input_location);
 
   expr = NULL;
   append_to_statement_list (pred, &expr);
@@ -2665,7 +2706,10 @@ shortcut_cond_expr (tree expr)
     {
       if (jump_over_else)
 	{
+	  tree last = expr_last (expr);
 	  t = build_and_jump (&end_label);
+	  if (EXPR_HAS_LOCATION (last))
+	    SET_EXPR_LOCATION (t, EXPR_LOCATION (last));
 	  append_to_statement_list (t, &expr);
 	}
       if (emit_false)
@@ -4428,13 +4472,11 @@ gimplify_scalar_mode_aggregate_compare (tree *expr_p)
 
 	a && b ? true : false
 
-    gimplify_cond_expr will do the rest.
-
-    PRE_P points to the list where side effects that must happen before
-	*EXPR_P should be stored.  */
+    LOCUS is the source location to be put on the generated COND_EXPR.
+    gimplify_cond_expr will do the rest.  */
 
 static enum gimplify_status
-gimplify_boolean_expr (tree *expr_p)
+gimplify_boolean_expr (tree *expr_p, location_t locus)
 {
   /* Preserve the original type of the expression.  */
   tree type = TREE_TYPE (*expr_p);
@@ -4443,6 +4485,8 @@ gimplify_boolean_expr (tree *expr_p)
 		    fold_convert (type, boolean_true_node),
 		    fold_convert (type, boolean_false_node));
 
+  SET_EXPR_LOCATION (*expr_p, locus);
+
   return GS_OK;
 }
 
@@ -6430,7 +6474,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
 	case TRUTH_ANDIF_EXPR:
 	case TRUTH_ORIF_EXPR:
-	  ret = gimplify_boolean_expr (expr_p);
+	  /* Pass the source location of the outer expression.  */
+	  ret = gimplify_boolean_expr (expr_p, saved_location);
 	  break;
 
 	case TRUTH_NOT_EXPR:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 066f4ea26c83b835d6227b3b1f77e9012502c868..697da24fec6904e06dbfb80f7e5247f143965fa3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2009-04-21  Eric Botcazou  <ebotcazou@adacore.com>
+
+	* gcc.dg/debug/dwarf2/short-circuit.c: New test.
+
 2009-04-21  Richard Guenther  <rguenther@suse.de>
 
 	PR middle-end/39829
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/short-circuit.c b/gcc/testsuite/gcc.dg/debug/dwarf2/short-circuit.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e745ff19d2ba1802152cbe87d5d776774d7c19f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/short-circuit.c
@@ -0,0 +1,108 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -gdwarf-2 -dA" } */
+
+#define True  1
+#define False 0
+
+_Bool F1 (_Bool B1, _Bool B2)
+{
+  _Bool R;
+
+  if (B1
+      && B2)
+    R = True;
+  else
+    R = False;
+  return R;
+}
+
+_Bool F2 (_Bool B1, _Bool B2)
+{
+  _Bool R;
+
+  R = B1
+      && B2;
+  return R;
+}
+
+_Bool F3 (_Bool B1, _Bool B2)
+{
+  _Bool R = False;
+
+  if (B1
+      && B2)
+    R = True;
+  return R;
+}
+
+_Bool F4 (_Bool B1, _Bool B2)
+{
+  _Bool R = False;
+
+  if (B1
+      || B2)
+    ;
+  else
+    R = True;
+  return R;
+}
+
+_Bool F5 (_Bool B1, _Bool B2)
+{
+  _Bool R = False;
+
+  if (!(B1
+        && B2))
+    R = True;
+  return R;
+}
+
+_Bool F8 (_Bool B1, _Bool B2, _Bool B3, _Bool B4, _Bool B5, _Bool B6,
+          _Bool B7, _Bool B8)
+{
+  _Bool R;
+
+  if ((B1
+       || B2)
+       && B3
+       && !(B4
+            || B5)
+       && (B6
+           || (B7
+               && B8)))
+    R = True;
+  else
+    R = False;
+  return R;
+}
+
+/* { dg-final { scan-assembler "short-circuit.c:11" } } */
+/* { dg-final { scan-assembler "short-circuit.c:12" } } */
+/* { dg-final { scan-assembler "short-circuit.c:13" } } */
+/* { dg-final { scan-assembler "short-circuit.c:15" } } */
+
+/* { dg-final { scan-assembler "short-circuit.c:23" } } */
+/* { dg-final { scan-assembler "short-circuit.c:24" } } */
+
+/* { dg-final { scan-assembler "short-circuit.c:32" } } */
+/* { dg-final { scan-assembler "short-circuit.c:33" } } */
+/* { dg-final { scan-assembler "short-circuit.c:34" } } */
+
+/* { dg-final { scan-assembler "short-circuit.c:42" } } */
+/* { dg-final { scan-assembler "short-circuit.c:43" } } */
+/* { dg-final { scan-assembler "short-circuit.c:46" } } */
+
+/* { dg-final { scan-assembler "short-circuit.c:54" } } */
+/* { dg-final { scan-assembler "short-circuit.c:55" } } */
+/* { dg-final { scan-assembler "short-circuit.c:56" } } */
+
+/* { dg-final { scan-assembler "short-circuit.c:65" } } */
+/* { dg-final { scan-assembler "short-circuit.c:66" } } */
+/* { dg-final { scan-assembler "short-circuit.c:67" } } */
+/* { dg-final { scan-assembler "short-circuit.c:68" } } */
+/* { dg-final { scan-assembler "short-circuit.c:69" } } */
+/* { dg-final { scan-assembler "short-circuit.c:70" } } */
+/* { dg-final { scan-assembler "short-circuit.c:71" } } */
+/* { dg-final { scan-assembler "short-circuit.c:72" } } */
+/* { dg-final { scan-assembler "short-circuit.c:73" } } */
+/* { dg-final { scan-assembler "short-circuit.c:75" } } */