@@ -8785,6 +8785,7 @@ struct c_declspecs *
build_null_declspecs (void)
{
struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
+ memset (&ret->locations, 0, cdw_number_of_elements);
ret->type = 0;
ret->expr = 0;
ret->decl_attr = 0;
@@ -8822,7 +8823,8 @@ build_null_declspecs (void)
SPECS, returning SPECS. */
struct c_declspecs *
-declspecs_add_addrspace (struct c_declspecs *specs, addr_space_t as)
+declspecs_add_addrspace (source_location location,
+ struct c_declspecs *specs, addr_space_t as)
{
specs->non_sc_seen_p = true;
specs->declspecs_seen_p = true;
@@ -8833,7 +8835,10 @@ declspecs_add_addrspace (struct c_declspecs *specs, addr_space_t as)
c_addr_space_name (as),
c_addr_space_name (specs->address_space));
else
- specs->address_space = as;
+ {
+ specs->address_space = as;
+ specs->locations[cdw_address_space] = location;
+ }
return specs;
}
@@ -8841,7 +8846,8 @@ declspecs_add_addrspace (struct c_declspecs *specs, addr_space_t as)
returning SPECS. */
struct c_declspecs *
-declspecs_add_qual (struct c_declspecs *specs, tree qual)
+declspecs_add_qual (source_location loc,
+ struct c_declspecs *specs, tree qual)
{
enum rid i;
bool dupe = false;
@@ -8855,20 +8861,23 @@ declspecs_add_qual (struct c_declspecs *specs, tree qual)
case RID_CONST:
dupe = specs->const_p;
specs->const_p = true;
+ specs->locations[cdw_const] = loc;
break;
case RID_VOLATILE:
dupe = specs->volatile_p;
specs->volatile_p = true;
+ specs->locations[cdw_volatile] = loc;
break;
case RID_RESTRICT:
dupe = specs->restrict_p;
specs->restrict_p = true;
+ specs->locations[cdw_restrict] = loc;
break;
default:
gcc_unreachable ();
}
if (dupe && !flag_isoc99)
- pedwarn (input_location, OPT_Wpedantic, "duplicate %qE", qual);
+ pedwarn (loc, OPT_Wpedantic, "duplicate %qE", qual);
return specs;
}
@@ -8921,6 +8930,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
pedwarn_c90 (loc, OPT_Wlong_long,
"ISO C90 does not support %<long long%>");
specs->long_long_p = 1;
+ specs->locations[cdw_long_long] = loc;
break;
}
if (specs->short_p)
@@ -8960,7 +8970,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<long%> and %<_Decimal128%> in "
"declaration specifiers"));
else
- specs->long_p = true;
+ {
+ specs->long_p = true;
+ specs->locations[cdw_long] = loc;
+ }
break;
case RID_SHORT:
dupe = specs->short_p;
@@ -9005,7 +9018,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<short%> and %<_Decimal128%> in "
"declaration specifiers"));
else
- specs->short_p = true;
+ {
+ specs->short_p = true;
+ specs->locations[cdw_short] = loc;
+ }
break;
case RID_SIGNED:
dupe = specs->signed_p;
@@ -9042,7 +9058,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<signed%> and %<_Decimal128%> in "
"declaration specifiers"));
else
- specs->signed_p = true;
+ {
+ specs->signed_p = true;
+ specs->locations[cdw_signed] = loc;
+ }
break;
case RID_UNSIGNED:
dupe = specs->unsigned_p;
@@ -9079,11 +9098,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<unsigned%> and %<_Decimal128%> in "
"declaration specifiers"));
else
- specs->unsigned_p = true;
+ {
+ specs->unsigned_p = true;
+ specs->locations[cdw_unsigned] = loc;
+ }
break;
case RID_COMPLEX:
dupe = specs->complex_p;
- if (!flag_isoc99 && !in_system_header)
+ if (!flag_isoc99 && !in_system_header_at (loc))
pedwarn (loc, OPT_Wpedantic,
"ISO C90 does not support complex types");
if (specs->typespec_word == cts_void)
@@ -9119,7 +9141,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<complex%> and %<_Sat%> in "
"declaration specifiers"));
else
- specs->complex_p = true;
+ {
+ specs->complex_p = true;
+ specs->locations[cdw_complex] = loc;
+ }
break;
case RID_SAT:
dupe = specs->saturating_p;
@@ -9172,7 +9197,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<_Sat%> and %<complex%> in "
"declaration specifiers"));
else
- specs->saturating_p = true;
+ {
+ specs->saturating_p = true;
+ specs->locations[cdw_saturating] = loc;
+ }
break;
default:
gcc_unreachable ();
@@ -9218,7 +9246,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<__int128%> and %<short%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_int128;
+ {
+ specs->typespec_word = cts_int128;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_VOID:
if (specs->long_p)
@@ -9246,7 +9277,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<_Sat%> and %<void%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_void;
+ {
+ specs->typespec_word = cts_void;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_BOOL:
if (specs->long_p)
@@ -9274,7 +9308,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<_Sat%> and %<_Bool%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_bool;
+ {
+ specs->typespec_word = cts_bool;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_CHAR:
if (specs->long_p)
@@ -9290,7 +9327,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<_Sat%> and %<char%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_char;
+ {
+ specs->typespec_word = cts_char;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_INT:
if (specs->saturating_p)
@@ -9298,7 +9338,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<_Sat%> and %<int%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_int;
+ {
+ specs->typespec_word = cts_int;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_FLOAT:
if (specs->long_p)
@@ -9322,7 +9365,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<_Sat%> and %<float%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_float;
+ {
+ specs->typespec_word = cts_float;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_DOUBLE:
if (specs->long_long_p)
@@ -9346,7 +9392,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<_Sat%> and %<double%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_double;
+ {
+ specs->typespec_word = cts_double;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_DFLOAT32:
case RID_DFLOAT64:
@@ -9400,6 +9449,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
specs->typespec_word = cts_dfloat64;
else
specs->typespec_word = cts_dfloat128;
+ specs->locations[cdw_typespec] = loc;
}
if (!targetm.decimal_float_supported_p ())
error_at (loc,
@@ -9425,6 +9475,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
specs->typespec_word = cts_fract;
else
specs->typespec_word = cts_accum;
+ specs->locations[cdw_typespec] = loc;
}
if (!targetm.fixed_point_supported_p ())
error_at (loc,
@@ -9458,6 +9509,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
specs->decl_attr = DECL_ATTRIBUTES (type);
specs->typedef_p = true;
specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+ specs->locations[cdw_typedef] = loc;
/* If this typedef name is defined in a struct, then a C++
lookup would return a different value. */
@@ -9481,13 +9533,17 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
else if (TREE_TYPE (t) == error_mark_node)
;
else
- specs->type = TREE_TYPE (t);
+ {
+ specs->type = TREE_TYPE (t);
+ specs->locations[cdw_typespec] = loc;
+ }
}
else
{
if (TREE_CODE (type) != ERROR_MARK && spec.kind == ctsk_typeof)
{
specs->typedef_p = true;
+ specs->locations[cdw_typedef] = loc;
if (spec.expr)
{
if (specs->expr)
@@ -9508,7 +9564,9 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
declaration specifiers SPECS, returning SPECS. */
struct c_declspecs *
-declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
+declspecs_add_scspec (source_location loc,
+ struct c_declspecs *specs,
+ tree scspec)
{
enum rid i;
enum c_storage_class n = csc_none;
@@ -9529,11 +9587,13 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
difference between gnu89 and C99 inline. */
dupe = false;
specs->inline_p = true;
+ specs->locations[cdw_inline] = loc;
break;
case RID_NORETURN:
/* Duplicate _Noreturn is permitted. */
dupe = false;
specs->noreturn_p = true;
+ specs->locations[cdw_noreturn] = loc;
break;
case RID_THREAD:
dupe = specs->thread_p;
@@ -9544,7 +9604,10 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
else if (specs->storage_class == csc_typedef)
error ("%<__thread%> used with %<typedef%>");
else
- specs->thread_p = true;
+ {
+ specs->thread_p = true;
+ specs->locations[cdw_thread] = loc;
+ }
break;
case RID_AUTO:
n = csc_auto;
@@ -9583,6 +9646,7 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
else
{
specs->storage_class = n;
+ specs->locations[cdw_storage_class] = loc;
if (n != csc_extern && n != csc_static && specs->thread_p)
{
error ("%<__thread%> used with %qE", scspec);
@@ -9597,9 +9661,10 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
returning SPECS. */
struct c_declspecs *
-declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
+declspecs_add_attrs (source_location loc, struct c_declspecs *specs, tree attrs)
{
specs->attrs = chainon (attrs, specs->attrs);
+ specs->locations[cdw_attributes] = loc;
specs->declspecs_seen_p = true;
return specs;
}
@@ -9608,10 +9673,12 @@ declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
alignment is ALIGN) to the declaration specifiers SPECS, returning
SPECS. */
struct c_declspecs *
-declspecs_add_alignas (struct c_declspecs *specs, tree align)
+declspecs_add_alignas (source_location loc,
+ struct c_declspecs *specs, tree align)
{
int align_log;
specs->alignas_p = true;
+ specs->locations[cdw_alignas] = loc;
if (align == error_mark_node)
return specs;
align_log = check_user_alignment (align, true);
@@ -9652,9 +9719,11 @@ finish_declspecs (struct c_declspecs *specs)
{
if (specs->saturating_p)
{
- error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+ error_at (specs->locations[cdw_saturating],
+ "%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
if (!targetm.fixed_point_supported_p ())
- error ("fixed-point types not supported for this target");
+ error_at (specs->locations[cdw_saturating],
+ "fixed-point types not supported for this target");
specs->typespec_word = cts_fract;
}
else if (specs->long_p || specs->short_p
@@ -9665,7 +9734,7 @@ finish_declspecs (struct c_declspecs *specs)
else if (specs->complex_p)
{
specs->typespec_word = cts_double;
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
"ISO C does not support plain %<complex%> meaning "
"%<double complex%>");
}
@@ -9710,7 +9779,7 @@ finish_declspecs (struct c_declspecs *specs)
specs->type = char_type_node;
if (specs->complex_p)
{
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
@@ -9723,7 +9792,7 @@ finish_declspecs (struct c_declspecs *specs)
: int128_integer_type_node);
if (specs->complex_p)
{
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
@@ -9749,7 +9818,7 @@ finish_declspecs (struct c_declspecs *specs)
: integer_type_node);
if (specs->complex_p)
{
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
@@ -315,7 +315,7 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
case CPP_NUMBER:
{
const char *suffix = NULL;
- unsigned int flags = cpp_classify_number (parse_in, tok, &suffix);
+ unsigned int flags = cpp_classify_number (parse_in, tok, &suffix, *loc);
switch (flags & CPP_N_CATEGORY)
{
@@ -417,7 +417,7 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
*cpp_spell_token (parse_in, tok, name, true) = 0;
- error ("stray %qs in program", name);
+ error_at (*loc, "stray %qs in program", name);
}
goto retry;
@@ -2015,14 +2015,15 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
if (c_parser_next_token_is (parser, CPP_NAME))
{
- tree value = c_parser_peek_token (parser)->value;
- c_id_kind kind = c_parser_peek_token (parser)->id_kind;
+ c_token *name_token = c_parser_peek_token (parser);
+ tree value = name_token->value;
+ c_id_kind kind = name_token->id_kind;
if (kind == C_ID_ADDRSPACE)
{
addr_space_t as
- = c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE;
- declspecs_add_addrspace (specs, as);
+ = name_token->keyword - RID_FIRST_ADDR_SPACE;
+ declspecs_add_addrspace (name_token->location, specs, as);
c_parser_consume_token (parser);
attrs_ok = true;
continue;
@@ -2068,7 +2069,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
}
t.expr = NULL_TREE;
t.expr_const_operands = true;
- declspecs_add_type (loc, specs, t);
+ declspecs_add_type (name_token->location, specs, t);
continue;
}
if (c_parser_next_token_is (parser, CPP_LESS))
@@ -2104,7 +2105,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
/* TODO: Distinguish between function specifiers (inline, noreturn)
and storage class specifiers, either here or in
declspecs_add_scspec. */
- declspecs_add_scspec (specs, c_parser_peek_token (parser)->value);
+ declspecs_add_scspec (loc, specs,
+ c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
break;
case RID_UNSIGNED:
@@ -2171,18 +2173,18 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
case RID_VOLATILE:
case RID_RESTRICT:
attrs_ok = true;
- declspecs_add_qual (specs, c_parser_peek_token (parser)->value);
+ declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
break;
case RID_ATTRIBUTE:
if (!attrs_ok)
goto out;
attrs = c_parser_attributes (parser);
- declspecs_add_attrs (specs, attrs);
+ declspecs_add_attrs (loc, specs, attrs);
break;
case RID_ALIGNAS:
align = c_parser_alignas_specifier (parser);
- declspecs_add_alignas (specs, align);
+ declspecs_add_alignas (loc, specs, align);
break;
default:
goto out;
@@ -3332,7 +3334,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
specs = build_null_declspecs ();
if (attrs)
{
- declspecs_add_attrs (specs, attrs);
+ declspecs_add_attrs (input_location, specs, attrs);
attrs = NULL_TREE;
}
c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
@@ -222,8 +222,45 @@ enum c_typespec_keyword {
cts_accum
};
-/* A sequence of declaration specifiers in C. */
+/* This enum lists all the possible declarator specifiers, storage
+ class or attribute that a user can write. There is at least one
+ enumerator per possible declarator specifier in the struct
+ c_declspecs below.
+
+ It is used to index the array of declspec locations in struct
+ c_declspecs. */
+enum c_declspec_word {
+ cdw_typespec /* A catch-all for a typespec. */,
+ cdw_storage_class /* A catch-all for a storage class */,
+ cdw_attributes,
+ cdw_typedef,
+ cdw_explicit_signed,
+ cdw_deprecated,
+ cdw_default_int,
+ cdw_long,
+ cdw_long_long,
+ cdw_short,
+ cdw_signed,
+ cdw_unsigned,
+ cdw_complex,
+ cdw_inline,
+ cdw_noreturn,
+ cdw_thread,
+ cdw_const,
+ cdw_volatile,
+ cdw_restrict,
+ cdw_saturating,
+ cdw_alignas,
+ cdw_address_space,
+ cdw_number_of_elements /* This one must always be the last
+ enumerator. */
+};
+
+/* A sequence of declaration specifiers in C. When a new declaration
+ specifier is added, please update the enum c_declspec_word above
+ accordingly. */
struct c_declspecs {
+ source_location locations[cdw_number_of_elements];
/* The type specified, if a single type specifier such as a struct,
union or enum specifier, typedef name or typeof specifies the
whole type, or NULL_TREE if none or a keyword such as "void" or
@@ -509,15 +546,20 @@ extern struct c_declarator *build_id_declarator (tree);
extern struct c_declarator *make_pointer_declarator (struct c_declspecs *,
struct c_declarator *);
extern struct c_declspecs *build_null_declspecs (void);
-extern struct c_declspecs *declspecs_add_qual (struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_qual (source_location,
+ struct c_declspecs *, tree);
extern struct c_declspecs *declspecs_add_type (location_t,
struct c_declspecs *,
struct c_typespec);
-extern struct c_declspecs *declspecs_add_scspec (struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_addrspace (struct c_declspecs *,
+extern struct c_declspecs *declspecs_add_scspec (source_location,
+ struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_attrs (source_location,
+ struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_addrspace (source_location,
+ struct c_declspecs *,
addr_space_t);
-extern struct c_declspecs *declspecs_add_alignas (struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_alignas (source_location,
+ struct c_declspecs *, tree);
extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
/* in c-objc-common.c */
@@ -4643,7 +4643,40 @@ typedef enum cp_storage_class {
sc_mutable
} cp_storage_class;
-/* An individual decl-specifier. */
+/* The possible decl spec, attribute or type spec that the user can
+ write. This is used to index the array of locations for the
+ declspecs in struct cp_decl_specifier_seq below. */
+
+typedef enum cp_decl_spec_word {
+ cpdw_signed,
+ cpdw_unsigned,
+ cpdw_short,
+ cpdw_long,
+ cpdw_const,
+ cpdw_volatile,
+ cpdw_restrict,
+ cpdw_inline,
+ cpdw_virtual,
+ cpdw_explicit,
+ cpdw_friend,
+ cpdw_typedef,
+ cpdw_alias,
+ cpdw_constexpr,
+ cpdw_complex,
+ cpdw_thread, /* From the beginning to here, each enumerator has the
+ same value as its enum cp_decl_spec counterpart. */
+
+ cpdw_type_spec, /* From here onward, these enumerators have no
+ counterpart in enum cp_decl_spec. */
+ cpdw_builtin_type_spec,
+ cpdw_attribute,
+ cpdw_storage_class,
+ cpdw_number_of_elements /* This enumerator must always be the last one. */
+} cp_decl_spec_word;
+
+/* An individual decl-specifier. Whenever a new enumarator is added
+ here, please remember to add a matching one to enum
+ cp_decl_spec_word above. */
typedef enum cp_decl_spec {
ds_first,
@@ -4663,7 +4696,7 @@ typedef enum cp_decl_spec {
ds_constexpr,
ds_complex,
ds_thread,
- ds_last
+ ds_last /* This enumerator must always be the last one. */
} cp_decl_spec;
/* A decl-specifier-seq. */
@@ -4671,9 +4704,9 @@ typedef enum cp_decl_spec {
typedef struct cp_decl_specifier_seq {
/* The number of times each of the keywords has been seen. */
unsigned specs[(int) ds_last];
- /* The location of the primary type. Mainly used for error
- reporting. */
- location_t type_location;
+ /* An array of locations for the declaration sepecifiers, indexed
+ by enum cp_decl_spec_word. */
+ source_location locations[cpdw_number_of_elements];
/* The primary type, if any, given by the decl-specifier-seq.
Modifiers, like "short", "const", and "unsigned" are not
reflected here. This field will be a TYPE, unless a typedef-name
@@ -2495,8 +2495,7 @@ cp_parser_simulate_error (cp_parser* parser)
/* Check for repeated decl-specifiers. */
static void
-cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
- location_t location)
+cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
{
int ds;
@@ -2509,9 +2508,11 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
if (ds == ds_long)
{
if (count > 2)
- error_at (location, "%<long long long%> is too long for GCC");
+ error_at (decl_specs->locations[cpdw_long],
+ "%<long long long%> is too long for GCC");
else
- pedwarn_cxx98 (location, OPT_Wlong_long,
+ pedwarn_cxx98 (decl_specs->locations[cpdw_long],
+ OPT_Wlong_long,
"ISO C++ 1998 does not support %<long long%>");
}
else if (count > 1)
@@ -2534,7 +2535,8 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
"__complex",
"__thread"
};
- error_at (location, "duplicate %qs", decl_spec_names[ds]);
+ error_at (decl_specs->locations[ds],
+ "duplicate %qs", decl_spec_names[ds]);
}
}
}
@@ -10572,6 +10574,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
decl_specs->attributes
= chainon (decl_specs->attributes,
cp_parser_attributes_opt (parser));
+ if (decl_specs->locations[cpdw_attribute] == 0)
+ decl_specs->locations[cpdw_attribute] = token->location;
continue;
}
/* Assume we will find a decl-specifier keyword. */
@@ -10592,6 +10596,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
else
{
++decl_specs->specs[(int) ds_friend];
+ decl_specs->locations[cpdw_friend] = token->location;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
}
@@ -10599,6 +10604,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
case RID_CONSTEXPR:
++decl_specs->specs[(int) ds_constexpr];
+ decl_specs->locations[cpdw_constexpr] = token->location;
cp_lexer_consume_token (parser->lexer);
break;
@@ -10616,6 +10622,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
typedef */
case RID_TYPEDEF:
++decl_specs->specs[(int) ds_typedef];
+ decl_specs->locations[cpdw_typedef] = token->location;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
/* A constructor declarator cannot appear in a typedef. */
@@ -10670,6 +10677,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
++decl_specs->specs[(int) ds_thread];
+ decl_specs->locations[cpdw_thread] = token->location;
break;
default:
@@ -10766,12 +10774,12 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
flags |= CP_PARSER_FLAGS_OPTIONAL;
}
- cp_parser_check_decl_spec (decl_specs, start_token->location);
+ cp_parser_check_decl_spec (decl_specs);
/* Don't allow a friend specifier with a class definition. */
if (decl_specs->specs[(int) ds_friend] != 0
&& (*declares_class_or_enum & 2))
- error_at (start_token->location,
+ error_at (decl_specs->locations[cpdw_friend],
"class definition may not be declared a friend");
}
@@ -10833,7 +10841,10 @@ cp_parser_function_specifier_opt (cp_parser* parser,
{
case RID_INLINE:
if (decl_specs)
- ++decl_specs->specs[(int) ds_inline];
+ {
+ ++decl_specs->specs[(int) ds_inline];
+ decl_specs->locations[cpdw_inline] = token->location;
+ }
break;
case RID_VIRTUAL:
@@ -10843,12 +10854,18 @@ cp_parser_function_specifier_opt (cp_parser* parser,
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
error_at (token->location, "templates may not be %<virtual%>");
else if (decl_specs)
- ++decl_specs->specs[(int) ds_virtual];
+ {
+ ++decl_specs->specs[(int) ds_virtual];
+ decl_specs->locations[cpdw_virtual] = token->location;
+ }
break;
case RID_EXPLICIT:
if (decl_specs)
- ++decl_specs->specs[(int) ds_explicit];
+ {
+ ++decl_specs->specs[(int) ds_explicit];
+ decl_specs->locations[cpdw_explicit] = token->location;
+ }
break;
default:
@@ -13155,7 +13172,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
if (declares_class_or_enum & 2)
cp_parser_check_for_definition_in_return_type (declarator,
decl_specifiers.type,
- decl_specifiers.type_location);
+ decl_specifiers.locations[cpdw_type_spec]);
if (declarator != cp_error_declarator)
{
if (decl_specifiers.specs[(int)ds_inline])
@@ -13427,6 +13444,10 @@ cp_parser_type_specifier (cp_parser* parser,
{
++decl_specs->specs[(int)ds];
decl_specs->any_specifiers_p = true;
+ /* The value of a cp_decl_spec enumerator is the same as a
+ cp_decl_spec_word enumerator, so we can use DS to index
+ decl_specs->locations. */
+ decl_specs->locations[ds] = token->location;
}
return cp_lexer_consume_token (parser->lexer)->u.value;
}
@@ -13517,7 +13538,10 @@ cp_parser_simple_type_specifier (cp_parser* parser,
break;
case RID_SHORT:
if (decl_specs)
- ++decl_specs->specs[(int) ds_short];
+ {
+ ++decl_specs->specs[(int) ds_short];
+ decl_specs->locations[cpdw_short] = token->location;
+ }
type = short_integer_type_node;
break;
case RID_INT:
@@ -13534,17 +13558,26 @@ cp_parser_simple_type_specifier (cp_parser* parser,
break;
case RID_LONG:
if (decl_specs)
- ++decl_specs->specs[(int) ds_long];
+ {
+ ++decl_specs->specs[(int) ds_long];
+ decl_specs->locations[cpdw_long] = token->location;
+ }
type = long_integer_type_node;
break;
case RID_SIGNED:
if (decl_specs)
- ++decl_specs->specs[(int) ds_signed];
+ {
+ ++decl_specs->specs[(int) ds_signed];
+ decl_specs->locations[cpdw_signed] = token->location;
+ }
type = integer_type_node;
break;
case RID_UNSIGNED:
if (decl_specs)
- ++decl_specs->specs[(int) ds_unsigned];
+ {
+ ++decl_specs->specs[(int) ds_unsigned];
+ decl_specs->locations[cpdw_unsigned] = token->location;
+ }
type = unsigned_type_node;
break;
case RID_FLOAT:
@@ -15500,7 +15533,7 @@ cp_parser_init_declarator (cp_parser* parser,
if (declares_class_or_enum & 2)
cp_parser_check_for_definition_in_return_type (declarator,
decl_specifiers->type,
- decl_specifiers->type_location);
+ decl_specifiers->locations[cpdw_type_spec]);
/* Figure out what scope the entity declared by the DECLARATOR is
located in. `grokdeclarator' sometimes changes the scope, so
@@ -16922,7 +16955,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
}
- cp_parser_check_decl_spec (type_specifier_seq, start_token->location);
+ cp_parser_check_decl_spec (type_specifier_seq);
}
/* Parse a parameter-declaration-clause.
@@ -19027,7 +19060,7 @@ cp_parser_member_declaration (cp_parser* parser)
if (declares_class_or_enum & 2)
cp_parser_check_for_definition_in_return_type
(declarator, decl_specifiers.type,
- decl_specifiers.type_location);
+ decl_specifiers.locations[cpdw_type_spec]);
/* Look for an asm-specification. */
asm_specification = cp_parser_asm_specification_opt (parser);
@@ -22035,6 +22068,7 @@ cp_parser_set_storage_class (cp_parser *parser,
{
error_at (location, "%<__thread%> before %qD", ridpointers[keyword]);
decl_specs->specs[(int) ds_thread] = 0;
+ decl_specs->locations[cpdw_thread] = location;
}
switch (keyword)
@@ -22058,6 +22092,7 @@ cp_parser_set_storage_class (cp_parser *parser,
gcc_unreachable ();
}
decl_specs->storage_class = storage_class;
+ decl_specs->locations[cpdw_storage_class] = location;
/* A storage class specifier cannot be applied alongside a typedef
specifier. If there is a typedef specifier present then set
@@ -22096,11 +22131,12 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
|| decl_specs->specs[(int) ds_signed]))
{
decl_specs->redefined_builtin_type = type_spec;
+ decl_specs->locations[cpdw_builtin_type_spec] = location;
if (!decl_specs->type)
{
decl_specs->type = type_spec;
decl_specs->type_definition_p = false;
- decl_specs->type_location = location;
+ decl_specs->locations[cpdw_type_spec] = location;
}
}
else if (decl_specs->type)
@@ -22110,7 +22146,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
decl_specs->type = type_spec;
decl_specs->type_definition_p = type_definition_p;
decl_specs->redefined_builtin_type = NULL_TREE;
- decl_specs->type_location = location;
+ decl_specs->locations[cpdw_type_spec] = location;
}
}
new file mode 100644
@@ -0,0 +1,16 @@
+/* Contributed by Dodji Seketeli <dodji@redhat.com> */
+/* Origin: PR preprocessor/7263 */
+/* { dg-options "-pedantic -std=c++98 -ftrack-macro-expansion=1" } */
+/* { dg-do compile } */
+
+/* This tests the proprer suppression of warning coming from macro
+ defined in system headers and expanded in a non-system header
+ location. */
+#include "syshdr3.h"
+
+static _Complex float c = _Complex_I + _Complex_I; /* These macros are defined in
+ system header so we should
+ have no warning here. */
+U_LL u = ONE_ULL; /* Likewise here. */
+
+unsigned long long v = 1ULL; /* { dg-warning "long long" } */
new file mode 100644
@@ -0,0 +1,7 @@
+#pragma GCC system_header
+
+#define _Complex __complex__
+#define _Complex_I 1.0iF
+
+#define U_LL unsigned long long
+#define ONE_ULL 1ULL
new file mode 100644
@@ -0,0 +1,18 @@
+/*
+ Origin: Dodji Seketeli <dodji@redhat.com>
+ { dg-options "-std=c++98 -pedantic" }
+ { dg-do compile }
+ */
+
+#include "system-binary-constants-1.h"
+
+int
+foo (void)
+{
+#if BINARY_INT_CONSTANT_IN_SYSTEM_HEADER /* A binary constant defined
+ in system header. No
+ warning. */
+ return 23;
+#endif
+ return 0b1101; /* { dg-warning "binary constants are a GCC extension" } */
+}
new file mode 100644
@@ -0,0 +1,3 @@
+#pragma GCC system_header
+
+#define BINARY_INT_CONSTANT_IN_SYSTEM_HEADER 0b1101
@@ -2,7 +2,7 @@
/* Origin: Joerg Wunsch <j.gnu@uriah.heep.sax.de>. */
/* { dg-do compile } */
-/* { dg-options "-std=iso9899:1999 -pedantic" } */
+/* { dg-options "-std=iso9899:1999 -pedantic -ftrack-macro-expansion=0" } */
#define FOO 0b1101
@@ -2,7 +2,7 @@
/* Origin: Joerg Wunsch <j.gnu@uriah.heep.sax.de>. */
/* { dg-do compile } */
-/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors -ftrack-macro-expansion=0" } */
#define FOO 0b1101
@@ -1,6 +1,6 @@
/* PR 7263: __extension__ keyword doesn't suppress warning on LL or ULL constants. */
/* { dg-do compile } */
-/* { dg-options "-std=c99 -pedantic-errors" } */
+/* { dg-options "-std=c99 -pedantic-errors -ftrack-macro-expansion=0" } */
#include "pr7263-3.h"
__complex__ bar () /* { dg-error "ISO C does not support plain .complex. meaning .double complex." } */
{
new file mode 100644
@@ -0,0 +1,16 @@
+/* Contributed by Dodji Seketeli <dodji@redhat.com> */
+/* Origin: PR preprocessor/7263 */
+/* { dg-options "-pedantic -std=c89 -ftrack-macro-expansion=1" } */
+/* { dg-do compile } */
+
+/* This tests the proprer suppression of warning coming from macro
+ defined in system headers and expanded in a non-system header
+ location. */
+#include "syshdr3.h"
+
+static _Complex float c = _Complex_I + _Complex_I; /* These macros are defined in
+ system header so we should
+ have no warning here. */
+U_LL u = ONE_ULL; /* Likewise here. */
+
+unsigned long long v = 1ULL; /* { dg-warning "long long" } */
new file mode 100644
@@ -0,0 +1,7 @@
+#pragma GCC system_header
+
+#define _Complex __complex__
+#define _Complex_I 1.0iF
+
+#define U_LL unsigned long long
+#define ONE_ULL 1ULL
@@ -1,7 +1,7 @@
/* Copyright (C) 2001 Free Software Foundation, Inc. */
/* { dg-do preprocess } */
-/* { dg-options "-std=gnu99 -pedantic -Wtraditional" } */
+/* { dg-options "-std=gnu99 -pedantic -Wtraditional -ftrack-macro-expansion=0" } */
/* Tests diagnostics are suppressed for some macros defined in system
headers. */
@@ -1,7 +1,7 @@
/* Copyright (C) 2001 Free Software Foundation, Inc. */
/* { dg-do compile } */
-/* { dg-options "-std=gnu99 -pedantic -Wtraditional" } */
+/* { dg-options "-std=gnu99 -pedantic -Wtraditional -ftrack-macro-expansion=0" } */
/* Tests diagnostics are suppressed for some macros defined in system
headers. */
@@ -20,10 +20,10 @@ f3 (void)
return 0k; /* { dg-error "not supported" "reject fixed-point" } */
}
-_Sat
-f4 (void) /* { dg-error "not supported" "reject fixed-point" } */
+_Sat /* { dg-error "not supported" "reject fixed-point" } */
+f4 (void)
{
return 0k; /* { dg-error "not supported" "reject fixed-point" } */
}
-/* { dg-error "is used without" "" { target *-*-* } 24 } */
+/* { dg-error "is used without" "" { target *-*-* } 23 } */
new file mode 100644
@@ -0,0 +1,18 @@
+/*
+ Origin: Dodji Seketeli <dodji@redhat.com>
+ { dg-options "-std=iso9899:1999 -pedantic" }
+ { dg-do compile }
+ */
+
+#include "system-binary-constants-1.h"
+
+int
+foo (void)
+{
+#if BINARY_INT_CONSTANT_IN_SYSTEM_HEADER /* A binary constant defined
+ in system header. No
+ warning. */
+ return 23;
+#endif
+ return 0b1101; /* { dg-warning "binary constants are a GCC extension" } */
+}
new file mode 100644
@@ -0,0 +1,3 @@
+#pragma GCC system_header
+
+#define BINARY_INT_CONSTANT_IN_SYSTEM_HEADER 0b1101
@@ -59,7 +59,7 @@ static cpp_num num_rshift (cpp_num, size_t, size_t);
static cpp_num append_digit (cpp_num, int, int, size_t);
static cpp_num parse_defined (cpp_reader *);
-static cpp_num eval_token (cpp_reader *, const cpp_token *);
+static cpp_num eval_token (cpp_reader *, const cpp_token *, source_location);
static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype);
static unsigned int interpret_float_suffix (const uchar *, size_t);
static unsigned int interpret_int_suffix (const uchar *, size_t);
@@ -76,6 +76,12 @@ static void check_promotion (cpp_reader *, const struct op *);
#define SYNTAX_ERROR2(msgid, arg) \
do { cpp_error (pfile, CPP_DL_ERROR, msgid, arg); goto syntax_error; } \
while(0)
+#define SYNTAX_ERROR_AT(loc, msgid) \
+ do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid); goto syntax_error; } \
+ while(0)
+#define SYNTAX_ERROR2_AT(loc, msgid, arg) \
+ do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid, arg); goto syntax_error; } \
+ while(0)
/* Subroutine of cpp_classify_number. S points to a float suffix of
length LEN, possibly zero. Returns 0 for an invalid suffix, or a
@@ -358,11 +364,18 @@ cpp_get_userdef_suffix (const cpp_token *tok)
/* Categorize numeric constants according to their field (integer,
floating point, or invalid), radix (decimal, octal, hexadecimal),
- and type suffixes. In C++0X if UD_SUFFIX is non null it will be
- assigned any unrecognized suffix for a user-defined literal. */
+ and type suffixes.
+
+ TOKEN is the token that represents the numeric constant to
+ classify.
+
+ In C++0X if UD_SUFFIX is non null it will be assigned
+ any unrecognized suffix for a user-defined literal.
+
+ VIRTUAL_LOCATION is the virtual location for TOKEN. */
unsigned int
cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
- const char **ud_suffix)
+ const char **ud_suffix, source_location virtual_location)
{
const uchar *str = token->val.str.text;
const uchar *limit;
@@ -421,7 +434,8 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
if (float_flag == NOT_FLOAT)
float_flag = AFTER_POINT;
else
- SYNTAX_ERROR ("too many decimal points in number");
+ SYNTAX_ERROR_AT (virtual_location,
+ "too many decimal points in number");
}
else if ((radix <= 10 && (c == 'e' || c == 'E'))
|| (radix == 16 && (c == 'p' || c == 'P')))
@@ -449,8 +463,8 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
radix = 10;
if (CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "fixed-point constants are a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "fixed-point constants are a GCC extension");
goto syntax_ok;
}
else
@@ -463,26 +477,29 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
if (max_digit >= radix)
{
if (radix == 2)
- SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit);
+ SYNTAX_ERROR2_AT (virtual_location,
+ "invalid digit \"%c\" in binary constant", '0' + max_digit);
else
- SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
+ SYNTAX_ERROR2_AT (virtual_location,
+ "invalid digit \"%c\" in octal constant", '0' + max_digit);
}
if (float_flag != NOT_FLOAT)
{
if (radix == 2)
{
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid prefix \"0b\" for floating constant");
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "invalid prefix \"0b\" for floating constant");
return CPP_N_INVALID;
}
if (radix == 16 && !seen_digit)
- SYNTAX_ERROR ("no digits in hexadecimal floating constant");
+ SYNTAX_ERROR_AT (virtual_location,
+ "no digits in hexadecimal floating constant");
if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "use of C99 hexadecimal floating constant");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "use of C99 hexadecimal floating constant");
if (float_flag == AFTER_EXPON)
{
@@ -491,14 +508,15 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
/* Exponent is decimal, even if string is a hex float. */
if (!ISDIGIT (*str))
- SYNTAX_ERROR ("exponent has no digits");
+ SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
do
str++;
while (ISDIGIT (*str));
}
else if (radix == 16)
- SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
+ SYNTAX_ERROR_AT (virtual_location,
+ "hexadecimal floating constants require an exponent");
result = interpret_float_suffix (str, limit - str);
if (result == 0)
@@ -511,9 +529,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
}
else
{
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid suffix \"%.*s\" on floating constant",
- (int) (limit - str), str);
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "invalid suffix \"%.*s\" on floating constant",
+ (int) (limit - str), str);
return CPP_N_INVALID;
}
}
@@ -522,33 +540,33 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
if (limit != str
&& CPP_WTRADITIONAL (pfile)
&& ! cpp_sys_macro_p (pfile))
- cpp_warning (pfile, CPP_W_TRADITIONAL,
- "traditional C rejects the \"%.*s\" suffix",
- (int) (limit - str), str);
+ cpp_warning_with_line (pfile, CPP_W_TRADITIONAL, virtual_location, 0,
+ "traditional C rejects the \"%.*s\" suffix",
+ (int) (limit - str), str);
/* A suffix for double is a GCC extension via decimal float support.
If the suffix also specifies an imaginary value we'll catch that
later. */
if ((result == CPP_N_MEDIUM) && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "suffix for double constant is a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "suffix for double constant is a GCC extension");
/* Radix must be 10 for decimal floats. */
if ((result & CPP_N_DFLOAT) && radix != 10)
{
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid suffix \"%.*s\" with hexadecimal floating constant",
- (int) (limit - str), str);
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "invalid suffix \"%.*s\" with hexadecimal floating constant",
+ (int) (limit - str), str);
return CPP_N_INVALID;
}
if ((result & (CPP_N_FRACT | CPP_N_ACCUM)) && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "fixed-point constants are a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "fixed-point constants are a GCC extension");
if ((result & CPP_N_DFLOAT) && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "decimal float constants are a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "decimal float constants are a GCC extension");
result |= CPP_N_FLOATING;
}
@@ -565,9 +583,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
}
else
{
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid suffix \"%.*s\" on integer constant",
- (int) (limit - str), str);
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "invalid suffix \"%.*s\" on integer constant",
+ (int) (limit - str), str);
return CPP_N_INVALID;
}
}
@@ -581,9 +599,10 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
&& CPP_OPTION (pfile, cpp_warn_long_long);
if (u_or_i || large)
- cpp_warning (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
- "traditional C rejects the \"%.*s\" suffix",
- (int) (limit - str), str);
+ cpp_warning_with_line (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
+ virtual_location, 0,
+ "traditional C rejects the \"%.*s\" suffix",
+ (int) (limit - str), str);
}
if ((result & CPP_N_WIDTH) == CPP_N_LARGE
@@ -594,9 +613,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
: N_("use of C99 long long integer constant");
if (CPP_OPTION (pfile, c99))
- cpp_warning (pfile, CPP_W_LONG_LONG, message);
+ cpp_warning_with_line (pfile, CPP_W_LONG_LONG, virtual_location,
+ 0, message);
else
- cpp_pedwarning (pfile, CPP_W_LONG_LONG, message);
+ cpp_pedwarning_with_line (pfile, CPP_W_LONG_LONG,
+ virtual_location, 0, message);
}
result |= CPP_N_INTEGER;
@@ -604,11 +625,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
syntax_ok:
if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "imaginary constants are a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "imaginary constants are a GCC extension");
if (radix == 2 && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "binary constants are a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+ "binary constants are a GCC extension");
if (radix == 10)
result |= CPP_N_DECIMAL;
@@ -896,7 +917,8 @@ parse_defined (cpp_reader *pfile)
number or character constant, or the result of the "defined" or "#"
operators). */
static cpp_num
-eval_token (cpp_reader *pfile, const cpp_token *token)
+eval_token (cpp_reader *pfile, const cpp_token *token,
+ source_location virtual_location)
{
cpp_num result;
unsigned int temp;
@@ -908,21 +930,21 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
switch (token->type)
{
case CPP_NUMBER:
- temp = cpp_classify_number (pfile, token, NULL);
+ temp = cpp_classify_number (pfile, token, NULL, virtual_location);
if (temp & CPP_N_USERDEF)
cpp_error (pfile, CPP_DL_ERROR,
"user-defined literal in preprocessor expression");
switch (temp & CPP_N_CATEGORY)
{
case CPP_N_FLOATING:
- cpp_error (pfile, CPP_DL_ERROR,
- "floating constant in preprocessor expression");
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "floating constant in preprocessor expression");
break;
case CPP_N_INTEGER:
if (!(temp & CPP_N_IMAGINARY))
return cpp_interpret_integer (pfile, token, temp);
- cpp_error (pfile, CPP_DL_ERROR,
- "imaginary number in preprocessor expression");
+ cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
+ "imaginary number in preprocessor expression");
break;
case CPP_N_INVALID:
@@ -969,8 +991,9 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
result.high = 0;
result.low = 0;
if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
- cpp_warning (pfile, CPP_W_UNDEF, "\"%s\" is not defined",
- NODE_NAME (token->val.node.node));
+ cpp_warning_with_line (pfile, CPP_W_UNDEF, virtual_location, 0,
+ "\"%s\" is not defined",
+ NODE_NAME (token->val.node.node));
}
break;
@@ -980,11 +1003,12 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
/* A pedantic warning takes precedence over a deprecated
warning here. */
if (CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "assertions are a GCC extension");
+ cpp_error_with_line (pfile, CPP_DL_PEDWARN,
+ virtual_location, 0,
+ "assertions are a GCC extension");
else if (CPP_OPTION (pfile, cpp_warn_deprecated))
- cpp_warning (pfile, CPP_W_DEPRECATED,
- "assertions are a deprecated extension");
+ cpp_warning_with_line (pfile, CPP_W_DEPRECATED, virtual_location, 0,
+ "assertions are a deprecated extension");
}
_cpp_test_assertion (pfile, &temp);
result.high = 0;
@@ -1086,6 +1110,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
struct op *top = pfile->op_stack;
unsigned int lex_count;
bool saw_leading_not, want_value = true;
+ source_location virtual_location = 0;
pfile->state.skip_eval = 0;
@@ -1102,9 +1127,9 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
struct op op;
lex_count++;
- op.token = cpp_get_token (pfile);
+ op.token = cpp_get_token_with_location (pfile, &virtual_location);
op.op = op.token->type;
- op.loc = op.token->src_loc;
+ op.loc = virtual_location;
switch (op.op)
{
@@ -1117,10 +1142,11 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
case CPP_NAME:
case CPP_HASH:
if (!want_value)
- SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
- cpp_token_as_text (pfile, op.token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "missing binary operator before token \"%s\"",
+ cpp_token_as_text (pfile, op.token));
want_value = false;
- top->value = eval_token (pfile, op.token);
+ top->value = eval_token (pfile, op.token, op.loc);
continue;
case CPP_NOT:
@@ -1137,8 +1163,9 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
default:
if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ)
- SYNTAX_ERROR2 ("token \"%s\" is not valid in preprocessor expressions",
- cpp_token_as_text (pfile, op.token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "token \"%s\" is not valid in preprocessor expressions",
+ cpp_token_as_text (pfile, op.token));
break;
}
@@ -1146,27 +1173,32 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
if (optab[op.op].flags & NO_L_OPERAND)
{
if (!want_value)
- SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
- cpp_token_as_text (pfile, op.token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "missing binary operator before token \"%s\"",
+ cpp_token_as_text (pfile, op.token));
}
else if (want_value)
{
/* We want a number (or expression) and haven't got one.
Try to emit a specific diagnostic. */
if (op.op == CPP_CLOSE_PAREN && top->op == CPP_OPEN_PAREN)
- SYNTAX_ERROR ("missing expression between '(' and ')'");
+ SYNTAX_ERROR_AT (op.loc,
+ "missing expression between '(' and ')'");
if (op.op == CPP_EOF && top->op == CPP_EOF)
- SYNTAX_ERROR2 ("%s with no expression", is_if ? "#if" : "#elif");
+ SYNTAX_ERROR2_AT (op.loc,
+ "%s with no expression", is_if ? "#if" : "#elif");
if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
- SYNTAX_ERROR2 ("operator '%s' has no right operand",
- cpp_token_as_text (pfile, top->token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "operator '%s' has no right operand",
+ cpp_token_as_text (pfile, top->token));
else if (op.op == CPP_CLOSE_PAREN || op.op == CPP_EOF)
/* Complain about missing paren during reduction. */;
else
- SYNTAX_ERROR2 ("operator '%s' has no left operand",
- cpp_token_as_text (pfile, op.token));
+ SYNTAX_ERROR2_AT (op.loc,
+ "operator '%s' has no left operand",
+ cpp_token_as_text (pfile, op.token));
}
top = reduce (pfile, top, op.op);
@@ -1191,7 +1223,8 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
break;
case CPP_COLON:
if (top->op != CPP_QUERY)
- SYNTAX_ERROR (" ':' without preceding '?'");
+ SYNTAX_ERROR_AT (op.loc,
+ " ':' without preceding '?'");
if (!num_zerop (top[-1].value)) /* Was '?' condition true? */
pfile->state.skip_eval++;
else
@@ -1208,7 +1241,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
top->op = op.op;
top->token = op.token;
- top->loc = op.token->src_loc;
+ top->loc = op.loc;
}
/* The controlling macro expression is only valid if we called lex 3
@@ -1219,8 +1252,9 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
if (top != pfile->op_stack)
{
- cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in %s",
- is_if ? "#if" : "#elif");
+ cpp_error_with_line (pfile, CPP_DL_ICE, top->loc, 0,
+ "unbalanced stack in %s",
+ is_if ? "#if" : "#elif");
syntax_error:
return false; /* Return false on syntax error. */
}
@@ -851,7 +851,7 @@ struct cpp_num
/* Classify a CPP_NUMBER token. The return value is a combination of
the flags from the above sets. */
extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *,
- const char **);
+ const char **, source_location);
/* Return the classification flags for a float suffix. */
extern unsigned int cpp_interpret_float_suffix (const char *, size_t);