Confused by compiler warning



 DEVELOP > C > Confused by compiler warning

LINK TO THIS PAGE  


rating :  0   |  0


  Page 1 of 1

1

 
Topic: DEVELOP > C
User: "James H. Newman"
Date: 05 Feb 2008 06:16:59 PM
Object: Confused by compiler warning
I am playing with some code that has been automatically generated
from ASN.1 data specification found in RFC 3280. One of the structures
generated reads as follows:
typedef struct TBSCertList {
Version_t *version /* OPTIONAL */;
AlgorithmIdentifier_t signature;
Name_t issuer;
Time_t thisUpdate;
struct Time *nextUpdate /* OPTIONAL */;
struct revokedCertificates {
A_SEQUENCE_OF(struct Member {
CertificateSerialNumber_t userCertificate;
Time_t revocationDate;
struct Extensions *crlEntryExtensions /
* OPTIONAL */;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} ) list;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} *revokedCertificates;
struct Extensions *crlExtensions /* OPTIONAL */;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} TBSCertList_t;
/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_TBSCertList;
}
where A_SEQUENCE_OF() is defined as
#define A_SEQUENCE_OF(type) \
struct { \
type **array; \
int count; /* Meaningful size */ \
int size; /* Allocated size */ \
void (*free)(type *); \
}
The preprocessor expands this as
typedef struct TBSCertList {
Version_t *version;
AlgorithmIdentifier_t signature;
Name_t issuer;
Time_t thisUpdate;
struct Time *nextUpdate;
struct revokedCertificates {
struct {
struct Member {
CertificateSerialNumber_t userCertificate;
Time_t revocationDate;
struct Extensions *crlEntryExtensions;
asn_struct_ctx_t _asn_ctx;
} **array;
int count;
int size;
void (*free) (struct Member {
CertificateSerialNumber_t userCertificate;
Time_t revocationDate;
struct Extensions * crlEntryExtensions;
asn_struct_ctx_t _asn_ctx;
} *);
} list;
asn_struct_ctx_t _asn_ctx;
} *revokedCertificates;
struct Extensions *crlExtensions;
asn_struct_ctx_t _asn_ctx;
} TBSCertList_t;
This compiles all right, but the GCC compiler generates the
following warning:
TBSCertList.h:47: warning: structure defined inside parms
TBSCertList.h:47: warning: `struct Member' declared inside parameter list
TBSCertList.h:47: warning: its scope is only this definition or
declaration, which is probably not what you want
Line 47 is the line that reads
} ) list;
in the code above, before the preprocessing.
Now I want to believe that this code is generated the way it is
generated for some good reason. What I do not understand is what the
compiler is complaining about. Anybody care to explain? What is it about
struct Member that the compiler reckons that that's not what we want?
.

User: "Peter Nilsson"

Title: Re: Confused by compiler warning 05 Feb 2008 06:38:56 PM
"James H. Newman" <NewJa...@exicite.com> wrote:
<snip>

=A0 =A0 =A0 =A0 This compiles all right, but the GCC compiler
generates the following warning:

TBSCertList.h:47: warning: structure defined inside parms
TBSCertList.h:47: warning: `struct Member' declared inside parameter list
TBSCertList.h:47: warning: its scope is only this definition or
declaration, which is probably not what you want

This is Question 11.5 in the FAQ...
http://c-faq.com/ansi/structinproto.html
--
Peter
.

User: "Jack Klein"

Title: Re: Confused by compiler warning 05 Feb 2008 10:04:36 PM
On Wed, 06 Feb 2008 00:16:59 GMT, "James H. Newman"
<NewJames@exicite.com> wrote in comp.lang.c:

I am playing with some code that has been automatically generated
from ASN.1 data specification found in RFC 3280. One of the structures
generated reads as follows:

typedef struct TBSCertList {
Version_t *version /* OPTIONAL */;
AlgorithmIdentifier_t signature;
Name_t issuer;
Time_t thisUpdate;
struct Time *nextUpdate /* OPTIONAL */;
struct revokedCertificates {
A_SEQUENCE_OF(struct Member {
CertificateSerialNumber_t userCertificate;
Time_t revocationDate;
struct Extensions *crlEntryExtensions /
* OPTIONAL */;

/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} ) list;

/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} *revokedCertificates;
struct Extensions *crlExtensions /* OPTIONAL */;

/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} TBSCertList_t;

