Commit 478a1c5b by Ian Lance Taylor Committed by Ian Lance Taylor

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
parent 3b5269a9
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> 2010-10-03 H.J. Lu <hongjiu.lu@intel.com>
* tree-vect-data-refs.c (vect_analyze_data_ref_access): Revert * tree-vect-data-refs.c (vect_analyze_data_ref_access): Revert
...@@ -6614,15 +6614,15 @@ grokfield (location_t loc, ...@@ -6614,15 +6614,15 @@ grokfield (location_t loc,
is the anonymous union extension. Similarly for struct. is the anonymous union extension. Similarly for struct.
If this is something of the form "struct foo;", then If this is something of the form "struct foo;", then
If MS extensions are enabled, this is handled as an If MS or Plan 9 extensions are enabled, this is handled as
anonymous struct. an anonymous struct.
Otherwise this is a forward declaration of a structure tag. 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 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 If foo names a structure or union without a tag, then this
is an anonymous struct (this is permitted by C1X). is an anonymous struct (this is permitted by C1X).
If MS extensions are enabled and foo names a structure, then If MS or Plan 9 extensions are enabled and foo names a
again this is an anonymous struct. structure, then again this is an anonymous struct.
Otherwise this is an error. Otherwise this is an error.
Oh what a horrid tangled web we weave. I wonder if MS consciously Oh what a horrid tangled web we weave. I wonder if MS consciously
...@@ -6636,7 +6636,7 @@ grokfield (location_t loc, ...@@ -6636,7 +6636,7 @@ grokfield (location_t loc,
if (type_ok) if (type_ok)
{ {
if (flag_ms_extensions) if (flag_ms_extensions || flag_plan9_extensions)
ok = true; ok = true;
else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL) else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL)
ok = true; ok = true;
...@@ -6688,6 +6688,50 @@ grokfield (location_t loc, ...@@ -6688,6 +6688,50 @@ grokfield (location_t loc,
return value; 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 /* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
to HTAB, giving errors for any duplicates. */ to HTAB, giving errors for any duplicates. */
...@@ -6710,7 +6754,22 @@ detect_field_duplicates_hash (tree fieldlist, htab_t htab) ...@@ -6710,7 +6754,22 @@ detect_field_duplicates_hash (tree fieldlist, htab_t htab)
} }
else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (x)) == UNION_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 /* Generate an error for any duplicate field names in FIELDLIST. Munge
...@@ -6755,10 +6814,18 @@ detect_field_duplicates (tree fieldlist) ...@@ -6755,10 +6814,18 @@ detect_field_duplicates (tree fieldlist)
if (timeout > 0) if (timeout > 0)
{ {
for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x)) 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)) 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); error ("duplicate member %q+D", x);
DECL_NAME (x) = NULL_TREE; DECL_NAME (x) = NULL_TREE;
......
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> 2010-10-03 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
* c-cppbuiltin.c (define__GNUC__, builtin_define_type_precision): * c-cppbuiltin.c (define__GNUC__, builtin_define_type_precision):
......
...@@ -893,6 +893,10 @@ fpermissive ...@@ -893,6 +893,10 @@ fpermissive
C++ ObjC++ C++ ObjC++
Downgrade conformance errors to warnings Downgrade conformance errors to warnings
fplan9-extensions
C ObjC Var(flag_plan9_extensions)
Enable Plan 9 language extensions
fpreprocessed fpreprocessed
C ObjC C++ ObjC++ C ObjC C++ ObjC++
Treat the input file as already preprocessed Treat the input file as already preprocessed
......
...@@ -2044,6 +2044,17 @@ lookup_field (tree type, tree component) ...@@ -2044,6 +2044,17 @@ lookup_field (tree type, tree component)
if (anon) if (anon)
return tree_cons (NULL_TREE, field, 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) ...@@ -2080,6 +2091,16 @@ lookup_field (tree type, tree component)
if (anon) if (anon)
return tree_cons (NULL_TREE, field, 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) if (DECL_NAME (field) == component)
...@@ -4952,6 +4973,106 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, ...@@ -4952,6 +4973,106 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
return result; 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 /* 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 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 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, ...@@ -5323,6 +5444,25 @@ convert_for_assignment (location_t location, tree type, tree rhs,
/* Opaque pointers are treated like void pointers. */ /* Opaque pointers are treated like void pointers. */
is_opaque_pointer = vector_targets_convertible_p (ttl, ttr); 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, /* C++ does not allow the implicit conversion void* -> T*. However,
for the purpose of reducing the number of false positives, we for the purpose of reducing the number of false positives, we
tolerate the special case of tolerate the special case of
......
...@@ -13027,6 +13027,34 @@ also be a definition with a tag such as @samp{struct foo @{ int a; ...@@ -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 @samp{struct foo;}, or a reference to a @code{typedef} name for a
previously defined structure or union type with a tag. 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 @node Thread-Local
@section Thread-Local Storage @section Thread-Local Storage
@cindex Thread-Local Storage @cindex Thread-Local Storage
......
...@@ -172,7 +172,7 @@ in the following sections. ...@@ -172,7 +172,7 @@ in the following sections.
@gccoptlist{-ansi -std=@var{standard} -fgnu89-inline @gol @gccoptlist{-ansi -std=@var{standard} -fgnu89-inline @gol
-aux-info @var{filename} @gol -aux-info @var{filename} @gol
-fno-asm -fno-builtin -fno-builtin-@var{function} @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 -trigraphs -no-integrated-cpp -traditional -traditional-cpp @gol
-fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol -fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol
-fsigned-bitfields -fsigned-char @gol -fsigned-bitfields -fsigned-char @gol
...@@ -1700,6 +1700,16 @@ Some cases of unnamed fields in structures and unions are only ...@@ -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 accepted with this option. @xref{Unnamed Fields,,Unnamed struct/union
fields within structs/unions}, for details. 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 @item -trigraphs
@opindex trigraphs @opindex trigraphs
Support ISO C trigraphs. The @option{-ansi} option (and @option{-std} Support ISO C trigraphs. The @option{-ansi} option (and @option{-std}
......
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> 2010-10-03 H.J. Lu <hongjiu.lu@intel.com>
* g++.dg/torture/pr45764.C: Revert revision 164914. * g++.dg/torture/pr45764.C: Revert revision 164914.
......
/* { 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);
}
/* { 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);
}
/* { 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" } */
}
/* { 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" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment