Pointers to Incomplete Types in Prototypes

Joseph Schwartz xor at aix01.aix.rpi.edu
Sat May 4 05:10:11 AEST 1991


In article <cl3gg!n at rpi.edu> I wrote:
>In article <700 at taumet.com> steve at taumet.com (Stephen Clamage) writes:
>>
>>There was another answer posted to this question which was not complete.
>>As shown, the prototype declares "struct bar" to be an incomplete type
>>*local to the prototype*, and hence unavailable outside the prototype.
>>It is then impossible to call this function, since no object of type
>>"struct bar" (or pointer to one) could ever exist.  (Any later "struct
>>bar" is a new type in a different scope.)  The compiler may have been
>>complaining about this.
>>
>>If you precede the declaration with an incomplete decl for bar, the
>>prototype now refers to that decl, and all is well.  Example:
>>	struct bar;			/* defined later */
>>	extern void foo(struct bar*);	/* refers to previous bar */
>>
>>You didn't say whether there was a prior incomplete decl.
>
>No, there was no prior incomplete declaration of struct bar.
>
>Your claim that struct bar has local scope to the prototype is pretty
>scary.  In many of our cases, a function foo is declared with a prototype
>in an included header file, and then a struct bar is defined in a second
>included header file, and finally the function foo is called from the
>.c file that's been doing the #including.  
>
>Now, if I understand you correctly, I should never be allowed to call 
>function foo, because the struct bar * that I pass to it is incompatible
>with the struct bar * that it was declared to take as a parameter.
>Can you please direct me to the section of the Standard that supports
>this?  Specifically, I want to know where it says that struct bar has
>scope local only to the prototype.
> 
>I'm aware that if I said:
>
>    extern void foo(struct bar *stool);
>
>then stool would be local to the prototype.  I'm skeptical that this 
>also holds for struct/union tags.
 
Okay, I've done some research and staightened out a few misunderstandings.
First things first.
 
Our compiler was NOT reporting an error when it encountered the prototype.
It was reporting a warning, essentially saying exactly what Stephen said
above:  it warned that struct bar had scope local to the prototype.
 
The compiler WAS reporting an error when it encountered a call to function
foo, again supporting Stephen 100%:  it reported that the pointer being
passed as a parameter was incompatible with the pointer used in the
prototype.
 
I apologize for not Reading The F***ing Error Messages.  I'm researching
and reporting this problem on behalf of a co-worker, and I misunderstood
his description of the problem.
 
Stephen, it DID help to put the vacuous declaration "struct bar;" before
the prototype.  Everything worked.  However, this is not a completely
acceptable solution, and I'm still not convinced that the behavior of
this compiler is a correct interpretation of the Standard.
 
The paragraph in question is 3.1.2.1, lines 32-37:
 
"If the declarator or type specifier that declares the identifier appears
within the list of parameter declarations in a function prototype (not
part of a function definition), the identifier has FUNCTION PROTOTYPE
SCOPE [emphasis theirs], which terminates at the end of the function
declarator.  If an outer declaration of a lexically identical identifier
exists in the same name space, it is hidden until the current scope
terminates, after which it again becomes visible."
 
As I said earlier, I believe this applies to the identifier "stool" in:
 
     extern void foo(struct bar *stool);
 
I could also believe that it applies to complete structure declarations,
as in:
 
     extern void foo(struct bar { int a; int b; } *);
 
But I still have a hard time believing that it applies to struct bar in:
 
     extern void foo(struct bar *);
 
Making bar have local scope in this case is of questionable usefulness,
and it would appear to break code that existed before the Standard.
 
But let's assume that the correct interpretation of the Standard is to
give struct bar local scope in my last example above.  Then why does this:
 
      struct bar;
      extern void foo(struct bar *);
 
solve the scoping problems?  According to the paragraph that I quoted above,
the vacuous declaration of struct bar is HIDDEN inside the prototype.  That
is, the local struct bar inside the prototype will override the one that's
already declared.  Once the prototype ends, its struct bar goes out of scope,
and the previous declaration is unhidden.  Any subsequent calls to foo (or
declarations of struct bar) will use a struct bar compatible with the vacuous
declaration, but not compatible with the struct bar local to the prototype.
How can adding the vacuous declaration prevent the prototype from giving
struct bar local scope?
 
-- 
Joe Schwartz
Internet: xor at mts.rpi.edu
Bitnet: userez3n at rpitsmts



More information about the Comp.std.c mailing list