This is an archive of the discontinued LLVM Phabricator instance.

[Sema] Validate large bitfields
Changes PlannedPublic

Authored by Mordante on Dec 6 2019, 12:23 PM.

Details

Summary

Note: I'm not entirely happy with the text of the diagnostics and I'm open to suggestions.

Fixes PR23505: Large bitfield: Assertion `getActiveBits() <= 64 && "Too many bits for uint64_t"' failed

Diff Detail

Event Timeline

Mordante created this revision.Dec 6 2019, 12:23 PM
aaron.ballman added inline comments.Dec 6 2019, 1:48 PM
clang/include/clang/Basic/DiagnosticSemaKinds.td
5186–5189

I feel like this situation should be an error rather than a warning -- what could the code possibly have meant?

clang/lib/Sema/SemaDecl.cpp
15845

too wide -> too-wide
bit-fields they -> bit-fields, they

rsmith added a comment.Dec 6 2019, 3:57 PM

It seems fine and reasonable to reject this as a violation of an implementation limit. Can we actually support the full range 2^64 bits range, or would it be wiser to pick a smaller limit? (There's at least no point in allowing bit-widths that would mean the size of the bitfield doesn't fit in size_t, which means no more than 35 bits for a 32-bit target.)

clang/include/clang/Basic/DiagnosticSemaKinds.td
5186–5189

The name of the diagnostic and the kind of diagnostic should agree. Currently we have warn_ vs Error<.

Mordante marked 3 inline comments as done.Dec 7 2019, 3:54 AM

I'll have a look whether I can find a sane maximum width for a bit-field.

I'll have a look whether I can find a sane maximum width for a bit-field.

The limits according to C are the size of the field's declared type (C17 6.7.2.1p4), but it seems that C++ decided it would make sense to turn the bits into padding bits (http://eel.is/c++draft/class.bit#1.sentence-6), so I guess a reasonable implementation limit would be SIZE_MAX for the target architecture (aka, sizeof(size_t) * CHAR_BIT bits).

clang/include/clang/Basic/DiagnosticSemaKinds.td
5186–5189

Ooof, good catch! These diagnostics should be renamed to start with err_ instead.

Mordante marked 2 inline comments as done.Dec 8 2019, 6:47 AM

Further testing revealed the Codegen already has decided the limit.
clang/lib/CodeGen/CGRecordLayout.h:64:

struct CGBitFieldInfo {
  /// The offset within a contiguous run of bitfields that are represented as
  /// a single "field" within the LLVM struct type. This offset is in bits.
  unsigned Offset : 16;

  /// The total size of the bit-field, in bits.
  unsigned Size : 15;

So I'll look at using that limit. I also want to look at improving the diagnostics a bit more.

clang/include/clang/Basic/DiagnosticSemaKinds.td
5186–5189

Hmm odd I'm sure I left a comment here yesterday, but it seems I didn't commit it properly.
It is a copy paste bug and I forgot to change the warn_ prefix to err_.

xbolva00 added a subscriber: xbolva00.EditedDec 8 2019, 7:04 AM

Maybe a bit offtopic, but it would be good to diagnose this case too:

enum A {a, b, c = 8};

struct T {
    enum A field : 2;
};

GCC catches this bug.

Mordante marked an inline comment as done.Dec 8 2019, 10:18 AM

Maybe a bit offtopic, but it would be good to diagnose this case too:

enum A {a, b, c = 8};

struct T {
    enum A field : 2;
};

GCC catches this bug.

I created https://bugs.llvm.org/show_bug.cgi?id=44251 and will look at adding this warning.

Any comments?

@rsmith @aaron.ballman

There are outstanding review comments, so I'm waiting for the patch author to address those, unless I've missed a question somewhere?

Mordante planned changes to this revision.Apr 7 2020, 11:53 AM

Any comments?

@rsmith @aaron.ballman

There are outstanding review comments, so I'm waiting for the patch author to address those, unless I've missed a question somewhere?

No I still need to address some issues, but I haven't found time for it yet.