[clang] [clang] Add clang::debug_info_type attribute for bitfields (PR #69104)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 18 12:36:12 PDT 2023
================
@@ -5910,6 +5910,30 @@ static void handleBuiltinAliasAttr(Sema &S, Decl *D,
D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident));
}
+static void handleDebugInfoTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!AL.hasParsedType()) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
+ return;
+ }
+
+ TypeSourceInfo *ParmTSI = nullptr;
+ QualType type = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI);
+ assert(ParmTSI && "no type source info for attribute argument");
+
+ if (type->isEnumeralType()) {
+ QualType BitfieldType = llvm::cast<FieldDecl>(D)->getType();
+ QualType EnumUnderlyingType =
+ type->getAs<EnumType>()->getDecl()->getIntegerType();
+ if (EnumUnderlyingType != BitfieldType) {
----------------
erichkeane wrote:
> A few things -- I think we should look at the canonical type so that we don't run into issues with typedefs. e.g.,
>
> ```
> enum E { Zero, One };
> typedef int Foo;
> struct S {
> [[clang::debug_info_type(E) Foo field : 1;
> };
> ```
>
> where the enum's underlying type is `int` but the bit-field's type is a typedef.
>
> Another case we should consider would be whether we want to allow signed unsigned mismatches, as in:
>
> ```
> enum E { Invalid = -1, ValidValue, OtherValidValue, YetAnotherValidValue };
> struct S {
> [[clang::debug_info_type(E) unsigned field : 3;
> };
> ```
>
> and only prevent situations where the specified type is not an enumeration or integral type.
This ALSO makes me wonder if forcing it to be an enum type is necessary. I can see potential value of a "OpaqueValueOfStruct" storage type thing, that perhaps we should just 'trust' that the user is doing something sensible with it.
I think in the signed/unsigned mismatch, we should allow it (thanks to the layout rules). That is, consider:
```
enum SIGNED {Invalid = -1, Valid };
enum UNSIGNED {Valid, INVALID = 0xF };
struct S {
[[attr_name(SIGNED)]]
unsigned SignedThing : 4;
[[attr_name(UNSIGNED)]]
unsigned UnsignedThing : 4;
};
```
They HAVE to be the same type else they don't get packed into the same byte, but you have 1 enum that can represent a negative value.
https://github.com/llvm/llvm-project/pull/69104
More information about the cfe-commits
mailing list