This is an archive of the discontinued LLVM Phabricator instance.

Implement P1766R1: diagnose giving non-C-compatible classes a typedef name for linkage purposes.
ClosedPublic

Authored by rsmith on Feb 5 2020, 6:55 PM.

Details

Summary

Due to a recent (but retroactive) C++ rule change, only sufficiently
C-compatible classes are permitted to be given a typedef name for
linkage purposes. Add an enabled-by-default warning for these cases, and
rephrase our existing error for the case where we encounter the typedef
name for linkage after we've already computed and used a wrong linkage
in terms of the new rule.

Diff Detail

Event Timeline

rsmith created this revision.Feb 5 2020, 6:55 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 5 2020, 6:55 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Oh thank goodness, they finally fixed this.

clang/lib/Sema/SemaDecl.cpp
4365

Starting the quote here makes it look like it's describing the invalid-decl short-circuit just below.

4394

This is essentially part of the next paragraph.

I believe friend declarations also do not declare "members", under the same logic allowing static_assert.

4404

Do lambdas in nested expressions really get added to the class's decls list? I wouldn't have expected that, but it definitely makes this check a lot easier.

rsmith updated this revision to Diff 243022.Feb 6 2020, 2:58 PM
rsmith marked 4 inline comments as done.

Updates based on review comments from @rjmccall.

clang/lib/Sema/SemaDecl.cpp
4394

I think you're right, but that's a defect in the wording -- a friend definition, at least, could use the class in a way that requires a linkage calculation, and the design intent as approved by the Evolution Working Group did not permit friend declarations. I'll take this back to the committee for some rewording, but I think it makes sense to proceed under the assumption that friends won't be allowed. In any case, I'm updating the diagnostic to treat friends as a special case, since they're not member declarations.

4404

They end up in some enclosing DeclContext, which is either the class itself or something else that we also disallow.

rsmith updated this revision to Diff 243023.Feb 6 2020, 3:00 PM

Add test coverage for the 'friend' case.

Harbormaster completed remote builds in B45900: Diff 243023.
rjmccall added inline comments.Feb 6 2020, 4:07 PM
clang/lib/Sema/SemaDecl.cpp
4394

Could it? I think the same inability to write a self-reference that makes the C-like cases okay should also apply to friends. If you can write a self-reference in a friend declaration, you can write one in a template argument list in the type of a field declaration. Well, okay, I suppose a friend function *definition* might need to be forbidden.

Anyway, I don't think it's actually a problem if the committee wants to outlaw friends here, just wondering at the effective rule they're aiming for in case we need to figure out how to apply it to extensions.

4404

Yeah, obviously their DC should be the class, but I didn't think the decl-to-DC link always implied membership in the decls list. But hey, it seems to work in the case we care about.

4491

Might be good to tell future maintainers how to fix it: probably, by adding something to the forbidden list above.

rsmith updated this revision to Diff 243048.Feb 6 2020, 4:40 PM
rsmith marked 3 inline comments as done.

Extend assert comment to suggest likely remediations.

rjmccall accepted this revision.Feb 6 2020, 5:06 PM

Thanks, LGTM, assuming that we do indeed want to ban friends.

This revision is now accepted and ready to land.Feb 6 2020, 5:06 PM
rsmith updated this revision to Diff 243057.Feb 6 2020, 5:08 PM
rsmith marked an inline comment as done.

Add back a diagnostic for remaining cases that the new langauge rule doesn't handle.

rsmith added a comment.Feb 6 2020, 5:10 PM

Ugh, you mentioned template argument lists and made me realize we can still reach problem cases that way. And with array bounds. :(

I've added back in a diagnostic for the case where we compute the linkage too early for a "C-like" struct. Hopefully people won't hit it too much.

clang/lib/Sema/SemaDecl.cpp
4394

Hm. Now you come to mention it, I think friends might actually be fine -- or at least no worse than non-static data members -- from a linkage perspective.

The intended rule is described in P1766R1 section 2.3. If there are extensions that we permit in C structs, it would presumably be reasonable to permit them here too, but I would expect that C++-specific extensions should be disallowed here.

Okay, if the basic idea is to avoid anything that would need the linkage to be computed, that seems like exactly the right goal.

I know one of the awful ways to get an early reference to the anonymous type is to define a typedef of like a pointer to it, then use that in a second declarator, then try to give it a typedef-for-linkage-purposes in yet another declarator. I don't know of any way to get an expression whose type involves the anonymous type without a non-static member function or initializer or something like that.

This revision was automatically updated to reflect the committed changes.