aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog29
-rw-r--r--gcc/c-decl.c127
-rw-r--r--gcc/c-family/ChangeLog7
-rw-r--r--gcc/c-family/c-lex.c4
-rw-r--r--gcc/c-parser.c22
-rw-r--r--gcc/c-tree.h54
-rw-r--r--gcc/cp/ChangeLog34
-rw-r--r--gcc/cp/cp-tree.h21
-rw-r--r--gcc/cp/decl.c80
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/parser.c261
-rw-r--r--gcc/testsuite/ChangeLog20
-rw-r--r--gcc/testsuite/g++.dg/cpp/syshdr3.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp/syshdr3.h7
-rw-r--r--gcc/testsuite/g++.dg/system-binary-constants-1.C18
-rw-r--r--gcc/testsuite/g++.dg/system-binary-constants-1.h3
-rw-r--r--gcc/testsuite/gcc.dg/binary-constants-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/binary-constants-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pr7263-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/syshdr3.c16
-rw-r--r--gcc/testsuite/gcc.dg/cpp/syshdr3.h7
-rw-r--r--gcc/testsuite/gcc.dg/cpp/sysmac1.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/sysmac2.c2
-rw-r--r--gcc/testsuite/gcc.dg/nofixed-point-2.c6
-rw-r--r--gcc/testsuite/gcc.dg/system-binary-constants-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/system-binary-constants-1.h3
26 files changed, 558 insertions, 207 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2d2260f..9a0d816 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,32 @@
+2012-05-16 Dodji Seketeli <dodji@redhat.com>
+
+ PR preprocessor/7263
+ * c-tree.h (enum c_declspec_word): Declare new enum.
+ (struct c_declspecs::locations): New member.
+ (declspecs_add_qual, declspecs_add_scspec)
+ (declspecs_add_addrspace, declspecs_add_alignas): Take a new
+ location parameter.
+ * c-decl.c (build_null_declspecs): Initialize the new struct
+ c_declspecs::locations member.
+ (declspecs_add_addrspace): Take a location parameter for the
+ address space. Store it onto declaration specifiers.
+ (declspecs_add_qual): Likewise, take a location parameter for the
+ qualifier.
+ (declspecs_add_type): Likewise, take a location parameter for the
+ type specifier.
+ (declspecs_add_scspec): Likewise, take a location parameter for
+ the storage class specifier.
+ (declspecs_add_attrs): Likewise, take a location parameter for the
+ first attribute.
+ (declspecs_add_alignas): Likewise, take a location parameter for
+ the alignas token.
+ (finish_declspecs): For diagnostics, use the location of the
+ relevant declspec, instead of the global input_location.
+ * c-parser.c (c_parser_parameter_declaration): Pass the precise
+ virtual location of the declspec to the declspecs-setters.
+ (c_parser_declspecs): Likewise. Avoid calling c_parser_peek_token
+ repeatedly.
+
2012-05-16 Igor Zamyatin <igor.zamyatin@intel.com>
* configure.ac: Stack protector enabling for Android targets.
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 3153cf4..41688a7 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -8787,6 +8787,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;
@@ -8824,7 +8825,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;
@@ -8835,7 +8837,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;
}
@@ -8843,7 +8848,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;
@@ -8857,20 +8863,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;
}
@@ -8923,6 +8932,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)
@@ -8962,7 +8972,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;
@@ -9007,7 +9020,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;
@@ -9044,7 +9060,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;
@@ -9081,11 +9100,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)
@@ -9121,7 +9143,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;
@@ -9174,7 +9199,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 ();
@@ -9220,7 +9248,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)
@@ -9248,7 +9279,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)
@@ -9276,7 +9310,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)
@@ -9292,7 +9329,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)
@@ -9300,7 +9340,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)
@@ -9324,7 +9367,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)
@@ -9348,7 +9394,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:
@@ -9402,6 +9451,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,
@@ -9427,6 +9477,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,
@@ -9460,6 +9511,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. */
@@ -9483,13 +9535,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)
@@ -9510,7 +9566,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;
@@ -9531,11 +9589,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;
@@ -9546,7 +9606,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;
@@ -9585,6 +9648,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);
@@ -9599,9 +9663,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;
}
@@ -9610,10 +9675,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);
@@ -9654,9 +9721,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
@@ -9667,7 +9736,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%>");
}
@@ -9712,7 +9781,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);
}
@@ -9725,7 +9794,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);
}
@@ -9751,7 +9820,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);
}
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index da28510..0229a92 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,10 @@
+2012-05-16 Dodji Seketeli <dodji@redhat.com>
+
+ PR preprocessor/7263
+ * c-lex.c (c_lex_with_flags): Pass a virtual location to the call
+ to cpp_classify_number. For diagnostics, use the precise location
+ instead of the global input_location.
+
2012-05-15 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/11856
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 2a605f6..b122dab 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -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;
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 47908f1..33420ca 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -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);
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 468cfe4..8f8c9d8e 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -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 */
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b0cfbe6..9913002 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,37 @@
+2012-05-16 Dodji Seketeli <dodji@redhat.com>
+
+ PR preprocessor/7263
+ * cp-tree.h (enum cp_decl_spec): Add new enumerators to cover all
+ the possible declarator specifiers so far.
+ (struct cp_decl_specifier_seq::locations): Declare new member.
+ (cp_decl_specifier_seq::{specs, type_location}): Remove.
+ (decl_spec_seq_has_spec_p): Declare new function.
+ * parser.c (cp_parser_check_decl_spec): Remove.
+ (set_and_check_decl_spec_loc): Define new static function.
+ (decl_spec_seq_has_spec_p): Define new public function.
+ (cp_parser_decl_specifier_seq, cp_parser_function_specifier_opt)
+ (cp_parser_type_specifier, cp_parser_simple_type_specifier)
+ (cp_parser_set_storage_class, cp_parser_set_decl_spec_type)
+ (cp_parser_alias_declaration): Set the locations for each
+ declspec, using set_and_check_decl_spec_loc.
+ (cp_parser_explicit_instantiation, cp_parser_init_declarator)
+ (cp_parser_member_declaration, cp_parser_init_declarator): Use the
+ new declspec location for specifiers. Use the new
+ decl_spec_seq_has_spec_p.
+ (cp_parser_type_specifier_seq): Use the new
+ set_and_check_decl_spec_loc. Stop using
+ cp_parser_check_decl_spec. Use the new decl_spec_seq_has_spec_p.
+ (, cp_parser_init_declarator): Use the new
+ set_and_check_decl_spec_loc.
+ (cp_parser_single_declaration, cp_parser_friend_p)
+ (cp_parser_objc_class_ivars, cp_parser_objc_struct_declaration):
+ Use the new decl_spec_seq_has_spec_p.
+ * decl.c (check_tag_decl): Use new decl_spec_seq_has_spec_p. Use
+ the more precise ds_redefined_builtin_type_spec location for
+ diagnostics about re-declaring C++ built-in types.
+ (start_decl, grokvardecl, grokdeclarator): Use the new
+ decl_spec_seq_has_spec_p.
+
2012-05-15 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/11856
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e5ec1d4..8eaf766 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4647,7 +4647,9 @@ typedef enum cp_storage_class {
sc_mutable
} cp_storage_class;
-/* An individual decl-specifier. */
+/* An individual decl-specifier. This is used to index the array of
+ locations for the declspecs in struct cp_decl_specifier_seq
+ below. */
typedef enum cp_decl_spec {
ds_first,
@@ -4667,17 +4669,20 @@ typedef enum cp_decl_spec {
ds_constexpr,
ds_complex,
ds_thread,
- ds_last
+ ds_type_spec,
+ ds_redefined_builtin_type_spec,
+ ds_attribute,
+ ds_storage_class,
+ ds_long_long,
+ ds_last /* This enumerator must always be the last one. */
} cp_decl_spec;
/* A decl-specifier-seq. */
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[ds_last];
/* 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
@@ -4827,6 +4832,8 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
bool in_system_header_p;
};
+bool decl_spec_seq_has_spec_p (const cp_decl_specifier_seq *, cp_decl_spec);
+
/* Return the type of the `this' parameter of FNTYPE. */
static inline tree
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8d7d745..fa9fcc8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4129,8 +4129,8 @@ fixup_anonymous_aggr (tree t)
tree
check_tag_decl (cp_decl_specifier_seq *declspecs)
{
- int saw_friend = declspecs->specs[(int)ds_friend] != 0;
- int saw_typedef = declspecs->specs[(int)ds_typedef] != 0;
+ int saw_friend = decl_spec_seq_has_spec_p (declspecs, ds_friend);
+ int saw_typedef = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
/* If a class, struct, or enum type is declared by the DECLSPECS
(i.e, if a class-specifier, enum-specifier, or non-typename
elaborated-type-specifier appears in the DECLSPECS),
@@ -4143,7 +4143,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
else if (declspecs->redefined_builtin_type)
{
if (!in_system_header)
- permerror (input_location, "redeclaration of C++ built-in type %qT",
+ permerror (declspecs->locations[ds_redefined_builtin_type_spec],
+ "redeclaration of C++ built-in type %qT",
declspecs->redefined_builtin_type);
return NULL_TREE;
}
@@ -4198,29 +4199,29 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
else
{
- if (declspecs->specs[(int)ds_inline]
- || declspecs->specs[(int)ds_virtual])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_inline)
+ || decl_spec_seq_has_spec_p (declspecs, ds_virtual))
error ("%qs can only be specified for functions",
- declspecs->specs[(int)ds_inline]
+ decl_spec_seq_has_spec_p (declspecs, ds_inline)
? "inline" : "virtual");
else if (saw_friend
&& (!current_class_type
|| current_scope () != current_class_type))
error ("%<friend%> can only be specified inside a class");
- else if (declspecs->specs[(int)ds_explicit])
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_explicit))
error ("%<explicit%> can only be specified for constructors");
else if (declspecs->storage_class)
error ("a storage class can only be specified for objects "
"and functions");
- else if (declspecs->specs[(int)ds_const]
- || declspecs->specs[(int)ds_volatile]
- || declspecs->specs[(int)ds_restrict]
- || declspecs->specs[(int)ds_thread])
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_const)
+ || decl_spec_seq_has_spec_p (declspecs, ds_volatile)
+ || decl_spec_seq_has_spec_p (declspecs, ds_restrict)
+ || decl_spec_seq_has_spec_p (declspecs, ds_thread))
error ("qualifiers can only be specified for objects "
"and functions");
else if (saw_typedef)
warning (0, "%<typedef%> was ignored in this declaration");
- else if (declspecs->specs[(int) ds_constexpr])
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_constexpr))
error ("%<constexpr%> cannot be used for type declarations");
}
@@ -4472,7 +4473,7 @@ start_decl (const cp_declarator *declarator,
error ("duplicate initialization of %qD", decl);
if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
decl = field;
- if (declspecs->specs[(int) ds_constexpr]
+ if (decl_spec_seq_has_spec_p (declspecs, ds_constexpr)
&& !DECL_DECLARED_CONSTEXPR_P (field))
error ("%qD declared %<constexpr%> outside its class", field);
}
@@ -7682,7 +7683,7 @@ grokvardecl (tree type,
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
- if (declspecs->specs[(int)ds_thread])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_thread))
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
/* If the type of the decl has no linkage, make sure that we'll
@@ -8436,16 +8437,16 @@ grokdeclarator (const cp_declarator *declarator,
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
bool template_type_arg = false;
bool template_parm_flag = false;
- bool constexpr_p = declspecs->specs[(int) ds_constexpr];
+ bool constexpr_p = decl_spec_seq_has_spec_p (declspecs, ds_constexpr);
const char *errmsg;
- signed_p = declspecs->specs[(int)ds_signed];
- unsigned_p = declspecs->specs[(int)ds_unsigned];
- short_p = declspecs->specs[(int)ds_short];
- long_p = declspecs->specs[(int)ds_long];
- longlong = declspecs->specs[(int)ds_long] >= 2;
+ signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
+ unsigned_p = decl_spec_seq_has_spec_p (declspecs, ds_unsigned);
+ short_p = decl_spec_seq_has_spec_p (declspecs, ds_short);
+ long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
+ longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
explicit_int128 = declspecs->explicit_int128_p;
- thread_p = declspecs->specs[(int)ds_thread];
+ thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
if (decl_context == FUNCDEF)
funcdef_flag = true, decl_context = NORMAL;
@@ -8646,7 +8647,7 @@ grokdeclarator (const cp_declarator *declarator,
if (dname && IDENTIFIER_OPNAME_P (dname))
{
- if (declspecs->specs[(int)ds_typedef])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_typedef))
{
error ("declaration of %qD as %<typedef%>", dname);
return error_mark_node;
@@ -8684,7 +8685,7 @@ grokdeclarator (const cp_declarator *declarator,
if (name == NULL)
name = decl_context == PARM ? "parameter" : "type name";
- if (constexpr_p && declspecs->specs[(int)ds_typedef])
+ if (constexpr_p && decl_spec_seq_has_spec_p (declspecs, ds_typedef))
{
error ("%<constexpr%> cannot appear in a typedef declaration");
return error_mark_node;
@@ -8910,7 +8911,7 @@ grokdeclarator (const cp_declarator *declarator,
else if (short_p)
type = short_integer_type_node;
- if (declspecs->specs[(int)ds_complex])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_complex))
{
if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
error ("complex invalid for %qs", name);
@@ -8934,11 +8935,11 @@ grokdeclarator (const cp_declarator *declarator,
}
type_quals = TYPE_UNQUALIFIED;
- if (declspecs->specs[(int)ds_const])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_const))
type_quals |= TYPE_QUAL_CONST;
- if (declspecs->specs[(int)ds_volatile])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
type_quals |= TYPE_QUAL_VOLATILE;
- if (declspecs->specs[(int)ds_restrict])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
type_quals |= TYPE_QUAL_RESTRICT;
if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
error ("qualifiers are not allowed on declaration of %<operator %T%>",
@@ -8963,9 +8964,9 @@ grokdeclarator (const cp_declarator *declarator,
type_quals = cp_type_quals (type);
staticp = 0;
- inlinep = !! declspecs->specs[(int)ds_inline];
- virtualp = !! declspecs->specs[(int)ds_virtual];
- explicitp = !! declspecs->specs[(int)ds_explicit];
+ inlinep = decl_spec_seq_has_spec_p (declspecs, ds_inline);
+ virtualp = decl_spec_seq_has_spec_p (declspecs, ds_virtual);
+ explicitp = decl_spec_seq_has_spec_p (declspecs, ds_explicit);
storage_class = declspecs->storage_class;
if (storage_class == sc_static)
@@ -8977,7 +8978,7 @@ grokdeclarator (const cp_declarator *declarator,
storage_class = sc_none;
staticp = 0;
}
- friendp = !! declspecs->specs[(int)ds_friend];
+ friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
if (dependent_name && !friendp)
{
@@ -8988,7 +8989,7 @@ grokdeclarator (const cp_declarator *declarator,
/* Issue errors about use of storage classes for parameters. */
if (decl_context == PARM)
{
- if (declspecs->specs[(int)ds_typedef])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_typedef))
{
error ("typedef declaration invalid in parameter declaration");
return error_mark_node;
@@ -9032,7 +9033,7 @@ grokdeclarator (const cp_declarator *declarator,
&& ((storage_class
&& storage_class != sc_extern
&& storage_class != sc_static)
- || declspecs->specs[(int)ds_typedef]))
+ || decl_spec_seq_has_spec_p (declspecs, ds_typedef)))
{
error ("multiple storage classes in declaration of %qs", name);
thread_p = false;
@@ -9046,7 +9047,7 @@ grokdeclarator (const cp_declarator *declarator,
&& (storage_class == sc_register
|| storage_class == sc_auto))
;
- else if (declspecs->specs[(int)ds_typedef])
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_typedef))
;
else if (decl_context == FIELD
/* C++ allows static class elements. */
@@ -9640,7 +9641,7 @@ grokdeclarator (const cp_declarator *declarator,
return error_mark_node;
}
}
- else if (declspecs->specs[(int)ds_typedef]
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)
&& current_class_type)
{
error ("cannot declare member %<%T::%s%> within %qT",
@@ -9711,7 +9712,8 @@ grokdeclarator (const cp_declarator *declarator,
error ("non-member %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
- else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
+ else if (decl_context == TYPENAME
+ || decl_spec_seq_has_spec_p (declspecs, ds_typedef))
{
error ("non-object member %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
@@ -9741,7 +9743,7 @@ grokdeclarator (const cp_declarator *declarator,
}
/* If this is declaring a typedef name, return a TYPE_DECL. */
- if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME)
+ if (decl_spec_seq_has_spec_p (declspecs, ds_typedef) && decl_context != TYPENAME)
{
tree decl;
@@ -9853,7 +9855,7 @@ grokdeclarator (const cp_declarator *declarator,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
- if (declspecs->specs[(int)ds_alias])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_alias))
/* Acknowledge that this was written:
`using analias = atype;'. */
TYPE_DECL_ALIAS_P (decl) = 1;
@@ -10352,7 +10354,7 @@ grokdeclarator (const cp_declarator *declarator,
and `extern' makes no difference. */
if (! toplevel_bindings_p ()
&& (storage_class == sc_static
- || declspecs->specs[(int)ds_inline])
+ || decl_spec_seq_has_spec_p (declspecs, ds_inline))
&& pedantic)
{
if (storage_class == sc_static)
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index b0544bb..aa2324e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -864,7 +864,7 @@ grokfield (const cp_declarator *declarator,
cplus_decl_attributes (&value, attrlist, attrflags);
}
- if (declspecs->specs[(int)ds_typedef]
+ if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)
&& TREE_TYPE (value) != error_mark_node
&& TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
set_underlying_type (value);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index dc64fa1..2dc8f56 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2223,6 +2223,9 @@ static void cp_parser_set_storage_class
(cp_parser *, cp_decl_specifier_seq *, enum rid, location_t);
static void cp_parser_set_decl_spec_type
(cp_decl_specifier_seq *, tree, location_t, bool);
+static void set_and_check_decl_spec_loc
+ (cp_decl_specifier_seq *decl_specs,
+ cp_decl_spec ds, source_location location);
static bool cp_parser_friend_p
(const cp_decl_specifier_seq *);
static void cp_parser_required_error
@@ -2494,53 +2497,6 @@ cp_parser_simulate_error (cp_parser* parser)
return false;
}
-/* Check for repeated decl-specifiers. */
-
-static void
-cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
- location_t location)
-{
- int ds;
-
- for (ds = ds_first; ds != ds_last; ++ds)
- {
- unsigned count = decl_specs->specs[ds];
- if (count < 2)
- continue;
- /* The "long" specifier is a special case because of "long long". */
- if (ds == ds_long)
- {
- if (count > 2)
- error_at (location, "%<long long long%> is too long for GCC");
- else
- pedwarn_cxx98 (location, OPT_Wlong_long,
- "ISO C++ 1998 does not support %<long long%>");
- }
- else if (count > 1)
- {
- static const char *const decl_spec_names[] = {
- "signed",
- "unsigned",
- "short",
- "long",
- "const",
- "volatile",
- "restrict",
- "inline",
- "virtual",
- "explicit",
- "friend",
- "typedef",
- "using",
- "constexpr",
- "__complex",
- "__thread"
- };
- error_at (location, "duplicate %qs", decl_spec_names[ds]);
- }
- }
-}
-
/* This function is called when a type is defined. If type
definitions are forbidden at this point, an error message is
issued. */
@@ -10555,6 +10511,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
{
bool constructor_possible_p = !parser->in_declarator_p;
cp_token *start_token = NULL;
+ cp_decl_spec ds;
/* Clear DECL_SPECS. */
clear_decl_specs (decl_specs);
@@ -10568,6 +10525,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
bool constructor_p;
bool found_decl_spec;
cp_token *token;
+ ds = ds_last;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
@@ -10583,6 +10541,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[ds_attribute] == 0)
+ decl_specs->locations[ds_attribute] = token->location;
continue;
}
/* Assume we will find a decl-specifier keyword. */
@@ -10602,14 +10562,14 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
}
else
{
- ++decl_specs->specs[(int) ds_friend];
+ ds = ds_friend;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
}
break;
case RID_CONSTEXPR:
- ++decl_specs->specs[(int) ds_constexpr];
+ ds = ds_constexpr;
cp_lexer_consume_token (parser->lexer);
break;
@@ -10626,7 +10586,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
/* decl-specifier:
typedef */
case RID_TYPEDEF:
- ++decl_specs->specs[(int) ds_typedef];
+ ds = ds_typedef;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
/* A constructor declarator cannot appear in a typedef. */
@@ -10679,8 +10639,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
break;
case RID_THREAD:
/* Consume the token. */
+ ds = ds_thread;
cp_lexer_consume_token (parser->lexer);
- ++decl_specs->specs[(int) ds_thread];
break;
default:
@@ -10694,13 +10654,16 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
&& token->keyword != RID_CONSTEXPR)
error ("decl-specifier invalid in condition");
+ if (ds != ds_last)
+ set_and_check_decl_spec_loc (decl_specs, ds, token->location);
+
/* Constructors are a special case. The `S' in `S()' is not a
decl-specifier; it is the beginning of the declarator. */
constructor_p
= (!found_decl_spec
&& constructor_possible_p
&& (cp_parser_constructor_declarator_p
- (parser, decl_specs->specs[(int) ds_friend] != 0)));
+ (parser, decl_spec_seq_has_spec_p (decl_specs, ds_friend))));
/* If we don't have a DECL_SPEC yet, then we must be looking at
a type-specifier. */
@@ -10777,12 +10740,10 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
flags |= CP_PARSER_FLAGS_OPTIONAL;
}
- cp_parser_check_decl_spec (decl_specs, start_token->location);
-
/* Don't allow a friend specifier with a class definition. */
- if (decl_specs->specs[(int) ds_friend] != 0
+ if (decl_spec_seq_has_spec_p (decl_specs, ds_friend)
&& (*declares_class_or_enum & 2))
- error_at (start_token->location,
+ error_at (decl_specs->locations[ds_friend],
"class definition may not be declared a friend");
}
@@ -10843,8 +10804,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
switch (token->keyword)
{
case RID_INLINE:
- if (decl_specs)
- ++decl_specs->specs[(int) ds_inline];
+ set_and_check_decl_spec_loc (decl_specs, ds_inline, token->location);
break;
case RID_VIRTUAL:
@@ -10853,13 +10813,11 @@ cp_parser_function_specifier_opt (cp_parser* parser,
A member function template shall not be virtual. */
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];
+ set_and_check_decl_spec_loc (decl_specs, ds_virtual, token->location);
break;
case RID_EXPLICIT:
- if (decl_specs)
- ++decl_specs->specs[(int) ds_explicit];
+ set_and_check_decl_spec_loc (decl_specs, ds_explicit, token->location);
break;
default:
@@ -13170,14 +13128,16 @@ 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[ds_type_spec]);
if (declarator != cp_error_declarator)
{
- if (decl_specifiers.specs[(int)ds_inline])
- permerror (input_location, "explicit instantiation shall not use"
+ if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_inline))
+ permerror (decl_specifiers.locations[ds_inline],
+ "explicit instantiation shall not use"
" %<inline%> specifier");
- if (decl_specifiers.specs[(int)ds_constexpr])
- permerror (input_location, "explicit instantiation shall not use"
+ if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_constexpr))
+ permerror (decl_specifiers.locations[ds_constexpr],
+ "explicit instantiation shall not use"
" %<constexpr%> specifier");
decl = grokdeclarator (declarator, &decl_specifiers,
@@ -13399,7 +13359,7 @@ cp_parser_type_specifier (cp_parser* parser,
type_spec
= (cp_parser_elaborated_type_specifier
(parser,
- decl_specs && decl_specs->specs[(int) ds_friend],
+ decl_spec_seq_has_spec_p (decl_specs, ds_friend),
is_declaration));
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs,
@@ -13440,7 +13400,7 @@ cp_parser_type_specifier (cp_parser* parser,
{
if (decl_specs)
{
- ++decl_specs->specs[(int)ds];
+ set_and_check_decl_spec_loc (decl_specs, ds, token->location);
decl_specs->any_specifiers_p = true;
}
return cp_lexer_consume_token (parser->lexer)->u.value;
@@ -13531,8 +13491,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
type = boolean_type_node;
break;
case RID_SHORT:
- if (decl_specs)
- ++decl_specs->specs[(int) ds_short];
+ set_and_check_decl_spec_loc (decl_specs, ds_short, token->location);
type = short_integer_type_node;
break;
case RID_INT:
@@ -13549,17 +13508,15 @@ cp_parser_simple_type_specifier (cp_parser* parser,
break;
case RID_LONG:
if (decl_specs)
- ++decl_specs->specs[(int) ds_long];
+ set_and_check_decl_spec_loc (decl_specs, ds_long, token->location);
type = long_integer_type_node;
break;
case RID_SIGNED:
- if (decl_specs)
- ++decl_specs->specs[(int) ds_signed];
+ set_and_check_decl_spec_loc (decl_specs, ds_signed, token->location);
type = integer_type_node;
break;
case RID_UNSIGNED:
- if (decl_specs)
- ++decl_specs->specs[(int) ds_unsigned];
+ set_and_check_decl_spec_loc (decl_specs, ds_unsigned, token->location);
type = unsigned_type_node;
break;
case RID_FLOAT:
@@ -15070,19 +15027,21 @@ static tree
cp_parser_alias_declaration (cp_parser* parser)
{
tree id, type, decl, pushed_scope = NULL_TREE, attributes;
- location_t id_location;
+ location_t id_location, using_location, attrs_location = 0;
cp_declarator *declarator;
cp_decl_specifier_seq decl_specs;
bool member_p;
const char *saved_message = NULL;
/* Look for the `using' keyword. */
+ using_location = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_require_keyword (parser, RID_USING, RT_USING);
id_location = cp_lexer_peek_token (parser->lexer)->location;
id = cp_parser_identifier (parser);
if (id == error_mark_node)
return error_mark_node;
+ attrs_location = cp_lexer_peek_token (parser->lexer)->location;
attributes = cp_parser_attributes_opt (parser);
if (attributes == error_mark_node)
return error_mark_node;
@@ -15131,9 +15090,19 @@ cp_parser_alias_declaration (cp_parser* parser)
clear_decl_specs (&decl_specs);
decl_specs.type = type;
- decl_specs.attributes = attributes;
- ++decl_specs.specs[(int) ds_typedef];
- ++decl_specs.specs[(int) ds_alias];
+ if (attributes != NULL_TREE)
+ {
+ decl_specs.attributes = attributes;
+ set_and_check_decl_spec_loc (&decl_specs,
+ ds_attribute,
+ attrs_location);
+ }
+ set_and_check_decl_spec_loc (&decl_specs,
+ ds_typedef,
+ using_location);
+ set_and_check_decl_spec_loc (&decl_specs,
+ ds_alias,
+ using_location);
declarator = make_id_declarator (NULL_TREE, id, sfk_none);
declarator->id_loc = id_location;
@@ -15515,7 +15484,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[ds_type_spec]);
/* Figure out what scope the entity declared by the DECLARATOR is
located in. `grokdeclarator' sometimes changes the scope, so
@@ -16936,8 +16905,6 @@ cp_parser_type_specifier_seq (cp_parser* parser,
if (is_declaration && !is_cv_qualifier)
flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
}
-
- cp_parser_check_decl_spec (type_specifier_seq, start_token->location);
}
/* Parse a parameter-declaration-clause.
@@ -19042,7 +19009,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[ds_type_spec]);
/* Look for an asm-specification. */
asm_specification = cp_parser_asm_specification_opt (parser);
@@ -21301,7 +21268,7 @@ cp_parser_single_declaration (cp_parser* parser,
*friend_p = cp_parser_friend_p (&decl_specifiers);
/* There are no template typedefs. */
- if (decl_specifiers.specs[(int) ds_typedef])
+ if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef))
{
error_at (decl_spec_token_start->location,
"template declaration of %<typedef%>");
@@ -22049,10 +22016,11 @@ cp_parser_set_storage_class (cp_parser *parser,
}
if ((keyword == RID_EXTERN || keyword == RID_STATIC)
- && decl_specs->specs[(int) ds_thread])
+ && decl_spec_seq_has_spec_p (decl_specs, ds_thread))
{
- error_at (location, "%<__thread%> before %qD", ridpointers[keyword]);
- decl_specs->specs[(int) ds_thread] = 0;
+ error_at (decl_specs->locations[ds_thread],
+ "%<__thread%> before %qD", ridpointers[keyword]);
+ decl_specs->locations[ds_thread] = 0;
}
switch (keyword)
@@ -22076,12 +22044,13 @@ cp_parser_set_storage_class (cp_parser *parser,
gcc_unreachable ();
}
decl_specs->storage_class = storage_class;
+ set_and_check_decl_spec_loc (decl_specs, ds_storage_class, location);
/* A storage class specifier cannot be applied alongside a typedef
specifier. If there is a typedef specifier present then set
conflicting_specifiers_p which will trigger an error later
on in grokdeclarator. */
- if (decl_specs->specs[(int)ds_typedef])
+ if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef))
decl_specs->conflicting_specifiers_p = true;
}
@@ -22101,24 +22070,27 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
this is what happened. In system headers, we ignore these
declarations so that G++ can work with system headers that are not
C++-safe. */
- if (decl_specs->specs[(int) ds_typedef]
+ if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef)
&& !type_definition_p
&& (type_spec == boolean_type_node
|| type_spec == char16_type_node
|| type_spec == char32_type_node
|| type_spec == wchar_type_node)
&& (decl_specs->type
- || decl_specs->specs[(int) ds_long]
- || decl_specs->specs[(int) ds_short]
- || decl_specs->specs[(int) ds_unsigned]
- || decl_specs->specs[(int) ds_signed]))
+ || decl_spec_seq_has_spec_p (decl_specs, ds_long)
+ || decl_spec_seq_has_spec_p (decl_specs, ds_short)
+ || decl_spec_seq_has_spec_p (decl_specs, ds_unsigned)
+ || decl_spec_seq_has_spec_p (decl_specs, ds_signed)))
{
decl_specs->redefined_builtin_type = type_spec;
+ set_and_check_decl_spec_loc (decl_specs,
+ ds_redefined_builtin_type_spec,
+ location);
if (!decl_specs->type)
{
decl_specs->type = type_spec;
decl_specs->type_definition_p = false;
- decl_specs->type_location = location;
+ set_and_check_decl_spec_loc (decl_specs,ds_type_spec, location);
}
}
else if (decl_specs->type)
@@ -22128,17 +22100,96 @@ 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;
+ set_and_check_decl_spec_loc (decl_specs, ds_type_spec, location);
+ }
+}
+
+/* Set the location for a declarator specifier and check if it is
+ duplicated.
+
+ DECL_SPECS is the sequence of declarator specifiers onto which to
+ set the location.
+
+ DS is the single declarator specifier to set which location is to
+ be set onto the existing sequence of declarators.
+
+ LOCATION is the location for the declarator specifier to
+ consider. */
+
+static void
+set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
+ cp_decl_spec ds, source_location location)
+{
+ gcc_assert (ds < ds_last);
+
+ if (decl_specs == NULL)
+ return;
+
+ if (decl_specs->locations[ds] == 0)
+ decl_specs->locations[ds] = location;
+ else
+ {
+ if (ds == ds_long)
+ {
+ if (decl_specs->locations[ds_long_long] != 0)
+ error_at (location,
+ "%<long long long%> is too long for GCC");
+ else
+ {
+ decl_specs->locations[ds_long_long] = location;
+ pedwarn_cxx98 (location,
+ OPT_Wlong_long,
+ "ISO C++ 1998 does not support %<long long%>");
+ }
+ }
+ else
+ {
+ static const char *const decl_spec_names[] = {
+ "signed",
+ "unsigned",
+ "short",
+ "long",
+ "const",
+ "volatile",
+ "restrict",
+ "inline",
+ "virtual",
+ "explicit",
+ "friend",
+ "typedef",
+ "using",
+ "constexpr",
+ "__complex",
+ "__thread"
+ };
+ error_at (location,
+ "duplicate %qs", decl_spec_names[ds]);
+ }
}
}
+/* Return true iff the declarator specifier DS is present in the
+ sequence of declarator specifiers DECL_SPECS. */
+
+bool
+decl_spec_seq_has_spec_p (const cp_decl_specifier_seq * decl_specs,
+ cp_decl_spec ds)
+{
+ gcc_assert (ds < ds_last);
+
+ if (decl_specs == NULL)
+ return false;
+
+ return decl_specs->locations[ds] != 0;
+}
+
/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */
static bool
cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers)
{
- return decl_specifiers->specs[(int) ds_friend] != 0;
+ return decl_spec_seq_has_spec_p (decl_specifiers, ds_friend);
}
/* Issue an error message indicating that TOKEN_DESC was expected.
@@ -23951,17 +24002,17 @@ cp_parser_objc_class_ivars (cp_parser* parser)
}
/* __thread. */
- if (declspecs.specs[(int) ds_thread])
+ if (decl_spec_seq_has_spec_p (&declspecs, ds_thread))
{
cp_parser_error (parser, "invalid type for instance variable");
- declspecs.specs[(int) ds_thread] = 0;
+ declspecs.locations[ds_thread] = 0;
}
/* typedef. */
- if (declspecs.specs[(int) ds_typedef])
+ if (decl_spec_seq_has_spec_p (&declspecs, ds_typedef))
{
cp_parser_error (parser, "invalid type for instance variable");
- declspecs.specs[(int) ds_typedef] = 0;
+ declspecs.locations[ds_thread] = 0;
}
prefix_attributes = declspecs.attributes;
@@ -24530,17 +24581,17 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
}
/* __thread. */
- if (declspecs.specs[(int) ds_thread])
+ if (decl_spec_seq_has_spec_p (&declspecs, ds_thread))
{
cp_parser_error (parser, "invalid type for property");
- declspecs.specs[(int) ds_thread] = 0;
+ declspecs.locations[ds_thread] = 0;
}
/* typedef. */
- if (declspecs.specs[(int) ds_typedef])
+ if (decl_spec_seq_has_spec_p (&declspecs, ds_typedef))
{
cp_parser_error (parser, "invalid type for property");
- declspecs.specs[(int) ds_typedef] = 0;
+ declspecs.locations[ds_typedef] = 0;
}
prefix_attributes = declspecs.attributes;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fdf43a9..ac4f287 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,23 @@
+2012-05-16 Dodji Seketeli <dodji@redhat.com>
+
+ PR preprocessor/7263
+ * gcc.dg/binary-constants-2.c: Run without tracking locations
+ accross macro expansion.
+ * gcc.dg/binary-constants-3.c: Likewise.
+ * gcc.dg/cpp/sysmac2.c: Likewise.
+ * testsuite/gcc.dg/nofixed-point-2.c: Adjust for more precise
+ location.
+ * gcc.dg/cpp/syshdr3.c: New test.
+ * gcc.dg/cpp/syshdr3.h: New header for the new test above.
+ * gcc.dg/system-binary-constants-1.c: New test.
+ * gcc.dg/system-binary-constants-1.h: New header for the new test
+ above.
+ * g++.dg/cpp/syshdr3.C: New test.
+ * g++.dg/cpp/syshdr3.h: New header the new test above.
+ * g++.dg/system-binary-constants-1.C: New test.
+ * g++.dg/system-binary-constants-1.h: New header the new test
+ above.
+
2012-05-15 Paolo Carlini <paolo.carlini@oracle.com>
* g++.old-deja/g++.pt/crash10.C: Adjust post PR11586.
diff --git a/gcc/testsuite/g++.dg/cpp/syshdr3.C b/gcc/testsuite/g++.dg/cpp/syshdr3.C
new file mode 100644
index 0000000..3916823
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/syshdr3.C
@@ -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" } */
diff --git a/gcc/testsuite/g++.dg/cpp/syshdr3.h b/gcc/testsuite/g++.dg/cpp/syshdr3.h
new file mode 100644
index 0000000..e5d502a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/syshdr3.h
@@ -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
diff --git a/gcc/testsuite/g++.dg/system-binary-constants-1.C b/gcc/testsuite/g++.dg/system-binary-constants-1.C
new file mode 100644
index 0000000..7ef26f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/system-binary-constants-1.C
@@ -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" } */
+}
diff --git a/gcc/testsuite/g++.dg/system-binary-constants-1.h b/gcc/testsuite/g++.dg/system-binary-constants-1.h
new file mode 100644
index 0000000..85f2917
--- /dev/null
+++ b/gcc/testsuite/g++.dg/system-binary-constants-1.h
@@ -0,0 +1,3 @@
+#pragma GCC system_header
+
+#define BINARY_INT_CONSTANT_IN_SYSTEM_HEADER 0b1101
diff --git a/gcc/testsuite/gcc.dg/binary-constants-2.c b/gcc/testsuite/gcc.dg/binary-constants-2.c
index 40d7636..6c3928a 100644
--- a/gcc/testsuite/gcc.dg/binary-constants-2.c
+++ b/gcc/testsuite/gcc.dg/binary-constants-2.c
@@ -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
diff --git a/gcc/testsuite/gcc.dg/binary-constants-3.c b/gcc/testsuite/gcc.dg/binary-constants-3.c
index 984477d..410fc4c 100644
--- a/gcc/testsuite/gcc.dg/binary-constants-3.c
+++ b/gcc/testsuite/gcc.dg/binary-constants-3.c
@@ -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
diff --git a/gcc/testsuite/gcc.dg/cpp/pr7263-3.c b/gcc/testsuite/gcc.dg/cpp/pr7263-3.c
index efa619a..225b659 100644
--- a/gcc/testsuite/gcc.dg/cpp/pr7263-3.c
+++ b/gcc/testsuite/gcc.dg/cpp/pr7263-3.c
@@ -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." } */
{
diff --git a/gcc/testsuite/gcc.dg/cpp/syshdr3.c b/gcc/testsuite/gcc.dg/cpp/syshdr3.c
new file mode 100644
index 0000000..15749ff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/syshdr3.c
@@ -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" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/syshdr3.h b/gcc/testsuite/gcc.dg/cpp/syshdr3.h
new file mode 100644
index 0000000..e5d502a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/syshdr3.h
@@ -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
diff --git a/gcc/testsuite/gcc.dg/cpp/sysmac1.c b/gcc/testsuite/gcc.dg/cpp/sysmac1.c
index fa741a4..cc8469e 100644
--- a/gcc/testsuite/gcc.dg/cpp/sysmac1.c
+++ b/gcc/testsuite/gcc.dg/cpp/sysmac1.c
@@ -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. */
diff --git a/gcc/testsuite/gcc.dg/cpp/sysmac2.c b/gcc/testsuite/gcc.dg/cpp/sysmac2.c
index 6d493a9..cdba668 100644
--- a/gcc/testsuite/gcc.dg/cpp/sysmac2.c
+++ b/gcc/testsuite/gcc.dg/cpp/sysmac2.c
@@ -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. */
diff --git a/gcc/testsuite/gcc.dg/nofixed-point-2.c b/gcc/testsuite/gcc.dg/nofixed-point-2.c
index 5b2f209..8442a19 100644
--- a/gcc/testsuite/gcc.dg/nofixed-point-2.c
+++ b/gcc/testsuite/gcc.dg/nofixed-point-2.c
@@ -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 } */
diff --git a/gcc/testsuite/gcc.dg/system-binary-constants-1.c b/gcc/testsuite/gcc.dg/system-binary-constants-1.c
new file mode 100644
index 0000000..921ee20
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/system-binary-constants-1.c
@@ -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" } */
+}
diff --git a/gcc/testsuite/gcc.dg/system-binary-constants-1.h b/gcc/testsuite/gcc.dg/system-binary-constants-1.h
new file mode 100644
index 0000000..85f2917
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/system-binary-constants-1.h
@@ -0,0 +1,3 @@
+#pragma GCC system_header
+
+#define BINARY_INT_CONSTANT_IN_SYSTEM_HEADER 0b1101