[PATCH] Add extra location information - PR43486
Arnaud Charlet
charlet@adacore.com
Tue Sep 18 10:59:00 GMT 2012
This is a relatively large patch which tackles the difficult issue of
generating more sloc information in front-ends (in particular C and C++
front-ends), so that "static analyzers" based on GCC can get more useful
and detailed information.
This happens to be related/similar to the need mentioned in PR43486, hence
the mention of this PR in the subject line.
In my work, as I mentioned a few times in the past, this patch is the
first foundation for another patch, which will provide source navigation
capabilities in IDEs/editors, by generating source cross reference information
based on the C and C++ front-ends (introducing a new switch -fdump-xref).
Ideally I'd like to submit both patches.
Since this issue is more general, I have split my changes and introduced a new
tentative switch called -fextra-slocs, which is the subject of this email.
In order to provide more sloc info attached to nodes (and in particular
VAR_DECLs), there are basically two possibilities:
- the one mentioned in comment 4 of PR43486:
<< Jason Merrill 2010-03-23 01:51:34 UTC
I suppose we could wrap rvalue uses in NOP_EXPR and lvalue uses in
VIEW_CONVERT_EXPR.
>>
I investigated this option, and unfortunately this does not work
because of folding occurring all over the place in the C and
C++ front-ends, removing these extra EXPRs very early.
So I opted for the second approach:
- Keep another data structure which will associate extra slocs with some
node expressions. The idea is that since you can't associate slocs with
VAR_DECLs in an expr, instead we store extra slocs in the containing
expression node. For instance, all binary expressions (add ADD, MINUS, ...)
will contain two extra slocs: one for the left hand side, and one for the
right hand side of the expression. One extra sloc for unary operators,
etc...
I've used a hash table which associates an array of location_t to some
expr nodes, which could then be used by static analysis passes (as done
by my patch to implement a -fdump-xref switch).
I have attached the various patches, split in directories:
- difs.common contains the common parts, introducing the -fextra-slocs
switch and the generic data structure/API to store/retrieve extra slocs
(in tree.[hc])
- difs.c contains the C front-end specific parts and add lots of source
location information, add some extra loc parameters to various parser
functions, and store these extra slocs when -fextra-slocs is enabled
- difs.cp does the same thing for the C++ front-end and includes testsuite
updates which are triggered by this patch, showing some of the immediate
benefits/side effects of generating more accurate "primary" slocs in
some cases (the case of Class::Method () references, where we now want to
reference the sloc pointing to Method rather than Class)
OK on principle? Or is the whole approach not suitable/doomed?
If OK on principle, I'd appreciate a C, C++ front-end maintainers, and
a general maintainer (for the common/general part) to review my patches in
more details, and hopefully give their review/OK.
Here is the ChangeLog (which will be split into the various directories of
course), patches are in attachment.
2012-09-18 Arnaud Charlet <charlet@adacore.com>
* tree.h, tree.c (stabilize_reference): Copy source locations.
(sloc_struct, extra_slocs): New.
(node_hash, node_eq): Implement extra_slocs hash table.
(expr_locations, set_expr_locations, set_expr_location2,
duplicate_expr_locations, expr_location_n): New functions.
(EXPR_LOCATIONS, SET_EXPR_LOCATION2, SET_EXPR_LOCATIONS): New macros.
* common.opt: New switch -fextra-slocs.
c/
* c-parser.c (c_parser_expr_list): New parameter locs, num_locs.
Set extra locations.
(c_parser_attributes): Adjust calls to c_parser_expr_list.
(c_parser_statement_after_labels): Adjust calls to c_finish_return with
extra expr location.
(c_parser_expr_no_commas, c_parser_conditional_expression,
c_parser_binary_expression, c_parser_cast_expression,
c_parser_unary_expression, c_parser_postfix_expression_after_primary,
c_parser_expr_list): Set extra locations.
(c_parser_postfix_expression): Remove extra semicolon.
(c_parser_objc_keywordexpr): Adjust call to c_parser_expr_list.
* c-typeck.c (c_finish_return): New parameter loc_expr.
* c-tree.h (c_finish_return): Add location_t parameter.
* c-decl.c (finish_function): Update call to c_finish_return.
(build_function_declarator): Set ret->id_loc.
c-family/
* c-common.c (c_fully_fold_internal): Copy extra locations on new node.
objc/
* objc-act.c (objc_synthesize_getter): Update call to c_finish_return.
cp/
* parser.c (cp_parser_unary_expression, cp_parser_binary_expression,
cp_parser_question_colon_clause, cp_parser_assignment_expression,
cp_parser_enumerator_definition): Set extra locations.
(cp_parser_parenthesized_expression_list): Ditto. New parameters
locs, num_locs.
(cp_parser_parse_and_diagnose_invalid_typ): Adjust call to
cp_parser_id_location.
(cp_parser_userdef_char_literal, cp_parser_userdef_numeric_literal,
cp_parser_userdef_string_literal, cp_parser_perform_range_for_lookup,
cp_parser_range_for_member_function): Adjust calls to finish_call_expr.
(cp_parser_primary_expression, cp_parser_postfix_dot_deref_expression,
cp_parser_decltype, cp_parser_type_parameter,
cp_parser_template_argument, cp_parser_omp_var_list_no_open): Adjust
calls to cp_parser_id_expression.
(cp_parser_id_expression, cp_parser_declarator_id): New parameter
location_t *. Set location to proper sloc for class::method
declarations.
(cp_parser_postfix_expression): Set extra locations.
Update calls to cp_parser_parenthesized_expression_list,
build_new_method_call and finish_call_expr.
(cp_parser_postfix_open_square_expression): Add extra locations for
array refs (e.g. a[i]).
(cp_parser_direct_declarator): Adjust call to cp_parser_declarator_id
and adjust sloc of declarator.
(cp_parser_new_placement, cp_parser_new_initializer,
cp_parser_mem_initializer, cp_parser_initializer,
cp_parser_attribute_list, cp_parser_functional_cast): Adjust call to
cp_parser_parenthesized_expression_list.
* typeck.c (build_c_cast): Ensure extra sloc information is preserved
over this function.
* call.c (build_over_call): New parameter loc.
(build_new_function_call, build_operator_new_call, build_op_call_1,
build_new_op_1, convert_like_real): Update call to build_over_call.
(build_new_method_call, build_new_method_call_1, finish_call_expr):
New parameter loc.
(build_special_member_call): Update call to build_new_method_call.
(perform_implicit_conversion_flags): Ensure line number
information is preserved over this function.
* method.c (locate_fn_flags): Update call to build_new_method_call.
* class.c (build_self_reference): Update decl location of internal type.
* cp-tree.h (build_new_method_call, finish_call_expr): New parameter
loc.
* pt.c (tsubst_copy_and_build): Update call to build_new_method_call
and finish_call_expr.
* init.c (build_new_1, build_dtor_call): Ditto.
* semantics.c (finish_omp_barrier, finish_omp_flush,
finish_omp_taskyield, finish_omp_taskwait): Ditto.
(finish_call_expr): Ditto. New parameter loc.
(finish_id_expression): Add sloc on decl.
testsuite/
* g++.dg/warn/pr26785.C, g++.old-deja/g++.brendan/crash16.C: Update
column numbers.
* g++.dg/tc1/dr52.C: Update baseline.
-------------- next part --------------
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)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: difs.c
Type: text/x-csrc
Size: 21698 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20120918/cd505173/attachment.bin>
-------------- next part --------------
Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 190939)
+++ cp/typeck.c (working copy)
@@ -6645,9 +6645,14 @@ build_const_cast (tree type, tree expr,
/* Like cp_build_c_cast, but for the c-common bits. */
tree
-build_c_cast (location_t loc ATTRIBUTE_UNUSED, tree type, tree expr)
+build_c_cast (location_t loc, tree type, tree expr)
{
- return cp_build_c_cast (type, expr, tf_warning_or_error);
+ tree result = cp_build_c_cast (type, expr, tf_warning_or_error);
+
+ if (EXPR_P (result))
+ SET_EXPR_LOCATION2 (result, loc);
+
+ return result;
}
/* Build an expression representing an explicit C-style cast to type
Index: cp/call.c
===================================================================
--- cp/call.c (revision 190939)
+++ cp/call.c (working copy)
@@ -146,7 +146,8 @@ static int equal_functions (tree, tree);
static int joust (struct z_candidate *, struct z_candidate *, bool,
tsubst_flags_t);
static int compare_ics (conversion *, conversion *);
-static tree build_over_call (struct z_candidate *, int, tsubst_flags_t);
+static tree build_over_call (struct z_candidate *, int, tsubst_flags_t,
+ location_t);
static tree build_java_interface_fn_ref (tree, tree);
#define convert_like(CONV, EXPR, COMPLAIN) \
convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
@@ -3905,7 +3906,7 @@ build_new_function_call (tree fn, VEC(tr
about peculiar null pointer conversion. */
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
flags |= LOOKUP_EXPLICIT_TMPL_ARGS;
- result = build_over_call (cand, flags, complain);
+ result = build_over_call (cand, flags, complain, input_location);
}
/* Free all the conversions we allocated. */
@@ -4024,7 +4025,7 @@ build_operator_new_call (tree fnname, VE
*fn = cand->fn;
/* Build the CALL_EXPR. */
- return build_over_call (cand, LOOKUP_NORMAL, complain);
+ return build_over_call (cand, LOOKUP_NORMAL, complain, input_location);
}
/* Build a new call to operator(). This may change ARGS. */
@@ -4145,7 +4146,8 @@ build_op_call_1 (tree obj, VEC(tree,gc)
DECL_NAME here. */
else if (TREE_CODE (cand->fn) == FUNCTION_DECL
&& DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
- result = build_over_call (cand, LOOKUP_NORMAL, complain);
+ result = build_over_call (cand, LOOKUP_NORMAL, complain,
+ input_location);
else
{
obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1,
@@ -5171,7 +5173,8 @@ build_new_op_1 (location_t loc, enum tre
if (resolve_args (arglist, complain) == NULL)
result = error_mark_node;
else
- result = build_over_call (cand, LOOKUP_NORMAL, complain);
+ result = build_over_call (cand, LOOKUP_NORMAL, complain,
+ input_location);
}
else
{
@@ -5783,7 +5786,7 @@ convert_like_real (conversion *convs, tr
for (i = 0; i < cand->num_convs; ++i)
cand->convs[i]->user_conv_p = true;
- expr = build_over_call (cand, LOOKUP_NORMAL, complain);
+ expr = build_over_call (cand, LOOKUP_NORMAL, complain, input_location);
/* If this is a constructor or a function returning an aggr type,
we need to build up a TARGET_EXPR. */
@@ -6402,7 +6405,8 @@ magic_varargs_p (tree fn)
bitmask of various LOOKUP_* flags which apply to the call itself. */
static tree
-build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
+build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain,
+ location_t loc ATTRIBUTE_UNUSED)
{
tree fn = cand->fn;
const VEC(tree,gc) *args = cand->args;
@@ -7130,7 +7134,7 @@ build_special_member_call (tree instance
ret = build_new_method_call (instance, fns, args,
TYPE_BINFO (BINFO_TYPE (binfo)),
flags, /*fn=*/NULL,
- complain);
+ complain, input_location);
if (allocated != NULL)
release_tree_vector (allocated);
@@ -7185,12 +7189,12 @@ name_as_c_string (tree name, tree type,
/* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will
be set, upon return, to the function called. ARGS may be NULL.
- This may change ARGS. */
+ This may change ARGS. LOC is the source location of the call. */
static tree
build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args,
tree conversion_path, int flags,
- tree *fn_p, tsubst_flags_t complain)
+ tree *fn_p, tsubst_flags_t complain, location_t loc)
{
struct z_candidate *candidates = 0, *cand;
tree explicit_targs = NULL_TREE;
@@ -7469,7 +7473,7 @@ build_new_method_call_1 (tree instance,
if (fn_p)
*fn_p = fn;
/* Build the actual CALL_EXPR. */
- call = build_over_call (cand, flags, complain);
+ call = build_over_call (cand, flags, complain, loc);
/* In an expression of the form `a->f()' where `f' turns
out to be a static member function, `a' is
none-the-less evaluated. */
@@ -7534,12 +7538,12 @@ build_new_method_call_1 (tree instance,
tree
build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
tree conversion_path, int flags,
- tree *fn_p, tsubst_flags_t complain)
+ tree *fn_p, tsubst_flags_t complain, location_t loc)
{
tree ret;
bool subtime = timevar_cond_start (TV_OVERLOAD);
ret = build_new_method_call_1 (instance, fns, args, conversion_path, flags,
- fn_p, complain);
+ fn_p, complain, loc);
timevar_cond_stop (TV_OVERLOAD, subtime);
return ret;
}
@@ -8562,6 +8566,7 @@ tree
perform_implicit_conversion_flags (tree type, tree expr,
tsubst_flags_t complain, int flags)
{
+ tree result = expr;
conversion *conv;
void *p;
location_t loc = EXPR_LOC_OR_HERE (expr);
@@ -8605,6 +8610,9 @@ perform_implicit_conversion_flags (tree
}
else
expr = convert_like (conv, expr, complain);
+
+ if (expr != error_mark_node)
+ duplicate_expr_locations (expr, result);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
Index: cp/method.c
===================================================================
--- cp/method.c (revision 190939)
+++ cp/method.c (working copy)
@@ -837,7 +837,8 @@ locate_fn_flags (tree type, tree name, t
}
fns = lookup_fnfields (binfo, name, 0);
- rval = build_new_method_call (ob, fns, &args, binfo, flags, &fn, complain);
+ rval = build_new_method_call (ob, fns, &args, binfo, flags, &fn, complain,
+ input_location);
release_tree_vector (args);
if (fn && rval == error_mark_node)
Index: cp/class.c
===================================================================
--- cp/class.c (revision 190939)
+++ cp/class.c (working copy)
@@ -7355,6 +7355,9 @@ build_self_reference (void)
DECL_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
SET_DECL_SELF_REFERENCE_P (value);
+ DECL_SOURCE_LOCATION (value) =
+ DECL_SOURCE_LOCATION (TYPE_NAME (current_class_type));
+
set_underlying_type (value);
if (processing_template_decl)
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 190939)
+++ cp/pt.c (working copy)
@@ -13788,20 +13788,20 @@ tsubst_copy_and_build (tree t,
ret = finish_call_expr (function, &call_args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
- complain);
+ complain, input_location);
else
ret = (build_new_method_call
(instance, fn,
&call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
/*fn_p=*/NULL,
- complain));
+ complain, input_location));
}
else
ret = finish_call_expr (function, &call_args,
/*disallow_virtual=*/qualified_p,
koenig_p,
- complain);
+ complain, input_location);
release_tree_vector (call_args);
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 190939)
+++ cp/parser.c (working copy)
@@ -1787,7 +1787,7 @@ static bool cp_parser_translation_unit
static tree cp_parser_primary_expression
(cp_parser *, bool, bool, bool, cp_id_kind *);
static tree cp_parser_id_expression
- (cp_parser *, bool, bool, bool *, bool, bool);
+ (cp_parser *, bool, bool, bool *, bool, bool, location_t *);
static tree cp_parser_unqualified_id
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier_opt
@@ -1803,7 +1803,7 @@ static tree cp_parser_postfix_open_squar
static tree cp_parser_postfix_dot_deref_expression
(cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
static VEC(tree,gc) *cp_parser_parenthesized_expression_list
- (cp_parser *, int, bool, bool, bool *);
+ (cp_parser *, int, bool, bool, bool *, location_t *, int *);
/* Values for the second parameter of cp_parser_parenthesized_expression_list. */
enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
static void cp_parser_pseudo_destructor_name
@@ -1831,7 +1831,7 @@ static tree cp_parser_cast_expression
static tree cp_parser_binary_expression
(cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *);
static tree cp_parser_question_colon_clause
- (cp_parser *, tree);
+ (cp_parser *, tree, location_t);
static tree cp_parser_assignment_expression
(cp_parser *, bool, cp_id_kind *);
static enum tree_code cp_parser_assignment_operator_opt
@@ -1968,7 +1968,7 @@ static cp_virt_specifiers cp_parser_virt
static tree cp_parser_late_return_type_opt
(cp_parser *, cp_cv_quals);
static tree cp_parser_declarator_id
- (cp_parser *, bool);
+ (cp_parser *, bool, location_t *);
static tree cp_parser_type_id
(cp_parser *);
static tree cp_parser_template_type_arg
@@ -2844,7 +2844,8 @@ cp_parser_parse_and_diagnose_invalid_typ
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/true,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*loc=*/NULL);
/* If the next token is a (, this is a function with no explicit return
type, i.e. constructor, destructor or conversion op. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
@@ -3583,7 +3584,8 @@ cp_parser_userdef_char_literal (cp_parse
release_tree_vector (args);
return error_mark_node;
}
- result = finish_call_expr (decl, &args, false, true, tf_warning_or_error);
+ result = finish_call_expr
+ (decl, &args, false, true, tf_warning_or_error, token->location);
release_tree_vector (args);
if (result != error_mark_node)
return result;
@@ -3641,7 +3643,8 @@ cp_parser_userdef_numeric_literal (cp_pa
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
- result = finish_call_expr (decl, &args, false, true, tf_none);
+ result = finish_call_expr
+ (decl, &args, false, true, tf_none, token->location);
if (result != error_mark_node)
{
release_tree_vector (args);
@@ -3658,7 +3661,8 @@ cp_parser_userdef_numeric_literal (cp_pa
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
- result = finish_call_expr (decl, &args, false, true, tf_none);
+ result = finish_call_expr
+ (decl, &args, false, true, tf_none, token->location);
if (result != error_mark_node)
{
release_tree_vector (args);
@@ -3676,7 +3680,8 @@ cp_parser_userdef_numeric_literal (cp_pa
{
tree tmpl_args = make_char_string_pack (num_string);
decl = lookup_template_function (decl, tmpl_args);
- result = finish_call_expr (decl, &args, false, true, tf_none);
+ result = finish_call_expr
+ (decl, &args, false, true, tf_none, token->location);
if (result != error_mark_node)
{
release_tree_vector (args);
@@ -3716,7 +3721,7 @@ cp_parser_userdef_string_literal (cp_tok
release_tree_vector (args);
return error_mark_node;
}
- result = finish_call_expr (decl, &args, false, true, tf_none);
+ result = finish_call_expr (decl, &args, false, true, tf_none, token->location);
release_tree_vector (args);
if (result != error_mark_node)
return result;
@@ -4226,7 +4231,8 @@ cp_parser_primary_expression (cp_parser
/*check_dependency_p=*/true,
&template_p,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*loc=*/NULL);
if (id_expression == error_mark_node)
return error_mark_node;
id_expr_token = token;
@@ -4389,7 +4395,10 @@ cp_parser_primary_expression (cp_parser
named is a template.
If DECLARATOR_P is true, the id-expression is appearing as part of
- a declarator, rather than as part of an expression. */
+ a declarator, rather than as part of an expression.
+
+ If LOC is non-NULL and a qualified-id is found, LOC is set to the location
+ of the unqualified-id. */
static tree
cp_parser_id_expression (cp_parser *parser,
@@ -4397,7 +4406,8 @@ cp_parser_id_expression (cp_parser *pars
bool check_dependency_p,
bool *template_p,
bool declarator_p,
- bool optional_p)
+ bool optional_p,
+ location_t *loc)
{
bool global_scope_p;
bool nested_name_specifier_p;
@@ -4437,6 +4447,10 @@ cp_parser_id_expression (cp_parser *pars
saved_scope = parser->scope;
saved_object_scope = parser->object_scope;
saved_qualifying_scope = parser->qualifying_scope;
+
+ if (loc)
+ *loc = cp_lexer_peek_token (parser->lexer)->location;
+
/* Process the final unqualified-id. */
unqualified_id = cp_parser_unqualified_id (parser, *template_p,
check_dependency_p,
@@ -4459,6 +4473,9 @@ cp_parser_id_expression (cp_parser *pars
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
+ if (loc)
+ *loc = token->location;
+
/* If it's an identifier, and the next token is not a "<", then
we can avoid the template-id case. This is an optimization
for this common case. */
@@ -4498,10 +4515,15 @@ cp_parser_id_expression (cp_parser *pars
}
}
else
- return cp_parser_unqualified_id (parser, template_keyword_p,
- /*check_dependency_p=*/true,
- declarator_p,
- optional_p);
+ {
+ if (loc)
+ *loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ return cp_parser_unqualified_id (parser, template_keyword_p,
+ /*check_dependency_p=*/true,
+ declarator_p,
+ optional_p);
+ }
}
/* Parse an unqualified-id.
@@ -5326,6 +5348,7 @@ cp_parser_postfix_expression (cp_parser
cp_id_kind idk = CP_ID_KIND_NONE;
tree postfix_expression = NULL_TREE;
bool is_member_access = false;
+ location_t locs[64], member_loc = UNKNOWN_LOCATION;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
@@ -5468,7 +5491,8 @@ cp_parser_postfix_expression (cp_parser
cp_lexer_consume_token (parser->lexer);
vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/false, /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ /*non_constant_p=*/NULL,
+ /*locs=*/NULL, /*num_locs=*/NULL);
if (vec == NULL)
return error_mark_node;
@@ -5603,6 +5627,7 @@ cp_parser_postfix_expression (cp_parser
= unqualified_name_lookup_error (postfix_expression);
/* Peek at the next token. */
+ locs[0] = token->location;
token = cp_lexer_peek_token (parser->lexer);
switch (token->type)
@@ -5624,6 +5649,7 @@ cp_parser_postfix_expression (cp_parser
bool saved_integral_constant_expression_p = false;
bool saved_non_integral_constant_expression_p = false;
VEC(tree,gc) *args;
+ int num_locs = 63;
is_member_access = false;
@@ -5642,7 +5668,7 @@ cp_parser_postfix_expression (cp_parser
args = (cp_parser_parenthesized_expression_list
(parser, non_attr,
/*cast_p=*/false, /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL));
+ /*non_constant_p=*/NULL, &locs[1], &num_locs));
if (is_builtin_constant_p)
{
parser->integral_constant_expression_p
@@ -5717,6 +5743,11 @@ cp_parser_postfix_expression (cp_parser
tree instance = TREE_OPERAND (postfix_expression, 0);
tree fn = TREE_OPERAND (postfix_expression, 1);
+ if (member_loc == UNKNOWN_LOCATION)
+ member_loc = locs[0];
+ else
+ locs[0] = member_loc;
+
if (processing_template_decl
&& (type_dependent_expression_p (instance)
|| (!BASELINK_P (fn)
@@ -5739,14 +5770,14 @@ cp_parser_postfix_expression (cp_parser
? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
: LOOKUP_NORMAL),
/*fn_p=*/NULL,
- tf_warning_or_error));
+ tf_warning_or_error, member_loc));
}
else
postfix_expression
= finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
- tf_warning_or_error);
+ tf_warning_or_error, member_loc);
}
else if (TREE_CODE (postfix_expression) == OFFSET_REF
|| TREE_CODE (postfix_expression) == MEMBER_REF
@@ -5760,14 +5791,15 @@ cp_parser_postfix_expression (cp_parser
= finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/true,
koenig_p,
- tf_warning_or_error);
+ tf_warning_or_error, locs[0]);
else
/* All other function calls. */
postfix_expression
= finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
koenig_p,
- tf_warning_or_error);
+ tf_warning_or_error, locs[0]);
+ SET_EXPR_LOCATIONS (postfix_expression, locs, num_locs+1);
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
idk = CP_ID_KIND_NONE;
@@ -5785,6 +5817,7 @@ cp_parser_postfix_expression (cp_parser
/* Consume the `.' or `->' operator. */
cp_lexer_consume_token (parser->lexer);
+ member_loc = locs[1] = cp_lexer_peek_token (parser->lexer)->location;
postfix_expression
= cp_parser_postfix_dot_deref_expression (parser, token->type,
@@ -5792,6 +5825,8 @@ cp_parser_postfix_expression (cp_parser
false, &idk,
token->location);
+ protected_set_expr_location (postfix_expression, token->location);
+ SET_EXPR_LOCATIONS (postfix_expression, locs, 2);
is_member_access = true;
break;
@@ -5799,6 +5834,7 @@ cp_parser_postfix_expression (cp_parser
/* postfix-expression ++ */
/* Consume the `++' token. */
cp_lexer_consume_token (parser->lexer);
+ locs[1] = locs [0];
/* Generate a representation for the complete expression. */
postfix_expression
= finish_increment_expr (postfix_expression,
@@ -5806,6 +5842,11 @@ cp_parser_postfix_expression (cp_parser
/* Increments may not appear in constant-expressions. */
if (cp_parser_non_integral_constant_expression (parser, NIC_INC))
postfix_expression = error_mark_node;
+ else
+ {
+ protected_set_expr_location (postfix_expression, token->location);
+ SET_EXPR_LOCATIONS (postfix_expression, locs, 2);
+ }
idk = CP_ID_KIND_NONE;
is_member_access = false;
break;
@@ -5814,6 +5855,7 @@ cp_parser_postfix_expression (cp_parser
/* postfix-expression -- */
/* Consume the `--' token. */
cp_lexer_consume_token (parser->lexer);
+ locs[1] = locs [0];
/* Generate a representation for the complete expression. */
postfix_expression
= finish_increment_expr (postfix_expression,
@@ -5821,6 +5863,11 @@ cp_parser_postfix_expression (cp_parser
/* Decrements may not appear in constant-expressions. */
if (cp_parser_non_integral_constant_expression (parser, NIC_DEC))
postfix_expression = error_mark_node;
+ else
+ {
+ protected_set_expr_location (postfix_expression, token->location);
+ SET_EXPR_LOCATIONS (postfix_expression, locs, 2);
+ }
idk = CP_ID_KIND_NONE;
is_member_access = false;
break;
@@ -5855,10 +5902,13 @@ cp_parser_postfix_open_square_expression
bool for_offsetof)
{
tree index;
+ location_t locs[2];
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ locs[0] = input_location;
/* Consume the `[' token. */
cp_lexer_consume_token (parser->lexer);
+ locs[1] = cp_lexer_peek_token (parser->lexer)->location;
/* Parse the index expression. */
/* ??? For offsetof, there is a question of what to allow here. If
@@ -5893,6 +5943,10 @@ cp_parser_postfix_open_square_expression
if (!for_offsetof
&& (cp_parser_non_integral_constant_expression (parser, NIC_ARRAY_REF)))
postfix_expression = error_mark_node;
+ else if (TREE_CODE (postfix_expression) == INDIRECT_REF)
+ SET_EXPR_LOCATIONS (TREE_OPERAND (postfix_expression, 0), locs, 2);
+ else
+ SET_EXPR_LOCATIONS (postfix_expression, locs, 2);
return postfix_expression;
}
@@ -6018,7 +6072,8 @@ cp_parser_postfix_dot_deref_expression (
/*check_dependency_p=*/true,
&template_p,
/*declarator_p=*/false,
- /*optional_p=*/false));
+ /*optional_p=*/false,
+ /*loc=*/NULL));
/* In general, build a SCOPE_REF if the member name is qualified.
However, if the name was not dependent and has already been
resolved; there is no need to build the SCOPE_REF. For example;
@@ -6115,12 +6170,14 @@ cp_parser_parenthesized_expression_list
int is_attribute_list,
bool cast_p,
bool allow_expansion_p,
- bool *non_constant_p)
+ bool *non_constant_p,
+ location_t *locs, int *num_locs)
{
VEC(tree,gc) *expression_list;
bool fold_expr_p = is_attribute_list != non_attr;
tree identifier = NULL_TREE;
bool saved_greater_than_is_operator_p;
+ int i = 0;
/* Assume all the expressions will be constant. */
if (non_constant_p)
@@ -6143,6 +6200,9 @@ cp_parser_parenthesized_expression_list
{
tree expr;
+ if (locs && i < *num_locs)
+ locs[i++] = cp_lexer_peek_token (parser->lexer)->location;
+
/* At the beginning of attribute lists, check to see if the
next token is an identifier. */
if (is_attribute_list == id_attr
@@ -6238,6 +6298,9 @@ cp_parser_parenthesized_expression_list
}
}
+ if (locs)
+ *num_locs = i;
+
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
@@ -6540,9 +6603,11 @@ cp_parser_unary_expression (cp_parser *p
tree identifier;
tree expression;
location_t loc = token->location;
+ location_t loc2;
/* Consume the '&&' token. */
cp_lexer_consume_token (parser->lexer);
+ loc2 = cp_lexer_peek_token (parser->lexer)->location;
/* Look for the identifier. */
identifier = cp_parser_identifier (parser);
/* Create an expression representing the address. */
@@ -6550,6 +6615,8 @@ cp_parser_unary_expression (cp_parser *p
if (cp_parser_non_integral_constant_expression (parser,
NIC_ADDR_LABEL))
expression = error_mark_node;
+ else
+ SET_EXPR_LOCATION2 (expression, loc2);
return expression;
}
}
@@ -6559,9 +6626,11 @@ cp_parser_unary_expression (cp_parser *p
tree expression = error_mark_node;
non_integral_constant non_constant_p = NIC_NONE;
location_t loc = token->location;
+ location_t loc2;
/* Consume the operator token. */
token = cp_lexer_consume_token (parser->lexer);
+ loc2 = cp_lexer_peek_token (parser->lexer)->location;
/* Parse the cast-expression. */
cast_expression
= cp_parser_cast_expression (parser,
@@ -6606,6 +6675,8 @@ cp_parser_unary_expression (cp_parser *p
&& cp_parser_non_integral_constant_expression (parser,
non_constant_p))
expression = error_mark_node;
+ else
+ SET_EXPR_LOCATION2 (expression, loc2);
return expression;
}
@@ -6761,7 +6832,7 @@ cp_parser_new_placement (cp_parser* pars
expression_list = (cp_parser_parenthesized_expression_list
(parser, non_attr, /*cast_p=*/false,
/*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL));
+ /*non_constant_p=*/NULL, /*locs=*/NULL, /*num_locs=*/NULL));
return expression_list;
}
@@ -6963,7 +7034,7 @@ cp_parser_new_initializer (cp_parser* pa
expression_list = (cp_parser_parenthesized_expression_list
(parser, non_attr, /*cast_p=*/false,
/*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL));
+ /*non_constant_p=*/NULL, /*locs=*/NULL, /*num_locs=*/NULL));
return expression_list;
}
@@ -7281,10 +7352,14 @@ cp_parser_binary_expression (cp_parser*
enum tree_code rhs_type;
enum cp_parser_prec new_prec, lookahead_prec;
tree overload;
+ location_t locs[2];
/* Parse the first expression. */
+ locs[0] = cp_lexer_peek_token (parser->lexer)->location;
current.lhs = cp_parser_cast_expression (parser, /*address_p=*/false,
cast_p, pidk);
+ if (EXPR_P (current.lhs))
+ locs[0] = EXPR_LOCATION (current.lhs);
current.lhs_type = ERROR_MARK;
current.prec = prec;
@@ -7340,6 +7415,7 @@ cp_parser_binary_expression (cp_parser*
/* Extract another operand. It may be the RHS of this expression
or the LHS of a new, higher priority expression. */
+ locs[1] = cp_lexer_peek_token (parser->lexer)->location;
rhs = cp_parser_simple_cast_expression (parser);
rhs_type = ERROR_MARK;
@@ -7359,6 +7435,8 @@ cp_parser_binary_expression (cp_parser*
current.lhs = rhs;
current.lhs_type = rhs_type;
current.prec = new_prec;
+ current.loc = locs[0];
+ locs[0] = locs[1];
new_prec = lookahead_prec;
goto get_rhs;
@@ -7375,6 +7453,8 @@ cp_parser_binary_expression (cp_parser*
rhs_type = current.lhs_type;
--sp;
current = *sp;
+ locs[1] = locs[0];
+ locs[0] = sp->loc;
}
/* Undo the disabling of warnings done above. */
@@ -7402,6 +7482,7 @@ cp_parser_binary_expression (cp_parser*
current.lhs, current.lhs_type,
rhs, rhs_type, &overload,
tf_warning_or_error);
+ SET_EXPR_LOCATIONS (current.lhs, locs, 2);
current.lhs_type = current.tree_type;
/* If the binary operator required the use of an overloaded operator,
@@ -7423,6 +7504,7 @@ cp_parser_binary_expression (cp_parser*
/* Parse the `? expression : assignment-expression' part of a
conditional-expression. The LOGICAL_OR_EXPR is the
logical-or-expression that started the conditional-expression.
+ LHS_LOC is the location of the lhs.
Returns a representation of the entire conditional-expression.
This routine is used by cp_parser_assignment_expression.
@@ -7434,13 +7516,24 @@ cp_parser_binary_expression (cp_parser*
? : assignment-expression */
static tree
-cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
+cp_parser_question_colon_clause (cp_parser* parser,
+ tree logical_or_expr,
+ location_t lhs_loc)
{
tree expr;
tree assignment_expr;
+ tree result;
+ /* locations of the conditional expression:
+ locs[0] == location of ?
+ locs[1] == location of lhs
+ locs[2] == location of expression
+ locs[3] == location of assignment-expression. */
+ location_t locs[4];
struct cp_token *token;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ locs[0] = cp_lexer_peek_token (parser->lexer)->location;
+ locs[1] = lhs_loc;
/* Consume the `?' token. */
cp_lexer_consume_token (parser->lexer);
token = cp_lexer_peek_token (parser->lexer);
@@ -7451,6 +7544,7 @@ cp_parser_question_colon_clause (cp_pars
"ISO C++ does not allow ?: with omitted middle operand");
/* Implicit true clause. */
expr = NULL_TREE;
+ locs[2] = UNKNOWN_LOCATION;
c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
warn_for_omitted_condop (token->location, logical_or_expr);
}
@@ -7458,6 +7552,7 @@ cp_parser_question_colon_clause (cp_pars
{
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
parser->colon_corrects_to_scope_p = false;
+ locs[2] = cp_lexer_peek_token (parser->lexer)->location;
/* Parse the expression. */
c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node;
expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
@@ -7469,15 +7564,19 @@ cp_parser_question_colon_clause (cp_pars
/* The next token should be a `:'. */
cp_parser_require (parser, CPP_COLON, RT_COLON);
+ locs[3] = cp_lexer_peek_token (parser->lexer)->location;
/* Parse the assignment-expression. */
assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
/* Build the conditional-expression. */
- return build_x_conditional_expr (loc, logical_or_expr,
- expr,
- assignment_expr,
- tf_warning_or_error);
+ result = build_x_conditional_expr (loc, logical_or_expr,
+ expr,
+ assignment_expr,
+ tf_warning_or_error);
+ protected_set_expr_location (result, locs[0]);
+ SET_EXPR_LOCATIONS (result, &locs[1], 3);
+ return result;
}
/* Parse an assignment-expression.
@@ -7496,6 +7595,12 @@ cp_parser_assignment_expression (cp_pars
cp_id_kind * pidk)
{
tree expr;
+ /* extra locations of the assignment expression:
+ locs[0] == location of lhs
+ locs[1] == location of rhs. */
+ location_t locs[2];
+
+ locs[0] = cp_lexer_peek_token (parser->lexer)->location;
/* If the next token is the `throw' keyword, then we're looking at
a throw-expression. */
@@ -7511,7 +7616,7 @@ cp_parser_assignment_expression (cp_pars
/* If the next token is a `?' then we're actually looking at a
conditional-expression. */
if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
- return cp_parser_question_colon_clause (parser, expr);
+ return cp_parser_question_colon_clause (parser, expr, locs[0]);
else
{
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -7524,9 +7629,11 @@ cp_parser_assignment_expression (cp_pars
{
bool non_constant_p;
location_t saved_input_location;
+ tree rhs;
/* Parse the right-hand side of the assignment. */
- tree rhs = cp_parser_initializer_clause (parser, &non_constant_p);
+ locs[1] = cp_lexer_peek_token (parser->lexer)->location;
+ rhs = cp_parser_initializer_clause (parser, &non_constant_p);
if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
@@ -7545,6 +7652,7 @@ cp_parser_assignment_expression (cp_pars
rhs,
tf_warning_or_error);
input_location = saved_input_location;
+ SET_EXPR_LOCATIONS (expr, locs, 2);
}
}
}
@@ -9609,12 +9717,12 @@ cp_parser_perform_range_for_lookup (tree
/*include_std=*/true,
tf_warning_or_error);
*begin = finish_call_expr (member_begin, &vec, false, true,
- tf_warning_or_error);
+ tf_warning_or_error, input_location);
member_end = perform_koenig_lookup (id_end, vec,
/*include_std=*/true,
tf_warning_or_error);
*end = finish_call_expr (member_end, &vec, false, true,
- tf_warning_or_error);
+ tf_warning_or_error, input_location);
release_tree_vector (vec);
}
@@ -9658,7 +9766,7 @@ cp_parser_range_for_member_function (tre
res = finish_call_expr (member, &vec,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
- tf_warning_or_error);
+ tf_warning_or_error, input_location);
release_tree_vector (vec);
return res;
}
@@ -11067,7 +11175,8 @@ cp_parser_decltype (cp_parser *parser)
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*loc=*/NULL);
if (!cp_parser_error_occurred (parser) && expr != error_mark_node)
{
@@ -11513,7 +11622,9 @@ cp_parser_mem_initializer (cp_parser* pa
vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/false,
/*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ /*non_constant_p=*/NULL,
+ /*locs=*/NULL,
+ /*num_locs=*/NULL);
if (vec == NULL)
return error_mark_node;
expression_list = build_tree_list_vec (vec);
@@ -12315,7 +12426,8 @@ cp_parser_type_parameter (cp_parser* par
/*check_dependency_p=*/true,
/*template_p=*/&is_template,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*loc=*/NULL);
if (TREE_CODE (default_argument) == TYPE_DECL)
/* If the id-expression was a template-id that refers to
a template-class, we already have the declaration here,
@@ -12943,7 +13055,8 @@ cp_parser_template_argument (cp_parser*
/*check_dependency_p=*/true,
&template_p,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*loc=*/NULL);
/* If the next token isn't a `,' or a `>', then this argument wasn't
really finished. */
if (!cp_parser_next_token_ends_template_argument_p (parser))
@@ -16245,6 +16358,7 @@ cp_parser_direct_declarator (cp_parser*
bool abstract_ok;
bool pack_expansion_p = false;
cp_token *declarator_id_start_token;
+ location_t loc;
/* Parse a declarator-id */
abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
@@ -16265,7 +16379,8 @@ cp_parser_direct_declarator (cp_parser*
declarator_id_start_token = cp_lexer_peek_token (parser->lexer);
unqualified_name
- = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
+ = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok,
+ &loc);
qualifying_scope = parser->scope;
if (abstract_ok)
{
@@ -16421,7 +16536,7 @@ cp_parser_direct_declarator (cp_parser*
declarator = make_id_declarator (qualifying_scope,
unqualified_name,
sfk);
- declarator->id_loc = token->location;
+ declarator->id_loc = loc;
declarator->parameter_pack_p = pack_expansion_p;
if (pack_expansion_p)
@@ -16772,10 +16887,12 @@ cp_parser_late_return_type_opt (cp_parse
If the id-expression was a qualified-id, then a SCOPE_REF is
returned. The first operand is the scope (either a NAMESPACE_DECL
or TREE_TYPE), but the second is still just a representation of an
- unqualified-id. */
+ unqualified-id.
+
+ if LOC is not-NULL, it is set to the location of the unqualified-id. */
static tree
-cp_parser_declarator_id (cp_parser* parser, bool optional_p)
+cp_parser_declarator_id (cp_parser* parser, bool optional_p, location_t *loc)
{
tree id;
/* The expression must be an id-expression. Assume that qualified
@@ -16797,7 +16914,8 @@ cp_parser_declarator_id (cp_parser* pars
/*check_dependency_p=*/false,
/*template_p=*/NULL,
/*declarator_p=*/true,
- optional_p);
+ optional_p,
+ loc);
if (id && BASELINK_P (id))
id = BASELINK_FUNCTIONS (id);
return id;
@@ -17548,7 +17666,9 @@ cp_parser_initializer (cp_parser* parser
vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/false,
/*allow_expansion_p=*/true,
- non_constant_p);
+ non_constant_p,
+ /*locs=*/NULL,
+ /*num_locs=*/NULL);
if (vec == NULL)
return error_mark_node;
init = build_tree_list_vec (vec);
@@ -20223,7 +20343,7 @@ cp_parser_attribute_list (cp_parser* par
vec = cp_parser_parenthesized_expression_list
(parser, attr_flag, /*cast_p=*/false,
/*allow_expansion_p=*/false,
- /*non_constant_p=*/NULL);
+ /*non_constant_p=*/NULL, /*locs=*/NULL, /*num_locs=*/NULL);
if (vec == NULL)
arguments = error_mark_node;
else
@@ -21489,7 +21609,9 @@ cp_parser_functional_cast (cp_parser* pa
vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/true,
/*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ /*non_constant_p=*/NULL,
+ /*locs=*/NULL,
+ /*num_locs=*/NULL);
if (vec == NULL)
expression_list = error_mark_node;
else
@@ -25145,7 +25267,8 @@ cp_parser_omp_var_list_no_open (cp_parse
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*loc=*/NULL);
if (name == error_mark_node)
goto skip_comma;
Index: cp/init.c
===================================================================
--- cp/init.c (revision 190939)
+++ cp/init.c (working copy)
@@ -2482,7 +2482,7 @@ build_new_1 (VEC(tree,gc) **placement, t
/*conversion_path=*/NULL_TREE,
LOOKUP_NORMAL,
&alloc_fn,
- complain);
+ complain, input_location);
}
else
{
@@ -3693,7 +3693,7 @@ build_dtor_call (tree exp, special_funct
/*conversion_path=*/NULL_TREE,
flags,
/*fn_p=*/NULL,
- complain);
+ complain, input_location);
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h (revision 190939)
+++ cp/cp-tree.h (working copy)
@@ -4890,7 +4890,7 @@ extern tree build_operator_new_call (tr
tsubst_flags_t);
extern tree build_new_method_call (tree, tree, VEC(tree,gc) **,
tree, int, tree *,
- tsubst_flags_t);
+ tsubst_flags_t, location_t);
extern tree build_special_member_call (tree, tree, VEC(tree,gc) **,
tree, int, tsubst_flags_t);
extern tree build_new_op (location_t, enum tree_code,
@@ -5594,7 +5594,8 @@ bool empty_expr_stmt_p (tree);
extern tree perform_koenig_lookup (tree, VEC(tree,gc) *, bool,
tsubst_flags_t);
extern tree finish_call_expr (tree, VEC(tree,gc) **, bool,
- bool, tsubst_flags_t);
+ bool, tsubst_flags_t,
+ location_t);
extern tree finish_increment_expr (tree, enum tree_code);
extern tree finish_this_expr (void);
extern tree finish_pseudo_destructor_expr (tree, tree, tree);
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 190939)
+++ cp/semantics.c (working copy)
@@ -2047,7 +2047,7 @@ perform_koenig_lookup (tree fn, VEC(tree
tree
finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual,
- bool koenig_p, tsubst_flags_t complain)
+ bool koenig_p, tsubst_flags_t complain, location_t loc)
{
tree result;
tree orig_fn;
@@ -2117,7 +2117,7 @@ finish_call_expr (tree fn, VEC(tree,gc)
? LOOKUP_NORMAL | LOOKUP_NONVIRTUAL
: LOOKUP_NORMAL),
/*fn_p=*/NULL,
- complain);
+ complain, loc);
}
}
@@ -2167,7 +2167,7 @@ finish_call_expr (tree fn, VEC(tree,gc)
? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
: LOOKUP_NORMAL),
/*fn_p=*/NULL,
- complain);
+ complain, loc);
}
else if (is_overloaded_fn (fn))
{
@@ -3211,6 +3211,8 @@ finish_id_expression (tree id_expression
decl = finish_non_static_data_member
(decl, NULL_TREE,
/*qualifying_scope=*/NULL_TREE);
+ if (EXPR_P (decl))
+ SET_EXPR_LOCATION (decl, location);
pop_deferring_access_checks ();
return decl;
}
@@ -3288,6 +3290,8 @@ finish_id_expression (tree id_expression
push_deferring_access_checks (dk_no_check);
decl = finish_non_static_data_member (decl, NULL_TREE,
/*qualifying_scope=*/NULL_TREE);
+ if (EXPR_P (decl))
+ SET_EXPR_LOCATION (decl, location);
pop_deferring_access_checks ();
}
else if (is_overloaded_fn (decl))
@@ -4978,7 +4982,8 @@ finish_omp_barrier (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
VEC(tree,gc) *vec = make_tree_vector ();
- tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error,
+ input_location);
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -4988,7 +4993,8 @@ finish_omp_flush (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
VEC(tree,gc) *vec = make_tree_vector ();
- tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error,
+ input_location);
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -4998,7 +5004,8 @@ finish_omp_taskwait (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
VEC(tree,gc) *vec = make_tree_vector ();
- tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error,
+ input_location);
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -5008,7 +5015,8 @@ finish_omp_taskyield (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
VEC(tree,gc) *vec = make_tree_vector ();
- tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error,
+ input_location);
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
Index: testsuite/g++.dg/warn/pr26785.C
===================================================================
--- testsuite/g++.dg/warn/pr26785.C (revision 190939)
+++ testsuite/g++.dg/warn/pr26785.C (working copy)
@@ -3,7 +3,7 @@
// { dg-options "-fshow-column" }
class foo {
- foo::foo // { dg-error "3:extra qualification" }
+ foo::foo // { dg-error "8:extra qualification" }
(int a,
int b,
int c);
Index: testsuite/g++.dg/tc1/dr52.C
===================================================================
--- testsuite/g++.dg/tc1/dr52.C (revision 190939)
+++ testsuite/g++.dg/tc1/dr52.C (working copy)
@@ -16,8 +16,8 @@ private:
struct B1 : B {};
struct B2 : B {};
-struct C
-{ // { dg-error "C" }
+struct C // { dg-error "C" }
+{
void foo(void);
};
Index: testsuite/g++.old-deja/g++.brendan/crash16.C
===================================================================
--- testsuite/g++.old-deja/g++.brendan/crash16.C (revision 190939)
+++ testsuite/g++.old-deja/g++.brendan/crash16.C (working copy)
@@ -8,7 +8,7 @@ public:
Graph(void) {} // { dg-error "7:'Graph" }
}
-Graph::Graph(void) // { dg-error "18:return type|1: error: redefinition" }
+Graph::Graph(void) // { dg-error "18:return type|8: error: redefinition" }
{ N = 10;
}
More information about the Gcc-patches
mailing list