[patch][pr22217] Use the most recent decl for mangling

Richard Smith richard at metafoo.co.uk
Thu Jan 29 14:47:45 PST 2015


On Fri, Jan 23, 2015 at 12:25 AM, John McCall <rjmccall at apple.com> wrote:

> > On Jan 22, 2015, at 4:52 PM, Rafael Espíndola <
> rafael.espindola at gmail.com> wrote:
> >
> > Sent the email a bit early.
> >
> >
> >>> That is not what I am seeing with gcc. Given
> >>>
> >>> int pr22217_foo;
> >>> int *b = &pr22217_foo;
> >>> extern int pr22217_foo __attribute__((section("zed")));
>
> This should be an error in both C and C++.  I see absolutely no reason to
> allow a declaration following a definition (even a tentative definition) to
> add a section attribute.  We should not be afraid to reject
> stupidly-written code when it abuses language extensions, even when they’re
> not “our” extensions.
>

I completely agree with the principle here. It is not reasonable to write
attributes that affect a definition after the definition. It is not
reasonable to write attributes that affect how a symbol is referenced (such
as an asm label) after the first use (and perhaps we should simply require
them on the first declaration).

(Segue away from attributes and towards tentative definitons follows...)

I don't agree with what you said about tentative definitions. The C
standard is very clear on the model for tentative definitions: they act
exactly like non-defining declarations until you get to the end of the
translation unit; if you've not seen a non-tentative definition by that
point "then the behavior is exactly as if the translation unit contains a
file scope declaration of that identifier, with the composite type as of
the end of the translation unit, with an initializer equal to 0."

Based on that simple semantic model, it is not reasonable for us to reject
this:

int pr22217_foo;
int *b = &pr22217_foo;
extern int pr22217_foo __attribute__((section("zed")));
int pr22217_foo = 123;

See also PR20688, which is a rejects-valid for standard C11 code due to our
being confused about how tentative definitions work.

And here's another case we get wrong:

  int a[];
  extern int a[5];

We're required to emit a definition of 'a' with type 'int[5]', but we emit
it with type 'int[1]'. We get the corresponding case with an incomplete
struct correct:

  struct foo x; // ok, tentative definition
  struct foo { int n, m; };
  // definition emitted now and has complete type; initializer is {0}.

There are lots of ways we can fix this; perhaps the easiest one would be to
literally follow what the C standard says: synthesize a definition for each
tentatively-defined variable at the end of the translation unit. Then we
can change isThisDeclarationADefinition to simply return 'bool' instead of
an enum, and have it return 'false' for tentative definitions. Sema would
track the tentative definitions it's seen, and consider converting each one
to a definition at end-of-TU.

Or we can try to keep our current model with a tristate for whether a
declaration is a definition, but that requires both Sema and IRGen to get a
lot smarter with regard to handling of tentative definitions.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150129/5ec35dd5/attachment.html>


More information about the cfe-commits mailing list