https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/69104
>From 976aa5c8f3d936a15e7123069a49d97ad3bf7a05 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Sun, 15 Oct 2023 13:14:55 +0300 Subject: [PATCH 1/3] [clang] Add clang::debug_info_type attribute --- clang/include/clang/Basic/Attr.td | 11 ++++++++ clang/include/clang/Basic/AttrDocs.td | 12 +++++++++ .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/CodeGen/CGDebugInfo.cpp | 2 ++ clang/lib/Sema/SemaDeclAttr.cpp | 26 +++++++++++++++++++ .../CodeGen/debug-info-debug-info-type.cpp | 14 ++++++++++ 6 files changed, 67 insertions(+) create mode 100644 clang/test/CodeGen/debug-info-debug-info-type.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 5c9eb7b8a981037..024421c0583c019 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -107,6 +107,10 @@ def NonBitField : SubsetSubject<Field, [{!S->isBitField()}], "non-bit-field non-static data members">; +def BitField : SubsetSubject<Field, + [{S->isBitField()}], + "bit-field non-static data members">; + def NonStaticCXXMethod : SubsetSubject<CXXMethod, [{!S->isStatic()}], "non-static member functions">; @@ -4264,3 +4268,10 @@ def CountedBy : InheritableAttr { void setCountedByFieldLoc(SourceRange Loc) { CountedByFieldLoc = Loc; } }]; } + +def DebugInfoType: InheritableAttr { + let Spellings = [Clang<"debug_info_type">]; + let Subjects = SubjectList<[BitField], ErrorDiag>; + let Args = [TypeArgument<"Type", 1>]; + let Documentation = [DebugInfoTypeDocumentation]; +} diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 9f9991bdae36155..6cceba1e0e0ad01 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -7219,6 +7219,18 @@ its underlying representation to be a WebAssembly ``funcref``. }]; } +def DebugInfoTypeDocumentation : Documentation { + let Category = DocCatField; + let Content = [{ +This attribute allows to alter type of a bitfield in debug information. +Such a need might arise when bitfield is intended to store an enumeration value, +but has to be specified as having enumeration's underlying type, in order to +facilitate compiler optimizations. But this also causes underlying type to be +emitted in debug information, making it hard for debuggers to map bitfield's +value back to enumeration. This attribute helps with this. + }]; +} + def CleanupDocs : Documentation { let Category = DocCatType; let Content = [{ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e85cd4d1a1ddc0d..b5c73494df367a6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3153,6 +3153,8 @@ def err_invalid_branch_protection_spec : Error< "invalid or misplaced branch protection specification '%0'">; def warn_unsupported_branch_protection_spec : Warning< "unsupported branch protection specification '%0'">, InGroup<BranchProtection>; +def warn_attribute_underlying_type_mismatch : Warning< + "underlying type %0 of enumeration %1 doesn't match bitfield type %2">; def warn_unsupported_target_attribute : Warning<"%select{unsupported|duplicate|unknown}0%select{| CPU|" diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index c73a63e12f03aab..85aedd87b21d41e 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1497,6 +1497,8 @@ CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl, llvm::DIScope *RecordTy, const RecordDecl *RD) { StringRef Name = BitFieldDecl->getName(); QualType Ty = BitFieldDecl->getType(); + if (BitFieldDecl->hasAttr<DebugInfoTypeAttr>()) + Ty = BitFieldDecl->getAttr<DebugInfoTypeAttr>()->getType(); SourceLocation Loc = BitFieldDecl->getLocation(); llvm::DIFile *VUnit = getOrCreateFile(Loc); llvm::DIType *DebugType = getOrCreateType(Ty, VUnit); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index feb02cad9080e3e..8d58968b7f985c8 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5910,6 +5910,28 @@ 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) { + S.Diag(AL.getLoc(), diag::warn_attribute_underlying_type_mismatch) << EnumUnderlyingType << type << BitfieldType; + return; + } + } + + D->addAttr(::new (S.Context) DebugInfoTypeAttr(S.Context, AL, ParmTSI)); +} + //===----------------------------------------------------------------------===// // Checker-specific attribute handlers. //===----------------------------------------------------------------------===// @@ -9629,6 +9651,10 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, handleBuiltinAliasAttr(S, D, AL); break; + case ParsedAttr::AT_DebugInfoType: + handleDebugInfoTypeAttr(S, D, AL); + break; + case ParsedAttr::AT_UsingIfExists: handleSimpleAttribute<UsingIfExistsAttr>(S, D, AL); break; diff --git a/clang/test/CodeGen/debug-info-debug-info-type.cpp b/clang/test/CodeGen/debug-info-debug-info-type.cpp new file mode 100644 index 000000000000000..6104ce7463ef918 --- /dev/null +++ b/clang/test/CodeGen/debug-info-debug-info-type.cpp @@ -0,0 +1,14 @@ +// RUN: %clang -target x86_64-linux -g -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -verify -DMISMATCH %s + +struct A { + enum E : unsigned {}; + [[clang::debug_info_type(E)]] unsigned b : 2; +#ifdef MISMATCH + [[clang::debug_info_type(E)]] int b2 : 2; + // expected-warning@-1 {{underlying type 'unsigned int' of enumeration 'E' doesn't match bitfield type 'int'}} +#endif +} a; + +// CHECK-DAG: [[ENUM:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E"{{.*}} +// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "b",{{.*}} baseType: [[ENUM]] \ No newline at end of file >From 4330b70c2fde70010f1caabbf6562b61c701ef7e Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Sun, 15 Oct 2023 13:34:09 +0300 Subject: [PATCH 2/3] Add newline to the test --- clang/test/CodeGen/debug-info-debug-info-type.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CodeGen/debug-info-debug-info-type.cpp b/clang/test/CodeGen/debug-info-debug-info-type.cpp index 6104ce7463ef918..4b60d1b64be239f 100644 --- a/clang/test/CodeGen/debug-info-debug-info-type.cpp +++ b/clang/test/CodeGen/debug-info-debug-info-type.cpp @@ -11,4 +11,4 @@ struct A { } a; // CHECK-DAG: [[ENUM:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E"{{.*}} -// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "b",{{.*}} baseType: [[ENUM]] \ No newline at end of file +// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "b",{{.*}} baseType: [[ENUM]] >From faf8238ae2a6362214e8176e4b9b7225fa7c8bd1 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Sun, 15 Oct 2023 13:55:13 +0300 Subject: [PATCH 3/3] Run clang-format --- clang/lib/Sema/SemaDeclAttr.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8d58968b7f985c8..294a73d2abf2d29 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5922,9 +5922,11 @@ static void handleDebugInfoTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (type->isEnumeralType()) { QualType BitfieldType = llvm::cast<FieldDecl>(D)->getType(); - QualType EnumUnderlyingType = type->getAs<EnumType>()->getDecl()->getIntegerType(); + QualType EnumUnderlyingType = + type->getAs<EnumType>()->getDecl()->getIntegerType(); if (EnumUnderlyingType != BitfieldType) { - S.Diag(AL.getLoc(), diag::warn_attribute_underlying_type_mismatch) << EnumUnderlyingType << type << BitfieldType; + S.Diag(AL.getLoc(), diag::warn_attribute_underlying_type_mismatch) + << EnumUnderlyingType << type << BitfieldType; return; } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits