@@ -8159,7 +8159,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
/* Build and install a CONST_DECL for one value of the
current enumeration type (one that was begun with start_enum).
DECL_LOC is the location of the enumerator.
- LOC is the location of the '=' operator if any, DECL_LOC otherwise.
+ LOC is the location of the value if any, DECL_LOC otherwise.
Return a tree-list containing the CONST_DECL and its value.
Assignment of sequential values by default is handled here. */
@@ -8169,6 +8169,10 @@ build_enumerator (location_t decl_loc, location_t loc,
{
tree decl, type;
+ rich_location richloc (line_table, decl_loc);
+ if (loc && loc != decl_loc)
+ richloc.add_range (loc, false);
+
/* Validate and default VALUE. */
if (value != 0)
@@ -8179,8 +8183,10 @@ build_enumerator (location_t decl_loc, location_t loc,
value = 0;
else if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
{
- error_at (loc, "enumerator value for %qE is not an integer constant",
- name);
+ error_at_rich_loc
+ (&richloc,
+ "enumerator value for %qE is not an integer constant",
+ name);
value = 0;
}
else
@@ -8189,14 +8195,17 @@ build_enumerator (location_t decl_loc, location_t loc,
{
value = c_fully_fold (value, false, NULL);
if (TREE_CODE (value) == INTEGER_CST)
- pedwarn (loc, OPT_Wpedantic,
- "enumerator value for %qE is not an integer "
- "constant expression", name);
+ pedwarn_at_rich_loc
+ (&richloc, OPT_Wpedantic,
+ "enumerator value for %qE is not an integer "
+ "constant expression", name);
}
if (TREE_CODE (value) != INTEGER_CST)
{
- error ("enumerator value for %qE is not an integer constant",
- name);
+ error_at_rich_loc
+ (&richloc,
+ "enumerator value for %qE is not an integer constant",
+ name);
value = 0;
}
else
@@ -8214,15 +8223,16 @@ build_enumerator (location_t decl_loc, location_t loc,
{
value = the_enum->enum_next_value;
if (the_enum->enum_overflow)
- error_at (loc, "overflow in enumeration values");
+ error_at_rich_loc (&richloc, "overflow in enumeration values");
}
/* Even though the underlying type of an enum is unspecified, the
type of enumeration constants is explicitly defined as int
(6.4.4.3/2 in the C99 Standard). GCC allows any integer type as
an extension. */
else if (!int_fits_type_p (value, integer_type_node))
- pedwarn (loc, OPT_Wpedantic,
- "ISO C restricts enumerator values to range of %<int%>");
+ pedwarn_at_rich_loc
+ (&richloc, OPT_Wpedantic,
+ "ISO C restricts enumerator values to range of %<int%>");
/* The ISO C Standard mandates enumerators to have type int, even
though the underlying type of an enum type is unspecified.
@@ -2720,8 +2720,14 @@ c_parser_enum_specifier (c_parser *parser)
if (c_parser_next_token_is (parser, CPP_EQ))
{
c_parser_consume_token (parser);
- value_loc = c_parser_peek_token (parser)->location;
- enum_value = c_parser_expr_no_commas (parser, NULL).value;
+ c_expr value = c_parser_expr_no_commas (parser, NULL);
+ enum_value = value.value;
+ if (EXPR_HAS_LOCATION (enum_value))
+ value_loc = EXPR_LOCATION (enum_value);
+ else
+ value_loc
+ = make_location (value.get_start (), value.get_start (),
+ value.get_finish ());
}
else
enum_value = NULL_TREE;
@@ -5792,7 +5792,7 @@ extern void xref_basetypes (tree, tree);
extern tree start_enum (tree, tree, tree, tree, bool, bool *);
extern void finish_enum_value_list (tree);
extern void finish_enum (tree);
-extern void build_enumerator (tree, tree, tree, tree, location_t);
+extern void build_enumerator (tree, tree, tree, tree, location_t, location_t);
extern tree lookup_enumerator (tree, tree);
extern bool start_preparsed_function (tree, tree, int);
extern bool start_function (cp_decl_specifier_seq *,
@@ -13542,7 +13542,7 @@ finish_enum (tree enumtype)
void
build_enumerator (tree name, tree value, tree enumtype, tree attributes,
- location_t loc)
+ location_t loc, location_t value_loc)
{
tree decl;
tree context;
@@ -13590,8 +13590,13 @@ build_enumerator (tree name, tree value, tree enumtype, tree attributes,
if (TREE_CODE (value) != INTEGER_CST
|| ! INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value)))
{
- error ("enumerator value for %qD is not an integer constant",
- name);
+ rich_location richloc (line_table, loc);
+ if (value_loc)
+ richloc.add_range (value_loc, false);
+ error_at_rich_loc
+ (&richloc,
+ "enumerator value for %qD is not an integer constant",
+ name);
value = NULL_TREE;
}
}
@@ -17398,6 +17398,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
tree identifier;
tree value;
location_t loc;
+ location_t value_loc = UNKNOWN_LOCATION;
/* Save the input location because we are interested in the location
of the identifier and not the location of the explicit value. */
@@ -17417,7 +17418,9 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
/* Consume the `=' token. */
cp_lexer_consume_token (parser->lexer);
/* Parse the value. */
- value = cp_parser_constant_expression (parser);
+ cp_expr value_expr = cp_parser_constant_expression (parser);
+ value = value_expr;
+ value_loc = value_expr.get_location ();
}
else
value = NULL_TREE;
@@ -17428,7 +17431,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
value = error_mark_node;
/* Create the enumerator. */
- build_enumerator (identifier, value, type, attrs, loc);
+ build_enumerator (identifier, value, type, attrs, loc, value_loc);
}
/* Parse a namespace-name.
@@ -22373,7 +22373,8 @@ tsubst_enum (tree tag, tree newtag, tree args)
/* Actually build the enumerator itself. Here we're assuming that
enumerators can't have dependent attributes. */
build_enumerator (DECL_NAME (decl), value, newtag,
- DECL_ATTRIBUTES (decl), DECL_SOURCE_LOCATION (decl));
+ DECL_ATTRIBUTES (decl), DECL_SOURCE_LOCATION (decl),
+ EXPR_LOCATION (value));
}
if (SCOPED_ENUM_P (newtag))
@@ -76,6 +76,8 @@ extern void fatal_error (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3)
/* Pass one of the OPT_W* from options.h as the second parameter. */
extern bool pedwarn (location_t, int, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
+extern bool pedwarn_at_rich_loc (rich_location *, int, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
extern bool permerror (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
extern bool permerror_at_rich_loc (rich_location *, const char *,
...) ATTRIBUTE_GCC_DIAG(2,3);
@@ -1089,6 +1089,18 @@ pedwarn (location_t location, int opt, const char *gmsgid, ...)
return ret;
}
+/* Same as "pedwarn", but at RICHLOC. */
+
+bool
+pedwarn_at_rich_loc (rich_location *richloc, int opt, const char *gmsgid, ...)
+{
+ va_list ap;
+ va_start (ap, gmsgid);
+ bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_PEDWARN);
+ va_end (ap);
+ return ret;
+}
+
/* A "permissive" error at LOCATION: issues an error unless
-fpermissive was given on the command line, in which case it issues
a warning. Use this for things that really should be errors but we
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-options "-fdiagnostics-show-caret" } */
+void test (void)
+{
+ enum { c1 = "not int", /* { dg-error "10: enumerator value for .c1. is not an integer constant" } */
+/* { dg-begin-multiline-output "" }
+ enum { c1 = "not int",
+ ^~ ~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ c_end };
+}
@@ -22,7 +22,7 @@ enum e {
E5 = 0 * -INT_MIN, /* { dg-warning "12:integer overflow in expression" } */
/* { dg-error "3:overflow in constant expression" "constant" { target *-*-* } 22 } */
E6 = 0 * !-INT_MIN, /* { dg-warning "13:integer overflow in expression" } */
- /* { dg-error "8:not an integer constant" "constant" { target *-*-* } 24 } */
+ /* { dg-error "3:not an integer constant" "constant" { target *-*-* } 24 } */
E7 = INT_MIN % -1 /* { dg-warning "16:integer overflow in expression" } */
/* { dg-error "1:overflow in constant expression" "constant" { target *-*-* } 28 } */
};
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-options "-pedantic -fdiagnostics-show-caret" } */
+void test (void)
+{
+ enum { c1 = -3000000000, /* { dg-warning "10: ISO C restricts enumerator values to range of .int." } */
+/* { dg-begin-multiline-output "" }
+ enum { c1 = -3000000000,
+ ^~ ~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ c2 = "not int", /* { dg-error "11: enumerator value for .c2. is not an integer constant" } */
+/* { dg-begin-multiline-output "" }
+ c2 = "not int",
+ ^~ ~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ c_end };
+}
new file mode 100644
@@ -0,0 +1,19 @@
+/* { dg-options "-pedantic -fdiagnostics-show-caret" } */
+
+#include <limits.h>
+
+void test (void)
+{
+ enum { e1 = LLONG_MIN }; /* { dg-warning "ISO C restricts enumerator values to range of .int." } */
+/* { dg-begin-multiline-output "" }
+ enum { e1 = LLONG_MIN };
+ ^~
+ { dg-end-multiline-output "" } */
+
+ enum { e2 = +LLONG_MIN }; /* { dg-warning "ISO C restricts enumerator values to range of .int." } */
+/* { dg-begin-multiline-output "" }
+ enum { e2 = +LLONG_MIN };
+ ^~
+ { dg-end-multiline-output "" } */
+
+}