Index: common.opt
===================================================================
--- common.opt	(revision 190939)
+++ common.opt	(working copy)
@@ -1098,6 +1098,10 @@ fexcess-precision=
 Common Joined RejectNegative Enum(excess_precision) Var(flag_excess_precision_cmdline) Init(EXCESS_PRECISION_DEFAULT)
 -fexcess-precision=[fast|standard]	Specify handling of excess floating-point precision
 
+fextra-slocs
+Common Var(flag_extra_slocs) Init(0)
+Generate extra sloc information on expression trees
+
 Enum
 Name(excess_precision) Type(enum excess_precision) UnknownError(unknown excess precision style %qs)
 
Index: tree.c
===================================================================
--- tree.c	(revision 190939)
+++ tree.c	(working copy)
@@ -3561,6 +3561,8 @@ stabilize_reference (tree ref)
   TREE_READONLY (result) = TREE_READONLY (ref);
   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
+  protected_set_expr_location (result, EXPR_LOCATION (ref));
+  duplicate_expr_locations (result, ref);
 
   return result;
 }
@@ -4157,6 +4159,123 @@ build_block (tree vars, tree subblocks,
   return block;
 }
 
+/* extra location hash table */
+
+typedef struct {
+  const_tree node;
+  unsigned char len;
+  location_t locus[1];
+} sloc_struct;
+
+static htab_t extra_slocs = NULL;
+
+/* Hash function used by extra_slocs htable.  */
+static hashval_t
+node_hash (const void *p)
+{
+  const sloc_struct *m = (const sloc_struct *)p;
+  return htab_hash_pointer (m->node);
+}
+
+/* Comparison function used by extra_slocs htable.  */
+static int
+node_eq (const void *p, const void *q)
+{
+  const sloc_struct *a = (const sloc_struct *)p;
+  const sloc_struct *b = (const sloc_struct *)q;
+
+  return a->node == b->node;
+}
+
+/* Only relevant for EXPR_P nodes and when flag_extra_slocs is enabled.
+   Return secondary locations if any for a given expression. This is useful for
+   getting precise sloc information in particular correct column
+   numbers for each member of an expression. Unary expressions will return one
+   extra location, binary expressions will return two, COND_EXPR 3 extra,
+   etc... CALL_EXPR will return one extra loc for the precise location of the
+   function or method called, and one extra loc per argument.  */
+location_t *
+expr_locations (const_tree node)
+{
+  sloc_struct key;
+  sloc_struct *res;
+
+  if (!extra_slocs)
+    return NULL;
+
+  key.node = node;
+  res = (sloc_struct *) htab_find (extra_slocs, &key);
+  return res ? res->locus : NULL;
+}
+
+/* Return the nth location N associated with NODE, or UNKNOWN_LOCATION if
+   no extra location can be found (or -fextra-slocs is not set).  */
+location_t
+expr_location_n (const_tree node, int n)
+{
+  sloc_struct key;
+  sloc_struct *res;
+
+  if (!extra_slocs)
+    return UNKNOWN_LOCATION;
+
+  key.node = node;
+  res = (sloc_struct *) htab_find (extra_slocs, &key);
+
+  if (res && res->len > n)
+    return res->locus[n];
+  else
+    return UNKNOWN_LOCATION;
+}
+
+/* Set extra locations associated with NODE. LOCUS is an array of LEN
+   locations.  No-op unless -fextra-slocs is set.  */
+void
+set_expr_locations (tree node, location_t *locus, int len)
+{
+  sloc_struct *m;
+
+  if (!flag_extra_slocs)
+    return;
+
+  if (!extra_slocs)
+    extra_slocs = htab_create (8192, node_hash, node_eq, free);
+
+  m = (sloc_struct *)
+       xcalloc (1, sizeof (sloc_struct) + sizeof (location_t) * (len - 1));
+  m->node = node;
+  m->len = len;
+  memcpy (m->locus, locus, sizeof (location_t) * len);
+  *htab_find_slot (extra_slocs, m, INSERT) = m;
+}
+
+/* Set an extra location LOCUS for tree NODE.  No-op unless -fextra-slocs.  */
+void
+set_expr_location2 (tree node, location_t locus)
+{
+  if (!flag_extra_slocs)
+    return;
+
+  location_t l = locus;
+  set_expr_locations (node, &l, 1);
+}
+
+/* Copy extra locations associated with TARGET to SOURCE, if any.  */
+void
+duplicate_expr_locations (tree target, tree source)
+{
+  sloc_struct key;
+  sloc_struct *res;
+
+  if (!extra_slocs || !CAN_HAVE_LOCATION_P (target))
+    return;
+
+  key.node = source;
+  res = (sloc_struct *) htab_find (extra_slocs, &key);
+
+  if (res)
+    set_expr_locations (target, res->locus, res->len);
+}
 
 /* Like SET_EXPR_LOCATION, but make sure the tree can have a location.
 
Index: tree.h
===================================================================
--- tree.h	(revision 190939)
+++ tree.h	(working copy)
@@ -1618,7 +1618,10 @@ struct GTY(()) tree_constructor {
    return nothing.  */
 #define EXPR_LOCATION(NODE) \
   (CAN_HAVE_LOCATION_P ((NODE)) ? (NODE)->exp.locus : UNKNOWN_LOCATION)
+#define EXPR_LOCATIONS(NODE) expr_locations ((NODE))
 #define SET_EXPR_LOCATION(NODE, LOCUS) EXPR_CHECK ((NODE))->exp.locus = (LOCUS)
+#define SET_EXPR_LOCATION2(NODE, FROM) set_expr_location2 ((NODE), (FROM))
+#define SET_EXPR_LOCATIONS(NODE, FROM, LENGTH) set_expr_locations ((NODE), (FROM), (LENGTH))
 #define EXPR_HAS_LOCATION(NODE) (EXPR_LOCATION (NODE) != UNKNOWN_LOCATION)
 /* The location to be used in a diagnostic about this expression.  Do not
    use this macro if the location will be assigned to other expressions.  */
@@ -1631,6 +1634,11 @@ struct GTY(()) tree_constructor {
 #define CAN_HAVE_LOCATION_P(NODE) ((NODE) && EXPR_P (NODE))
 
 extern void protected_set_expr_location (tree, location_t);
+extern location_t *expr_locations (const_tree);
+extern location_t expr_location_n (const_tree, int);
+extern void set_expr_location2 (tree, location_t);
+extern void set_expr_locations (tree, location_t *, int);
+extern void duplicate_expr_locations (tree, tree);
 
 /* In a TARGET_EXPR node.  */
 #define TARGET_EXPR_SLOT(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 0)
