c-typeck.c (lookup_field): If -fplan9-extensions, permit referring to a field using a typedef name.
gcc/: * c-typeck.c (lookup_field): If -fplan9-extensions, permit referring to a field using a typedef name. (find_anonymous_field_with_type): New static function. (convert_to_anonymous_field): New static function. (convert_for_assignment): If -fplan9-extensions, permit converting pointer to struct to pointer to anonymous field. * c-decl.c (grokfield): If -fplan9-extensions, permit anonymous fields. (is_duplicate_field): New static function. (detect_field_duplicates_hash): If -fplan9-extensions, check for typedef names duplicating field names. (detect_field_duplicates): Likewise. * doc/invoke.texi (Option Summary): Mention -fplan9-extensions. (C Dialect Options): Document -fplan9-extensions. * doc/extend.texi (Unnamed Fields): Document -fplan9-extensions. gcc/c-family/: * c.opt (-fplan9-extensions): New option. gcc/testsuite/: * gcc.dg/anon-struct-11.c: New test. * gcc.dg/anon-struct-12.c: New test. * gcc.dg/anon-struct-13.c: New test. * gcc.dg/anon-struct-14.c: New test. From-SVN: r164926
This commit is contained in:
parent
3b5269a95e
commit
478a1c5b90
12 changed files with 591 additions and 9 deletions
|
@ -1,3 +1,21 @@
|
|||
2010-10-03 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* c-typeck.c (lookup_field): If -fplan9-extensions, permit
|
||||
referring to a field using a typedef name.
|
||||
(find_anonymous_field_with_type): New static function.
|
||||
(convert_to_anonymous_field): New static function.
|
||||
(convert_for_assignment): If -fplan9-extensions, permit converting
|
||||
pointer to struct to pointer to anonymous field.
|
||||
* c-decl.c (grokfield): If -fplan9-extensions, permit anonymous
|
||||
fields.
|
||||
(is_duplicate_field): New static function.
|
||||
(detect_field_duplicates_hash): If -fplan9-extensions, check for
|
||||
typedef names duplicating field names.
|
||||
(detect_field_duplicates): Likewise.
|
||||
* doc/invoke.texi (Option Summary): Mention -fplan9-extensions.
|
||||
(C Dialect Options): Document -fplan9-extensions.
|
||||
* doc/extend.texi (Unnamed Fields): Document -fplan9-extensions.
|
||||
|
||||
2010-10-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* tree-vect-data-refs.c (vect_analyze_data_ref_access): Revert
|
||||
|
|
83
gcc/c-decl.c
83
gcc/c-decl.c
|
@ -6614,15 +6614,15 @@ grokfield (location_t loc,
|
|||
is the anonymous union extension. Similarly for struct.
|
||||
|
||||
If this is something of the form "struct foo;", then
|
||||
If MS extensions are enabled, this is handled as an
|
||||
anonymous struct.
|
||||
If MS or Plan 9 extensions are enabled, this is handled as
|
||||
an anonymous struct.
|
||||
Otherwise this is a forward declaration of a structure tag.
|
||||
|
||||
If this is something of the form "foo;" and foo is a TYPE_DECL, then
|
||||
If foo names a structure or union without a tag, then this
|
||||
is an anonymous struct (this is permitted by C1X).
|
||||
If MS extensions are enabled and foo names a structure, then
|
||||
again this is an anonymous struct.
|
||||
If MS or Plan 9 extensions are enabled and foo names a
|
||||
structure, then again this is an anonymous struct.
|
||||
Otherwise this is an error.
|
||||
|
||||
Oh what a horrid tangled web we weave. I wonder if MS consciously
|
||||
|
@ -6636,7 +6636,7 @@ grokfield (location_t loc,
|
|||
|
||||
if (type_ok)
|
||||
{
|
||||
if (flag_ms_extensions)
|
||||
if (flag_ms_extensions || flag_plan9_extensions)
|
||||
ok = true;
|
||||
else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL)
|
||||
ok = true;
|
||||
|
@ -6688,6 +6688,50 @@ grokfield (location_t loc,
|
|||
return value;
|
||||
}
|
||||
|
||||
/* Subroutine of detect_field_duplicates: return whether X and Y,
|
||||
which are both fields in the same struct, have duplicate field
|
||||
names. */
|
||||
|
||||
static bool
|
||||
is_duplicate_field (tree x, tree y)
|
||||
{
|
||||
if (DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y))
|
||||
return true;
|
||||
|
||||
/* When using -fplan9-extensions, an anonymous field whose name is a
|
||||
typedef can duplicate a field name. */
|
||||
if (flag_plan9_extensions
|
||||
&& (DECL_NAME (x) == NULL_TREE || DECL_NAME (y) == NULL_TREE))
|
||||
{
|
||||
tree xt, xn, yt, yn;
|
||||
|
||||
xt = TREE_TYPE (x);
|
||||
if (DECL_NAME (x) != NULL_TREE)
|
||||
xn = DECL_NAME (x);
|
||||
else if ((TREE_CODE (xt) == RECORD_TYPE || TREE_CODE (xt) == UNION_TYPE)
|
||||
&& TYPE_NAME (xt) != NULL_TREE
|
||||
&& TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL)
|
||||
xn = DECL_NAME (TYPE_NAME (xt));
|
||||
else
|
||||
xn = NULL_TREE;
|
||||
|
||||
yt = TREE_TYPE (y);
|
||||
if (DECL_NAME (y) != NULL_TREE)
|
||||
yn = DECL_NAME (y);
|
||||
else if ((TREE_CODE (yt) == RECORD_TYPE || TREE_CODE (yt) == UNION_TYPE)
|
||||
&& TYPE_NAME (yt) != NULL_TREE
|
||||
&& TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL)
|
||||
yn = DECL_NAME (TYPE_NAME (yt));
|
||||
else
|
||||
yn = NULL_TREE;
|
||||
|
||||
if (xn != NULL_TREE && xn == yn)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
|
||||
to HTAB, giving errors for any duplicates. */
|
||||
|
||||
|
@ -6710,7 +6754,22 @@ detect_field_duplicates_hash (tree fieldlist, htab_t htab)
|
|||
}
|
||||
else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
|
||||
detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
|
||||
{
|
||||
detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
|
||||
|
||||
/* When using -fplan9-extensions, an anonymous field whose
|
||||
name is a typedef can duplicate a field name. */
|
||||
if (flag_plan9_extensions
|
||||
&& TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
|
||||
&& TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)
|
||||
{
|
||||
tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x)));
|
||||
slot = htab_find_slot (htab, xn, INSERT);
|
||||
if (*slot)
|
||||
error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x)));
|
||||
*slot = xn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate an error for any duplicate field names in FIELDLIST. Munge
|
||||
|
@ -6755,10 +6814,18 @@ detect_field_duplicates (tree fieldlist)
|
|||
if (timeout > 0)
|
||||
{
|
||||
for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x))
|
||||
if (DECL_NAME (x))
|
||||
/* When using -fplan9-extensions, we can have duplicates
|
||||
between typedef names and fields. */
|
||||
if (DECL_NAME (x)
|
||||
|| (flag_plan9_extensions
|
||||
&& DECL_NAME (x) == NULL_TREE
|
||||
&& (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
|
||||
&& TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
|
||||
&& TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL))
|
||||
{
|
||||
for (y = fieldlist; y != x; y = TREE_CHAIN (y))
|
||||
if (DECL_NAME (y) == DECL_NAME (x))
|
||||
if (is_duplicate_field (y, x))
|
||||
{
|
||||
error ("duplicate member %q+D", x);
|
||||
DECL_NAME (x) = NULL_TREE;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2010-10-03 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* c.opt (-fplan9-extensions): New option.
|
||||
|
||||
2010-10-03 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
|
||||
|
||||
* c-cppbuiltin.c (define__GNUC__, builtin_define_type_precision):
|
||||
|
|
|
@ -893,6 +893,10 @@ fpermissive
|
|||
C++ ObjC++
|
||||
Downgrade conformance errors to warnings
|
||||
|
||||
fplan9-extensions
|
||||
C ObjC Var(flag_plan9_extensions)
|
||||
Enable Plan 9 language extensions
|
||||
|
||||
fpreprocessed
|
||||
C ObjC C++ ObjC++
|
||||
Treat the input file as already preprocessed
|
||||
|
|
140
gcc/c-typeck.c
140
gcc/c-typeck.c
|
@ -2044,6 +2044,17 @@ lookup_field (tree type, tree component)
|
|||
|
||||
if (anon)
|
||||
return tree_cons (NULL_TREE, field, anon);
|
||||
|
||||
/* The Plan 9 compiler permits referring
|
||||
directly to an anonymous struct/union field
|
||||
using a typedef name. */
|
||||
if (flag_plan9_extensions
|
||||
&& TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
|
||||
&& (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
|
||||
== TYPE_DECL)
|
||||
&& (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
|
||||
== component))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2080,6 +2091,16 @@ lookup_field (tree type, tree component)
|
|||
|
||||
if (anon)
|
||||
return tree_cons (NULL_TREE, field, anon);
|
||||
|
||||
/* The Plan 9 compiler permits referring directly to an
|
||||
anonymous struct/union field using a typedef
|
||||
name. */
|
||||
if (flag_plan9_extensions
|
||||
&& TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
|
||||
&& TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL
|
||||
&& (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
|
||||
== component))
|
||||
break;
|
||||
}
|
||||
|
||||
if (DECL_NAME (field) == component)
|
||||
|
@ -4952,6 +4973,106 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Return whether STRUCT_TYPE has an anonymous field with type TYPE.
|
||||
This is used to implement -fplan9-extensions. */
|
||||
|
||||
static bool
|
||||
find_anonymous_field_with_type (tree struct_type, tree type)
|
||||
{
|
||||
tree field;
|
||||
bool found;
|
||||
|
||||
gcc_assert (TREE_CODE (struct_type) == RECORD_TYPE
|
||||
|| TREE_CODE (struct_type) == UNION_TYPE);
|
||||
found = false;
|
||||
for (field = TYPE_FIELDS (struct_type);
|
||||
field != NULL_TREE;
|
||||
field = TREE_CHAIN (field))
|
||||
{
|
||||
if (DECL_NAME (field) == NULL
|
||||
&& comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
|
||||
{
|
||||
if (found)
|
||||
return false;
|
||||
found = true;
|
||||
}
|
||||
else if (DECL_NAME (field) == NULL
|
||||
&& (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
|
||||
&& find_anonymous_field_with_type (TREE_TYPE (field), type))
|
||||
{
|
||||
if (found)
|
||||
return false;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/* RHS is an expression whose type is pointer to struct. If there is
|
||||
an anonymous field in RHS with type TYPE, then return a pointer to
|
||||
that field in RHS. This is used with -fplan9-extensions. This
|
||||
returns NULL if no conversion could be found. */
|
||||
|
||||
static tree
|
||||
convert_to_anonymous_field (location_t location, tree type, tree rhs)
|
||||
{
|
||||
tree rhs_struct_type, lhs_main_type;
|
||||
tree field, found_field;
|
||||
bool found_sub_field;
|
||||
tree ret;
|
||||
|
||||
gcc_assert (POINTER_TYPE_P (TREE_TYPE (rhs)));
|
||||
rhs_struct_type = TREE_TYPE (TREE_TYPE (rhs));
|
||||
gcc_assert (TREE_CODE (rhs_struct_type) == RECORD_TYPE
|
||||
|| TREE_CODE (rhs_struct_type) == UNION_TYPE);
|
||||
|
||||
gcc_assert (POINTER_TYPE_P (type));
|
||||
lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
|
||||
|
||||
found_field = NULL_TREE;
|
||||
found_sub_field = false;
|
||||
for (field = TYPE_FIELDS (rhs_struct_type);
|
||||
field != NULL_TREE;
|
||||
field = TREE_CHAIN (field))
|
||||
{
|
||||
if (DECL_NAME (field) != NULL_TREE
|
||||
|| (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (field)) != UNION_TYPE))
|
||||
continue;
|
||||
if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
|
||||
{
|
||||
if (found_field != NULL_TREE)
|
||||
return NULL_TREE;
|
||||
found_field = field;
|
||||
}
|
||||
else if (find_anonymous_field_with_type (TREE_TYPE (field),
|
||||
lhs_main_type))
|
||||
{
|
||||
if (found_field != NULL_TREE)
|
||||
return NULL_TREE;
|
||||
found_field = field;
|
||||
found_sub_field = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_field == NULL_TREE)
|
||||
return NULL_TREE;
|
||||
|
||||
ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (found_field),
|
||||
build_fold_indirect_ref (rhs), found_field,
|
||||
NULL_TREE);
|
||||
ret = build_fold_addr_expr_loc (location, ret);
|
||||
|
||||
if (found_sub_field)
|
||||
{
|
||||
ret = convert_to_anonymous_field (location, type, ret);
|
||||
gcc_assert (ret != NULL_TREE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Convert value RHS to type TYPE as preparation for an assignment to
|
||||
an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the
|
||||
original type of RHS; this differs from TREE_TYPE (RHS) for enum
|
||||
|
@ -5323,6 +5444,25 @@ convert_for_assignment (location_t location, tree type, tree rhs,
|
|||
/* Opaque pointers are treated like void pointers. */
|
||||
is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
|
||||
|
||||
/* The Plan 9 compiler permits a pointer to a struct to be
|
||||
automatically converted into a pointer to an anonymous field
|
||||
within the struct. */
|
||||
if (flag_plan9_extensions
|
||||
&& (TREE_CODE (mvl) == RECORD_TYPE || TREE_CODE(mvl) == UNION_TYPE)
|
||||
&& (TREE_CODE (mvr) == RECORD_TYPE || TREE_CODE(mvr) == UNION_TYPE)
|
||||
&& mvl != mvr)
|
||||
{
|
||||
tree new_rhs = convert_to_anonymous_field (location, type, rhs);
|
||||
if (new_rhs != NULL_TREE)
|
||||
{
|
||||
rhs = new_rhs;
|
||||
rhstype = TREE_TYPE (rhs);
|
||||
coder = TREE_CODE (rhstype);
|
||||
ttr = TREE_TYPE (rhstype);
|
||||
mvr = TYPE_MAIN_VARIANT (ttr);
|
||||
}
|
||||
}
|
||||
|
||||
/* C++ does not allow the implicit conversion void* -> T*. However,
|
||||
for the purpose of reducing the number of false positives, we
|
||||
tolerate the special case of
|
||||
|
|
|
@ -13027,6 +13027,34 @@ also be a definition with a tag such as @samp{struct foo @{ int a;
|
|||
@samp{struct foo;}, or a reference to a @code{typedef} name for a
|
||||
previously defined structure or union type with a tag.
|
||||
|
||||
@opindex fplan9-extensions
|
||||
The option @option{-fplan9-extensions} enables
|
||||
@option{-fms-extensions} as well as two other extensions. First, a
|
||||
pointer to a structure is automatically converted to a pointer to an
|
||||
anonymous field for assignments and function calls. For example:
|
||||
|
||||
@smallexample
|
||||
struct s1 @{ int a; @};
|
||||
struct s2 @{ struct s1; @};
|
||||
extern void f1 (struct s1 *);
|
||||
void f2 (struct s2 *p) @{ f1 (p); @}
|
||||
@end smallexample
|
||||
|
||||
In the call to @code{f1} inside @code{f2}, the pointer @code{p} is
|
||||
converted into a pointer to the anonymous field.
|
||||
|
||||
Second, when the type of an anonymous field is a @code{typedef} for a
|
||||
@code{struct} or @code{union}, code may refer to the field using the
|
||||
name of the @code{typedef}.
|
||||
|
||||
@smallexample
|
||||
typedef struct @{ int a; @} s1;
|
||||
struct s2 @{ s1; @};
|
||||
s1 f1 (struct s2 *p) @{ return p->s1; @}
|
||||
@end smallexample
|
||||
|
||||
These usages are only permitted when they are not ambiguous.
|
||||
|
||||
@node Thread-Local
|
||||
@section Thread-Local Storage
|
||||
@cindex Thread-Local Storage
|
||||
|
|
|
@ -172,7 +172,7 @@ in the following sections.
|
|||
@gccoptlist{-ansi -std=@var{standard} -fgnu89-inline @gol
|
||||
-aux-info @var{filename} @gol
|
||||
-fno-asm -fno-builtin -fno-builtin-@var{function} @gol
|
||||
-fhosted -ffreestanding -fopenmp -fms-extensions @gol
|
||||
-fhosted -ffreestanding -fopenmp -fms-extensions -fplan9-extensions @gol
|
||||
-trigraphs -no-integrated-cpp -traditional -traditional-cpp @gol
|
||||
-fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol
|
||||
-fsigned-bitfields -fsigned-char @gol
|
||||
|
@ -1700,6 +1700,16 @@ Some cases of unnamed fields in structures and unions are only
|
|||
accepted with this option. @xref{Unnamed Fields,,Unnamed struct/union
|
||||
fields within structs/unions}, for details.
|
||||
|
||||
@item -fplan9-extensions
|
||||
Accept some non-standard constructs used in Plan 9 code.
|
||||
|
||||
This enables @option{-fms-extensions}, permits passing pointers to
|
||||
structures with anonymous fields to functions which expect pointers to
|
||||
elements of the type of the field, and permits referring to anonymous
|
||||
fields declared using a typedef. @xref{Unnamed Fields,,Unnamed
|
||||
struct/union fields within structs/unions}, for details. This is only
|
||||
supported for C, not C++.
|
||||
|
||||
@item -trigraphs
|
||||
@opindex trigraphs
|
||||
Support ISO C trigraphs. The @option{-ansi} option (and @option{-std}
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2010-10-03 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* gcc.dg/anon-struct-11.c: New test.
|
||||
* gcc.dg/anon-struct-12.c: New test.
|
||||
* gcc.dg/anon-struct-13.c: New test.
|
||||
* gcc.dg/anon-struct-14.c: New test.
|
||||
|
||||
2010-10-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* g++.dg/torture/pr45764.C: Revert revision 164914.
|
||||
|
|
111
gcc/testsuite/gcc.dg/anon-struct-11.c
Normal file
111
gcc/testsuite/gcc.dg/anon-struct-11.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
/* { dg-do compile } */
|
||||
|
||||
/* No special options--in particular, turn off the default
|
||||
-pedantic-errors option. */
|
||||
/* { dg-options "" } */
|
||||
|
||||
/* When not using -fplan9-extensions, we don't support automatic
|
||||
conversion of pointer types, and we don't support referring to a
|
||||
typedef name directly. */
|
||||
|
||||
extern void exit (int);
|
||||
extern void abort (void);
|
||||
|
||||
struct A { char a; };
|
||||
|
||||
struct B {
|
||||
char b;
|
||||
struct A; /* { dg-warning "does not declare anything" } */
|
||||
char c;
|
||||
};
|
||||
|
||||
void
|
||||
f1 (struct A *p) /* { dg-message "expected" } */
|
||||
{
|
||||
p->a = 1;
|
||||
}
|
||||
|
||||
void
|
||||
test1 (void)
|
||||
{
|
||||
struct B b;
|
||||
struct A *p;
|
||||
|
||||
b.b = 2;
|
||||
b.c = 3;
|
||||
f1 (&b); /* { dg-warning "incompatible pointer type" } */
|
||||
if (b.a != 1) /* { dg-error "no member" } */
|
||||
abort ();
|
||||
if (b.b != 2 || b.c != 3)
|
||||
abort ();
|
||||
p = &b; /* { dg-warning "incompatible pointer type" } */
|
||||
if (p->a != 1)
|
||||
abort ();
|
||||
}
|
||||
|
||||
typedef struct { char d; } D;
|
||||
|
||||
struct E {
|
||||
char b;
|
||||
struct F { char f; }; /* { dg-warning "does not declare anything" } */
|
||||
char c;
|
||||
union {
|
||||
D;
|
||||
};
|
||||
char e;
|
||||
};
|
||||
|
||||
void
|
||||
f2 (struct F *p) /* { dg-message "expected" } */
|
||||
{
|
||||
p->f = 6;
|
||||
}
|
||||
|
||||
void
|
||||
f3 (D *p) /* { dg-message "expected" } */
|
||||
{
|
||||
p->d = 4;
|
||||
}
|
||||
|
||||
void
|
||||
f4 (D d)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test2 (void)
|
||||
{
|
||||
struct E e;
|
||||
struct F *pf;
|
||||
D *pd;
|
||||
D d;
|
||||
|
||||
e.b = 2;
|
||||
e.c = 3;
|
||||
e.e = 5;
|
||||
f2 (&e); /* { dg-warning "incompatible pointer type" } */
|
||||
f3 (&e); /* { dg-warning "incompatible pointer type" } */
|
||||
if (e.d != 4)
|
||||
abort ();
|
||||
if (e.f != 6) /* { dg-error "no member" } */
|
||||
abort ();
|
||||
if (e.b != 2 || e.c != 3 || e.e != 5)
|
||||
abort ();
|
||||
pf = &e; /* { dg-warning "incompatible pointer type" } */
|
||||
if (pf->f != 6)
|
||||
abort ();
|
||||
pd = &e; /* { dg-warning "incompatible pointer type" } */
|
||||
if (pd->d != 4)
|
||||
abort ();
|
||||
d = e.D; /* { dg-error "no member" } */
|
||||
f3 (&e.D); /* { dg-error "no member" } */
|
||||
f4 (e.D); /* { dg-error "no member" } */
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
test1 ();
|
||||
test2 ();
|
||||
exit (0);
|
||||
}
|
108
gcc/testsuite/gcc.dg/anon-struct-12.c
Normal file
108
gcc/testsuite/gcc.dg/anon-struct-12.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-options "-fplan9-extensions" } */
|
||||
|
||||
/* When using -fplan9-extensions, we support automatic conversion of
|
||||
pointer types, and we support referring to a typedef name
|
||||
directly. */
|
||||
|
||||
extern void exit (int);
|
||||
extern void abort (void);
|
||||
|
||||
struct A { char a; };
|
||||
|
||||
struct B {
|
||||
char b;
|
||||
struct A;
|
||||
char c;
|
||||
};
|
||||
|
||||
void
|
||||
f1 (struct A *p)
|
||||
{
|
||||
p->a = 1;
|
||||
}
|
||||
|
||||
void
|
||||
test1 (void)
|
||||
{
|
||||
struct B b;
|
||||
struct A *p;
|
||||
|
||||
b.b = 2;
|
||||
b.c = 3;
|
||||
f1 (&b);
|
||||
if (b.a != 1)
|
||||
abort ();
|
||||
if (b.b != 2 || b.c != 3)
|
||||
abort ();
|
||||
p = &b;
|
||||
if (p->a != 1)
|
||||
abort ();
|
||||
}
|
||||
|
||||
typedef struct { char d; } D;
|
||||
|
||||
struct E {
|
||||
char b;
|
||||
struct F { char f; };
|
||||
char c;
|
||||
union {
|
||||
D;
|
||||
};
|
||||
char e;
|
||||
};
|
||||
|
||||
void
|
||||
f2 (struct F *p)
|
||||
{
|
||||
p->f = 6;
|
||||
}
|
||||
|
||||
void
|
||||
f3 (D *p)
|
||||
{
|
||||
p->d = 4;
|
||||
}
|
||||
|
||||
void
|
||||
f4 (D d)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
test2 (void)
|
||||
{
|
||||
struct E e;
|
||||
struct F *pf;
|
||||
D *pd;
|
||||
D d;
|
||||
|
||||
e.b = 2;
|
||||
e.c = 3;
|
||||
e.e = 5;
|
||||
f2 (&e);
|
||||
f3 (&e);
|
||||
if (e.d != 4)
|
||||
abort ();
|
||||
if (e.f != 6)
|
||||
abort ();
|
||||
if (e.b != 2 || e.c != 3 || e.e != 5)
|
||||
abort ();
|
||||
pf = &e;
|
||||
if (pf->f != 6)
|
||||
abort ();
|
||||
pd = &e;
|
||||
if (pd->d != 4)
|
||||
abort ();
|
||||
d = e.D;
|
||||
f3 (&e.D);
|
||||
f4 (e.D);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
test1 ();
|
||||
test2 ();
|
||||
exit (0);
|
||||
}
|
76
gcc/testsuite/gcc.dg/anon-struct-13.c
Normal file
76
gcc/testsuite/gcc.dg/anon-struct-13.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fplan9-extensions" } */
|
||||
|
||||
/* Test for ambiguity when using the Plan 9 extensions. */
|
||||
|
||||
struct A {
|
||||
char a; /* { dg-error "duplicate member" } */
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
struct A;
|
||||
struct A;
|
||||
};
|
||||
|
||||
char
|
||||
f1 (struct B *p)
|
||||
{
|
||||
return p->a; /* { dg-error "no member" } */
|
||||
}
|
||||
|
||||
void
|
||||
f2 (struct A *p) /* { dg-message "expected" } */
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
f3 (struct B *p)
|
||||
{
|
||||
f2 (p); /* { dg-warning "incompatible pointer type" } */
|
||||
}
|
||||
|
||||
struct C
|
||||
{
|
||||
char c; /* { dg-error "duplicate member" } */
|
||||
};
|
||||
|
||||
struct D
|
||||
{
|
||||
struct C;
|
||||
};
|
||||
|
||||
struct E
|
||||
{
|
||||
struct C;
|
||||
struct D;
|
||||
};
|
||||
|
||||
char
|
||||
f4 (struct E *p)
|
||||
{
|
||||
return p->c; /* { dg-error "no member" } */
|
||||
}
|
||||
|
||||
void
|
||||
f6 (struct C *p) /* { dg-message "expected" } */
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
f7 (struct E *p)
|
||||
{
|
||||
f6 (p); /* { dg-warning "incompatible pointer type" } */
|
||||
}
|
||||
|
||||
struct A
|
||||
f8 (struct B *p)
|
||||
{
|
||||
return p->A; /* { dg-error "no member" } */
|
||||
}
|
||||
|
||||
struct C
|
||||
f9 (struct E *p)
|
||||
{
|
||||
return p->C; /* { dg-error "no member" } */
|
||||
}
|
9
gcc/testsuite/gcc.dg/anon-struct-14.c
Normal file
9
gcc/testsuite/gcc.dg/anon-struct-14.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fplan9-extensions" } */
|
||||
|
||||
/* When using Plan 9 extensions, a typedef can conflict with an
|
||||
anonymous field. */
|
||||
|
||||
typedef struct { int a; } s1;
|
||||
struct s2 { s1; int s1; }; /* { dg-error "duplicate" } */
|
||||
int f(struct s2 *p) { return p->s1; } /* { dg-error "incompatible" } */
|
Loading…
Add table
Reference in a new issue