/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_TBSCertList;
}

where A_SEQUENCE_OF() is defined as

#define A_SEQUENCE_OF(type) \
struct { \
type **array; \
int count; /* Meaningful size */ \
int size; /* Allocated size */ \
void (*free)(type *); \
}

The preprocessor expands this as

typedef struct TBSCertList {
Version_t *version;
AlgorithmIdentifier_t signature;
Name_t issuer;
Time_t thisUpdate;
struct Time *nextUpdate;
struct revokedCertificates {
struct {
struct Member {
CertificateSerialNumber_t userCertificate;
Time_t revocationDate;
struct Extensions *crlEntryExtensions;
asn_struct_ctx_t _asn_ctx;
} **array;
int count;
int size;
void (*free) (struct Member {
CertificateSerialNumber_t userCertificate;
Time_t revocationDate;
struct Extensions * crlEntryExtensions;
asn_struct_ctx_t _asn_ctx;
} *);
} list;

asn_struct_ctx_t _asn_ctx;
} *revokedCertificates;
struct Extensions *crlExtensions;

asn_struct_ctx_t _asn_ctx;
} TBSCertList_t;

This compiles all right, but the GCC compiler generates the
following warning:

TBSCertList.h:47: warning: structure defined inside parms
TBSCertList.h:47: warning: `struct Member' declared inside parameter list
TBSCertList.h:47: warning: its scope is only this definition or
declaration, which is probably not what you want

Line 47 is the line that reads

} ) list;

in the code above, before the preprocessing.

Now I want to believe that this code is generated the way it is
generated for some good reason. What I do not understand is what the
compiler is complaining about. Anybody care to explain? What is it about
struct Member that the compiler reckons that that's not what we want?

C has something called "prototype scope". It applies to both names
and types that are defined inside the argument list of a function
prototype. These definitions go out of scope at the end of the
prototype.
You can see this most easily in names:
int func(int argument);
int func(int different);
int func(int x)
{
return x + 1;
}
The compiler will not complain that because the first prototype names
the argument "argument" but the second prototype for the same function
names it "different". Nor that the function definition gives it yet a
third name.
The same thing applies to types such as structs, unions, and enums
defined in a prototype scope. Consider this:
int func( struct two_ints { int x; int y; } );
struct two_ints file_scope_two_ints my_two_ints;
Compiling a file containing these two lines will is required to
generate a diagnostic on the struct object definition, because there
is no definition of "struct two_ints" in scope at that point.
In fact, if we insert a third line between the two, to get:
int func( struct two_ints { int x; int y; } );
struct two_ints { double a; double b; double c; };
struct two_ints file_scope_two_ints my_two_ints;
Then the object "my_two_ints" will actually contain three doubles, and
a later call in the same translation unit:
int result = func( my_two_ints );
....will net a diagnostic about calling "func" with an incompatible
argument type.
That is why struct, union, and enum definitions are usually defined
outside of their area of use, in a header, for example, or before
their first use if they are used in multiple places in a file.
C states that struct types are compatible if they neither has a tag
name or they both have the same tag names, and if the is a one-to-one
relationship between the order, types, and names of their members.
That is guaranteed when there is one and only one definition of the
struct type, and it is in scope everywhere the type is used.
Presumably, somewhere else in another source or header file, is a
prototype and/or definition of a function whose address will
eventually be stored in the "free" member of a struct list. It will
need to have a definition of the structure type it accepts, which
probably comes from physically different text than the source of this
macro.
If somebody changes the definition of the struct type in one place or
the other, but not all places, then suddenly you have problems,
undefined behavior, "mysterious" defects, etc.
It would be much better to put the definition of struct Member in a
header, and include that header everywhere it is used.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
.


  Page 1 of 1

1

 


Related Articles
 

NEWER

pg.716     pg.544     pg.412     pg.311     pg.234     pg.175     pg.130     pg.96     pg.70     pg.50     pg.35     pg.24     pg.16     pg.10     pg.6     pg.3     pg.1

OLDER