eddyz87 created this revision.
Herald added a subscriber: hiraditya.
Herald added a project: All.
eddyz87 updated this revision to Diff 497835.
eddyz87 added a comment.
eddyz87 retitled this revision from "[DebugInfo][BPF] 'annotations' on a target 
type to represent btf_type_tag" to "[DebugInfo][BPF] Add 'btf_type_tag:v2' 
annotation in DWARF".
eddyz87 edited the summary of this revision.
eddyz87 updated this revision to Diff 499281.
eddyz87 edited the summary of this revision.
eddyz87 updated this revision to Diff 502033.
eddyz87 edited the summary of this revision.
eddyz87 retitled this revision from "[DebugInfo][BPF] Add 'btf_type_tag:v2' 
annotation in DWARF" to "[DebugInfo][BPF] Add 'btf:type_tag' annotation in 
DWARF".
eddyz87 updated this revision to Diff 502321.
eddyz87 updated this revision to Diff 503198.
eddyz87 updated this revision to Diff 504493.
eddyz87 published this revision for review.
eddyz87 added reviewers: yonghong-song, echristo, dblaikie.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

- Removed DWARF tag 0x6001, use 'btf_type_tag:v2' name instead.
- Removed CopyBTFTypeTags pass, generate 'btf_type_tag' and 'btf_type_tag:v2' 
in `CGDebugInfo` instead.
- Added tests for BTF deduplication logic for debug info types that differ only 
in annotations.


yonghong-song added a comment.

When I tried to build llvm with the patch, I hit the following errors:

  [2198/3751] Building CXX object 
lib/Target/BPF/CMakeFiles/LLVMBPFCodeGen.dir/BTFDebug.cpp.o
  FAILED: lib/Target/BPF/CMakeFiles/LLVMBPFCodeGen.dir/BTFDebug.cpp.o 
  /bin/c++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE 
-D_LIBCPP_ENABLE_ASSERTIONS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS 
-D__STDC_LIMIT_MACROS -Ilib/Target/BPF -I../lib/Target/BPF -Iinclude 
-I../include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden 
-Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings 
-Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long 
-Wimplicit-fallthrough -Wno-maybe-uninitialized -Wno-class-memaccess 
-Wno-noexcept-type -Wdelete-non-virtual-dtor -Wno-comment 
-Wno-misleading-indentation -fdiagnostics-color -ffunction-sections 
-fdata-sections -O3 -DNDEBUG -fvisibility=hidden  -fno-exceptions -fno-rtti 
-UNDEBUG -std=c++17 -MD -MT 
lib/Target/BPF/CMakeFiles/LLVMBPFCodeGen.dir/BTFDebug.cpp.o -MF 
lib/Target/BPF/CMakeFiles/LLVMBPFCodeGen.dir/BTFDebug.cpp.o.d -o 
lib/Target/BPF/CMakeFiles/LLVMBPFCodeGen.dir/BTFDebug.cpp.o -c 
../lib/Target/BPF/BTFDebug.cpp
  ../lib/Target/BPF/BTFDebug.cpp: In function ‘llvm::DINodeArray 
lookupAnnotations(const llvm::DIType*)’:
  ../lib/Target/BPF/BTFDebug.cpp:516:21: error: ‘const class llvm::DIBasicType’ 
has no member named ‘getAnnotations’; did you mean ‘getEncoding’?
       Annots = SubTy->getAnnotations();
                       ^~~~~~~~~~~~~~
                       getEncoding
  ../lib/Target/BPF/BTFDebug.cpp:522:21: error: ‘const class 
llvm::DISubroutineType’ has no member named ‘getAnnotations’
       Annots = SubTy->getAnnotations();
                       ^~~~~~~~~~~~~~
  [2272/3751] Building CXX object 
lib/Passes/CMakeFiles/LLVMPasses.dir/PassBuilderPipelines.cpp.o
  In file included from ../lib/Passes/PassBuilderPipelines.cpp:113:
  ../include/llvm/Transforms/Scalar/SROA.h:95:7: warning: ‘llvm::SROAPass’ 
declared with greater visibility than the type of its field 
‘llvm::SROAPass::SelectsToRewrite’ [-Wattributes]
   class SROAPass : public PassInfoMixin<SROAPass> {
         ^~~~~~~~
  [2279/3751] Building CXX object 
lib/Passes/CMakeFiles/LLVMPasses.dir/PassBuilder.cpp.o
  In file included from ../lib/Passes/PassBuilder.cpp:214:
  ../include/llvm/Transforms/Scalar/SROA.h:95:7: warning: ‘llvm::SROAPass’ 
declared with greater visibility than the type of its field 
‘llvm::SROAPass::SelectsToRewrite’ [-Wattributes]
   class SROAPass : public PassInfoMixin<SROAPass> {
         ^~~~~~~~
  ninja: build stopped: subcommand failed.
  [yhs@devbig309.ftw3 ~/work/llvm-project/llvm/build (main)]$

The top commit is

  959216f9b1f1  [AMDGPU] MIR-Tests for Multiplication using KBA

Could you take a look?

My cmake command line:

  cmake .. -DCMAKE_BUILD_TYPE=Release -G Ninja \
      -DLLVM_ENABLE_PROJECTS="clang;lld" \
      -DLLVM_TARGETS_TO_BUILD="BPF;X86" \
      -DLLVM_ENABLE_ASSERTIONS=ON \
      -DLLVM_ENABLE_ZLIB=ON \
      -DCMAKE_INSTALL_PREFIX=$PWD/install


eddyz87 added a comment.

> ../lib/Target/BPF/BTFDebug.cpp: In function ‘llvm::DINodeArray 
> lookupAnnotations(const llvm::DIType*)’:
> ../lib/Target/BPF/BTFDebug.cpp:516:21: error: ‘const class llvm::DIBasicType’ 
> has no member named ‘getAnnotations’; did you mean ‘getEncoding’?
>
>   Annots = SubTy->getAnnotations();
>                   ^~~~~~~~~~~~~~
>                   getEncoding
>
> ../lib/Target/BPF/BTFDebug.cpp:522:21: error: ‘const class 
> llvm::DISubroutineType’ has no member named ‘getAnnotations’
>
>   Annots = SubTy->getAnnotations();
>                   ^~~~~~~~~~~~~~

Hi Yonghong,

Looking at the error it seems that you applied only the changes from D143967 
<https://reviews.llvm.org/D143967>, however it depends on D143966 
<https://reviews.llvm.org/D143966>. I organized these two as a stack to 
simplify the review:

- D143966 <https://reviews.llvm.org/D143966> adds annotations attribute for 
`DIBasicType` and `DISubroutineType`;
- D143967 <https://reviews.llvm.org/D143967> adds logic for `btf_type_tag:v2` 
generation.

Anyways, I've rebased the revisions against current main (dad3741e3bdc 
<https://reviews.llvm.org/rGdad3741e3bdc6e126c5b3adec9242d7b2d926282> [PowerPC] 
clang-format isPPC64ELFv2ABI() function. NFC) and see one failing test for 
`ninja check-all` target:

  Failed Tests (1):
    Clang :: CodeGen/dwarf-version.c

However, it fails without my changes as well.
I'll push the rebased revisions shortly.


eddyz87 added a comment.

Rebase


eddyz87 added a comment.

Rebase, change for tag name from btf_type_tag:v2 to btf:type_tag.


eddyz87 added a comment.

Another rebase, hope to fix windows build issue.


eddyz87 added a comment.

Fix support for cyclic types

Update to handle situations like below:

  struct bravo {
    struct bravo __tag(a) * a;
  } g;

During DI construction annotations are now represneted by
"annotation placeholders", special kind of derived type.
These placeholders are replaced by actual types with
proper "annotations" field in CGDebugInfo::finalize().


eddyz87 added a comment.

- BTFDebug changes moved to a separate revision (to simplify the review);
- Added test case for circular type reference handling.


This commit is a follow-up for discussion at Kernel BPF mailing list 
<https://lore.kernel.org/bpf/87r0w9jjoq....@oracle.com/>, it changes the way 
`__attribute__((btf_type_tag("...")))`s are represented in DWARF.

Prior to this commit type tags could only be attached to pointers. Such 
attachments associated the tags with a pointee type. E.g. for the following C 
code:

  int __attribute__((btf_type_tag("tag1"))) *g;

Generated DWARF looked as follows:

  0x0000001e:   DW_TAG_variable
                  DW_AT_name      ("g")
                  DW_AT_type      (0x00000029 "int *")
  
  0x00000029:   DW_TAG_pointer_type
                  DW_AT_type      (0x00000032 "int")
  
  0x0000002e:     DW_TAG_LLVM_annotation
                    DW_AT_name    ("btf_type_tag")
                    DW_AT_const_value     ("tag1")
  
  0x00000032:   DW_TAG_base_type
                  DW_AT_name      ("int")

The goal of this commit is to allow attachment of type tags to the tagged types 
instead. E.g. for the same example DWARF should look as follows:

  0x0000001e:   DW_TAG_variable
                  DW_AT_name      ("g")
                  DW_AT_type      (0x00000029 "int *")
  
  0x00000029:   DW_TAG_pointer_type
                  DW_AT_type      (0x00000032 "int")
  
  0x00000032:   DW_TAG_base_type
                  DW_AT_name      ("int")
  
  0x00000036:     DW_TAG_LLVM_annotation
                    DW_AT_name    ("btf:type_tag")
                    DW_AT_const_value     ("tag1")

A new tag name, `btf:type_tag`, is used so that DWARF consumers could 
distinguish between old and new attachment semantics.

In order to preserve backwards compatibility both `btf_type_tag` and 
`btf:type_tag` are generated. `btf_type_tag` might be deprecated in the future.

The commit includes the following changes:

- New overload for `CGDebugInfo::CreateType` method is added. This overload is 
responsible for creation of `DIBasicType`, `DICompositeType`, `DIDerivedType`, 
`DISubroutineType` entries with `annotations` fields describing attached BTF 
type tags. Generated annotations use `btf:type_tag` field name.

  llvm::DIType *CGDebugInfo::CreateType(const BTFTagAttributedType *Ty,
                                        llvm::DIFile *Unit);



- `ASTContext::getBTFTagAttributedType()` is updated to ensure that 
`BTFTagAttributedType` always wraps `QualType` w/o local 
constant/volatile/restricted qualifiers. This simplifies debug info generation.

- `BTFDebug` is updated to handle BTF type tags attached to non-pointer types:
  - The logic for `BTFTypeTypeTag` chains creation is moved to 
`BTFDebug::addType()`;
  - Special logic is added to avoid duplicate BTF entries for tagged and 
un-tagged type variants. Debug information generated for this example contains 
three instances of `DICompositeType(name: "foo")` with different `annotations` 
fields, however single BTF definition for structure "foo" should be generated. 
Field `BTFDebug::DIDedupMap` and method `BTFDebug::lookupType()` are 
responsible for this logic. E.g. this is useful in the following case:

  #define __tag1 __attribute__((btf_type_tag("tag1")))
  #define __tag2 __attribute__((btf_type_tag("tag2")))
  
  struct foo {};
  
  struct bar {
    struct foo __tag1 aa;
    struct foo __tag2 bb;
    struct foo cc;
  };


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D143967

Files:
  clang/lib/AST/ASTContext.cpp
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/CodeGen/CGDebugInfo.h
  clang/test/CodeGen/attr-btf_type_tag-circular.c
  clang/test/CodeGen/attr-btf_type_tag-func-ptr.c
  clang/test/CodeGen/attr-btf_type_tag-func.c
  clang/test/CodeGen/attr-btf_type_tag-similar-type.c
  clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
  clang/test/CodeGen/attr-btf_type_tag-var.c
  clang/test/CodeGen/attr-btf_type_tag-void.c
  llvm/include/llvm/IR/DIBuilder.h
  llvm/lib/IR/DIBuilder.cpp

Index: llvm/lib/IR/DIBuilder.cpp
===================================================================
--- llvm/lib/IR/DIBuilder.cpp
+++ llvm/lib/IR/DIBuilder.cpp
@@ -353,6 +353,17 @@
                             Annotations);
 }
 
+DIDerivedType *
+DIBuilder::createAnnotationsPlaceholder(DIType *Ty, DINodeArray Annotations) {
+  auto *RetTy =
+      DIDerivedType::getTemporary(
+          VMContext, dwarf::DW_TAG_LLVM_annotation, "", nullptr, 0, nullptr, Ty,
+          0, 0, 0, std::nullopt, DINode::FlagZero, nullptr, Annotations)
+          .release();
+  trackIfUnresolved(RetTy);
+  return RetTy;
+}
+
 DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) {
   assert(Ty && "Invalid type!");
   assert(FriendTy && "Invalid friend type!");
Index: llvm/include/llvm/IR/DIBuilder.h
===================================================================
--- llvm/include/llvm/IR/DIBuilder.h
+++ llvm/include/llvm/IR/DIBuilder.h
@@ -284,6 +284,9 @@
                                  DINode::DIFlags Flags = DINode::FlagZero,
                                  DINodeArray Annotations = nullptr);
 
+    DIDerivedType *createAnnotationsPlaceholder(DIType *Ty,
+                                                DINodeArray Annotations);
+
     /// Create debugging information entry for a 'friend'.
     DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy);
 
Index: clang/test/CodeGen/attr-btf_type_tag-void.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-btf_type_tag-void.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+void __tag1 *g;
+
+// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true)
+// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L2:[0-9]+]], size: [[#]], annotations: ![[L3:[0-9]+]])
+// CHECK: ![[L2]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "void", annotations: ![[L4:[0-9]+]])
+// CHECK: ![[L4]] = !{![[L5:[0-9]+]]}
+// CHECK: ![[L5]] = !{!"btf:type_tag", !"tag1"}
+// CHECK: ![[L3]] = !{![[L6:[0-9]+]]}
+// CHECK: ![[L6]] = !{!"btf_type_tag", !"tag1"}
Index: clang/test/CodeGen/attr-btf_type_tag-var.c
===================================================================
--- clang/test/CodeGen/attr-btf_type_tag-var.c
+++ clang/test/CodeGen/attr-btf_type_tag-var.c
@@ -21,23 +21,32 @@
 const int __tag1 __tag2 volatile * const __tag3  __tag4  volatile * __tag5  __tag6 const volatile * g;
 #endif
 
-// CHECK:  distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L6:[0-9]+]]
-// CHECK:  ![[L6]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L7:[0-9]+]], size: [[#]], annotations: ![[L22:[0-9]+]]
-// CHECK:  ![[L7]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L8:[0-9]+]]
-// CHECK:  ![[L8]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L9:[0-9]+]]
-// CHECK:  ![[L9]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L10:[0-9]+]], size: [[#]], annotations: ![[L19:[0-9]+]]
-// CHECK:  ![[L10]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L11:[0-9]+]]
-// CHECK:  ![[L11]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L12:[0-9]+]]
-// CHECK:  ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L16:[0-9]+]]
-// CHECK:  ![[L13]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L14:[0-9]+]]
-// CHECK:  ![[L14]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L15:[0-9]+]]
-// CHECK:  ![[L15]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed
-// CHECK:  ![[L16]] = !{![[L17:[0-9]+]], ![[L18:[0-9]+]]}
-// CHECK:  ![[L17]] = !{!"btf_type_tag", !"tag1"}
-// CHECK:  ![[L18]] = !{!"btf_type_tag", !"tag2"}
-// CHECK:  ![[L19]] = !{![[L20:[0-9]+]], ![[L21:[0-9]+]]}
-// CHECK:  ![[L20]] = !{!"btf_type_tag", !"tag3"}
-// CHECK:  ![[L21]] = !{!"btf_type_tag", !"tag4"}
-// CHECK:  ![[L22]] = !{![[L23:[0-9]+]], ![[L24:[0-9]+]]}
-// CHECK:  ![[L23]] = !{!"btf_type_tag", !"tag5"}
-// CHECK:  ![[L24]] = !{!"btf_type_tag", !"tag6"}
+// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L01:[0-9]+]], isLocal: false, isDefinition: true)
+// CHECK: ![[L01]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L02:[0-9]+]], size: [[#]], annotations: ![[L03:[0-9]+]])
+// CHECK: ![[L02]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L04:[0-9]+]], annotations: ![[L05:[0-9]+]])
+// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L06:[0-9]+]])
+// CHECK: ![[L06]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L07:[0-9]+]], size: [[#]], annotations: ![[L08:[0-9]+]])
+// CHECK: ![[L07]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L09:[0-9]+]], annotations: ![[L10:[0-9]+]])
+// CHECK: ![[L09]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L11:[0-9]+]])
+// CHECK: ![[L11]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L12:[0-9]+]], size: [[#]], annotations: ![[L13:[0-9]+]])
+// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L14:[0-9]+]], annotations: ![[L15:[0-9]+]])
+// CHECK: ![[L14]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L16:[0-9]+]])
+// CHECK: ![[L16]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed)
+// CHECK: ![[L15]] = !{![[L17:[0-9]+]], ![[L18:[0-9]+]]}
+// CHECK: ![[L17]] = !{!"btf:type_tag", !"tag1"}
+// CHECK: ![[L18]] = !{!"btf:type_tag", !"tag2"}
+// CHECK: ![[L13]] = !{![[L19:[0-9]+]], ![[L20:[0-9]+]]}
+// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L20]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: ![[L10]] = !{![[L21:[0-9]+]], ![[L22:[0-9]+]]}
+// CHECK: ![[L21]] = !{!"btf:type_tag", !"tag3"}
+// CHECK: ![[L22]] = !{!"btf:type_tag", !"tag4"}
+// CHECK: ![[L08]] = !{![[L23:[0-9]+]], ![[L24:[0-9]+]]}
+// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag3"}
+// CHECK: ![[L24]] = !{!"btf_type_tag", !"tag4"}
+// CHECK: ![[L05]] = !{![[L25:[0-9]+]], ![[L26:[0-9]+]]}
+// CHECK: ![[L25]] = !{!"btf:type_tag", !"tag5"}
+// CHECK: ![[L26]] = !{!"btf:type_tag", !"tag6"}
+// CHECK: ![[L03]] = !{![[L27:[0-9]+]], ![[L28:[0-9]+]]}
+// CHECK: ![[L27]] = !{!"btf_type_tag", !"tag5"}
+// CHECK: ![[L28]] = !{!"btf_type_tag", !"tag6"}
Index: clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
===================================================================
--- clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
+++ clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
@@ -14,22 +14,27 @@
   return (int *)a1->c;
 }
 
-// CHECK: ![[L4:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L16:[0-9]+]])
-// CHECK: ![[L16]] = !{![[L17:[0-9]+]], ![[L24:[0-9]+]], ![[L31:[0-9]+]]}
-// CHECK: ![[L17]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L18:[0-9]+]], size: [[#]])
-// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L19:[0-9]+]], size: [[#]], annotations: ![[L22:[0-9]+]])
-// CHECK: ![[L19]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L4]], size: [[#]], annotations: ![[L20:[0-9]+]])
-// CHECK: ![[L20]] = !{![[L21:[0-9]+]]}
-// CHECK: ![[L21]] = !{!"btf_type_tag", !"tag1"}
-// CHECK: ![[L22]] = !{![[L23:[0-9]+]]}
-// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag2"}
-// CHECK: ![[L24]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L25:[0-9]+]]
-// CHECK: ![[L25]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn2_t", file: ![[#]], line: [[#]], baseType: ![[L26:[0-9]+]])
-// CHECK: ![[L26]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L27:[0-9]+]], size: [[#]], annotations: ![[L30:[0-9]+]])
-// CHECK: ![[L27]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L28:[0-9]+]])
-// CHECK: ![[L28]] = !DISubroutineType(types: ![[L29:[0-9]+]])
-// CHECK: ![[L29]] = !{null, ![[L4]]}
-// CHECK: ![[L30]] = !{![[L21]], ![[L23]]}
-// CHECK: ![[L31]] = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#]], file: ![[#]], line: [[#]]1, baseType: ![[L32:[0-9]+]]
-// CHECK: ![[L32]] = !DIBasicType(name: "long", size: [[#]], encoding: DW_ATE_signed)
+// CHECK: ![[L01:[0-9]+]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed)
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L02:[0-9]+]])
+// CHECK: ![[L02]] = !{![[L03:[0-9]+]], ![[L04:[0-9]+]], ![[L05:[0-9]+]]}
+// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L06:[0-9]+]], size: [[#]])
+// CHECK: ![[L06]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L07:[0-9]+]], size: [[#]], annotations: ![[L08:[0-9]+]])
+// CHECK: ![[L07]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L09:[0-9]+]], size: [[#]], annotations: ![[L10:[0-9]+]])
+// CHECK: ![[L09]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L11:[0-9]+]])
+// CHECK: ![[L11]] = !{![[L12:[0-9]+]]}
+// CHECK: ![[L12]] = !{!"btf:type_tag", !"tag1"}
+// CHECK: ![[L10]] = !{![[L13:[0-9]+]], ![[L14:[0-9]+]]}
+// CHECK: ![[L13]] = !{!"btf:type_tag", !"tag2"}
+// CHECK: ![[L14]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L08]] = !{![[L15:[0-9]+]]}
+// CHECK: ![[L15]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L16:[0-9]+]], size: [[#]], offset: [[#]])
+// CHECK: ![[L16]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn2_t", file: ![[#]], line: [[#]], baseType: ![[L17:[0-9]+]])
+// CHECK: ![[L17]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L18:[0-9]+]], size: [[#]], annotations: ![[L19:[0-9]+]])
+// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L20:[0-9]+]], annotations: ![[L21:[0-9]+]])
+// CHECK: ![[L20]] = !DISubroutineType(types: ![[L22:[0-9]+]])
+// CHECK: ![[L22]] = !{null, ![[L01]]}
+// CHECK: ![[L21]] = !{![[L12]], ![[L13]]}
+// CHECK: ![[L19]] = !{![[L14]], ![[L15]]}
+// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L23:[0-9]+]], size: [[#]], offset: [[#]])
+// CHECK: ![[L23]] = !DIBasicType(name: "long", size: [[#]], encoding: DW_ATE_signed)
Index: clang/test/CodeGen/attr-btf_type_tag-similar-type.c
===================================================================
--- clang/test/CodeGen/attr-btf_type_tag-similar-type.c
+++ clang/test/CodeGen/attr-btf_type_tag-similar-type.c
@@ -12,15 +12,23 @@
         return *arg->a;
 }
 
-// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_value", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L14:[0-9]+]]
-// CHECK: ![[L14]] = !{![[L15:[0-9]+]], ![[L20:[0-9]+]]}
-// CHECK: ![[L15]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L16:[0-9]+]]
-// CHECK: ![[L16]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L17:[0-9]+]]
-// CHECK: ![[L17]] = !{![[L18:[0-9]+]], ![[L19:[0-9]+]]}
-// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag1"}
-// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag3"}
-// CHECK: ![[L20]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L21:[0-9]+]]
-// CHECK: ![[L21:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L22:[0-9]+]]
-// CHECK: ![[L22]] = !{![[L23:[0-9]+]], ![[L24:[0-9]+]]}
-// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag2"}
-// CHECK: ![[L24]] = !{!"btf_type_tag", !"tag4"}
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_value", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L01:[0-9]+]])
+// CHECK: ![[L01]] = !{![[L02:[0-9]+]], ![[L03:[0-9]+]]}
+// CHECK: ![[L02]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L04:[0-9]+]], size: [[#]])
+// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L05:[0-9]+]], size: [[#]], annotations: ![[L06:[0-9]+]])
+// CHECK: ![[L05]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L07:[0-9]+]])
+// CHECK: ![[L07]] = !{![[L08:[0-9]+]], ![[L09:[0-9]+]]}
+// CHECK: ![[L08]] = !{!"btf:type_tag", !"tag1"}
+// CHECK: ![[L09]] = !{!"btf:type_tag", !"tag3"}
+// CHECK: ![[L06]] = !{![[L10:[0-9]+]], ![[L11:[0-9]+]]}
+// CHECK: ![[L10]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L11]] = !{!"btf_type_tag", !"tag3"}
+// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L12:[0-9]+]], size: [[#]], offset: [[#]])
+// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L14:[0-9]+]])
+// CHECK: ![[L13]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L15:[0-9]+]])
+// CHECK: ![[L15]] = !{![[L16:[0-9]+]], ![[L17:[0-9]+]]}
+// CHECK: ![[L16]] = !{!"btf:type_tag", !"tag2"}
+// CHECK: ![[L17]] = !{!"btf:type_tag", !"tag4"}
+// CHECK: ![[L14]] = !{![[L18:[0-9]+]], ![[L19:[0-9]+]]}
+// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag4"}
Index: clang/test/CodeGen/attr-btf_type_tag-func.c
===================================================================
--- clang/test/CodeGen/attr-btf_type_tag-func.c
+++ clang/test/CodeGen/attr-btf_type_tag-func.c
@@ -15,14 +15,17 @@
 
 int __tag1 * __tag2 *foo(int __tag1 * __tag2 *arg) { return arg; }
 
-// CHECK: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L9:[0-9]+]]
-// CHECK: ![[L9]] = !DISubroutineType(types: ![[L10:[0-9]+]]
-// CHECK: ![[L10]] = !{![[L11:[0-9]+]], ![[L11]]}
-// CHECK: ![[L11]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L12:[0-9]+]], size: [[#]], annotations: ![[L16:[0-9]+]]
-// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L14:[0-9]+]]
-// CHECK: ![[L13]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed
-// CHECK: ![[L14]] = !{![[L15:[0-9]+]]}
-// CHECK: ![[L15]] = !{!"btf_type_tag", !"tag1"}
-// CHECK: ![[L16]] = !{![[L17:[0-9]+]]}
-// CHECK: ![[L17]] = !{!"btf_type_tag", !"tag2"}
-// CHECK: !DILocalVariable(name: "arg", arg: 1, scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L11]])
+// CHECK: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L01:[0-9]+]], {{.*}})
+// CHECK: ![[L01]] = !DISubroutineType(types: ![[L02:[0-9]+]])
+// CHECK: ![[L02]] = !{![[L03:[0-9]+]], ![[L03]]}
+// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L04:[0-9]+]], size: [[#]], annotations: ![[L05:[0-9]+]])
+// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], size: [[#]], annotations: ![[L07:[0-9]+]])
+// CHECK: ![[L06]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L08:[0-9]+]])
+// CHECK: ![[L08]] = !{![[L09:[0-9]+]]}
+// CHECK: ![[L09]] = !{!"btf:type_tag", !"tag1"}
+// CHECK: ![[L07]] = !{![[L10:[0-9]+]], ![[L11:[0-9]+]]}
+// CHECK: ![[L10]] = !{!"btf:type_tag", !"tag2"}
+// CHECK: ![[L11]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L05]] = !{![[L12:[0-9]+]]}
+// CHECK: ![[L12]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: !DILocalVariable(name: "arg", arg: 1, scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L03]])
Index: clang/test/CodeGen/attr-btf_type_tag-func-ptr.c
===================================================================
--- clang/test/CodeGen/attr-btf_type_tag-func-ptr.c
+++ clang/test/CodeGen/attr-btf_type_tag-func-ptr.c
@@ -8,8 +8,10 @@
   return arg->a;
 }
 
-// CHECK:      !DIDerivedType(tag: DW_TAG_member, name: "f"
-// CHECK-SAME: baseType: ![[L18:[0-9]+]]
-// CHECK:      ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L21:[0-9]+]])
-// CHECK:      ![[L21]] = !{![[L22:[0-9]+]]}
-// CHECK:      ![[L22]] = !{!"btf_type_tag", !"rcu"}
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L1:[0-9]+]], size: [[#]])
+// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L2:[0-9]+]], size: [[#]], annotations: ![[L3:[0-9]+]])
+// CHECK: ![[L2]] = !DISubroutineType(types: ![[#]], annotations: ![[L4:[0-9]+]])
+// CHECK: ![[L4]] = !{![[L5:[0-9]+]]}
+// CHECK: ![[L5]] = !{!"btf:type_tag", !"rcu"}
+// CHECK: ![[L3]] = !{![[L6:[0-9]+]]}
+// CHECK: ![[L6]] = !{!"btf_type_tag", !"rcu"}
Index: clang/test/CodeGen/attr-btf_type_tag-circular.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-btf_type_tag-circular.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+
+struct st {
+  struct st __tag1 *self;
+} g;
+
+// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true)
+// CHECK: ![[L1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "st", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L2:[0-9]+]])
+// CHECK: ![[L2]] = !{![[L3:[0-9]+]]}
+// CHECK: ![[L3]] = !DIDerivedType(tag: DW_TAG_member, name: "self", scope: ![[L1]], file: ![[#]], line: [[#]], baseType: ![[L4:[0-9]+]], size: [[#]])
+// CHECK: ![[L4]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L5:[0-9]+]], size: [[#]], annotations: ![[L6:[0-9]+]])
+// CHECK: ![[L5]] = !DICompositeType(tag: DW_TAG_structure_type, name: "st", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L2]], annotations: ![[L7:[0-9]+]])
+// CHECK: ![[L7]] = !{![[L8:[0-9]+]]}
+// CHECK: ![[L8]] = !{!"btf:type_tag", !"tag1"}
+// CHECK: ![[L6]] = !{![[L9:[0-9]+]]}
+// CHECK: ![[L9]] = !{!"btf_type_tag", !"tag1"}
Index: clang/lib/CodeGen/CGDebugInfo.h
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.h
+++ clang/lib/CodeGen/CGDebugInfo.h
@@ -173,6 +173,8 @@
   /// The key is coroutine real parameters, value is DIVariable in LLVM IR.
   Param2DILocTy ParamDbgMappings;
 
+  std::vector<llvm::DIDerivedType *> AnnotationPlaceholders;
+
   /// Helper functions for getOrCreateType.
   /// @{
   /// Currently the checksum of an interface includes the number of
@@ -212,6 +214,8 @@
   llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
   llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
   llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
+  llvm::DIType *CreateType(const BTFTagAttributedType *Ty,
+                           Qualifiers Qualifiers, llvm::DIFile *F);
   /// Get enumeration type.
   llvm::DIType *CreateEnumType(const EnumType *Ty);
   llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1173,6 +1173,50 @@
   return RetTy;
 }
 
+static QualType collectBTFTypeTagAnnotations(
+    llvm::LLVMContext &Context, llvm::DIBuilder &DBuilder,
+    llvm::SmallVectorImpl<llvm::Metadata *> &Annots,
+    const BTFTagAttributedType *BTFAttrTy, const char *TagName) {
+  QualType WrappedTy;
+
+  do {
+    StringRef TagValue = BTFAttrTy->getAttr()->getBTFTypeTag();
+    if (!TagValue.empty()) {
+      llvm::Metadata *Ops[] = {
+          llvm::MDString::get(Context, TagName),
+          llvm::MDString::get(Context, TagValue),
+      };
+      Annots.insert(Annots.begin(), llvm::MDNode::get(Context, Ops));
+    }
+    WrappedTy = BTFAttrTy->getWrappedType();
+    BTFAttrTy = dyn_cast<BTFTagAttributedType>(WrappedTy);
+  } while (BTFAttrTy);
+
+  return WrappedTy;
+}
+
+llvm::DIType *CGDebugInfo::CreateType(const BTFTagAttributedType *Ty,
+                                      Qualifiers Qualifiers,
+                                      llvm::DIFile *Unit) {
+  SmallVector<llvm::Metadata *, 4> Annotations;
+  ASTContext &C = CGM.getContext();
+  auto WrappedTy = collectBTFTypeTagAnnotations(
+      CGM.getLLVMContext(), DBuilder, Annotations, Ty, "btf:type_tag");
+  WrappedTy = C.getQualifiedType(WrappedTy, Qualifiers);
+  llvm::DIType *WrappedDI = getOrCreateType(WrappedTy, Unit);
+  if (Annotations.size() == 0)
+    return WrappedDI;
+
+  if (WrappedDI == nullptr)
+    WrappedDI = DBuilder.createUnspecifiedType("void");
+
+  auto *Placeholder = DBuilder.createAnnotationsPlaceholder(
+      WrappedDI, DBuilder.getOrCreateArray(Annotations));
+  AnnotationPlaceholders.push_back(Placeholder);
+
+  return Placeholder;
+}
+
 llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
                                                  const Type *Ty,
                                                  QualType PointeeTy,
@@ -1185,32 +1229,23 @@
       CGM.getTarget().getDWARFAddressSpace(
           CGM.getTypes().getTargetAddressSpace(PointeeTy));
 
-  SmallVector<llvm::Metadata *, 4> Annots;
-  auto *BTFAttrTy = dyn_cast<BTFTagAttributedType>(PointeeTy);
-  while (BTFAttrTy) {
-    StringRef Tag = BTFAttrTy->getAttr()->getBTFTypeTag();
-    if (!Tag.empty()) {
-      llvm::Metadata *Ops[2] = {
-          llvm::MDString::get(CGM.getLLVMContext(), StringRef("btf_type_tag")),
-          llvm::MDString::get(CGM.getLLVMContext(), Tag)};
-      Annots.insert(Annots.begin(),
-                    llvm::MDNode::get(CGM.getLLVMContext(), Ops));
-    }
-    BTFAttrTy = dyn_cast<BTFTagAttributedType>(BTFAttrTy->getWrappedType());
-  }
-
   llvm::DINodeArray Annotations = nullptr;
-  if (Annots.size() > 0)
-    Annotations = DBuilder.getOrCreateArray(Annots);
+  if (auto *BTFAttrTy =
+          dyn_cast<BTFTagAttributedType>(PointeeTy.getTypePtr())) {
+    SmallVector<llvm::Metadata *, 4> AnnotationsVec;
+    collectBTFTypeTagAnnotations(CGM.getLLVMContext(), DBuilder, AnnotationsVec,
+                                 BTFAttrTy, "btf_type_tag");
+    Annotations = DBuilder.getOrCreateArray(AnnotationsVec);
+  }
 
   if (Tag == llvm::dwarf::DW_TAG_reference_type ||
       Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
     return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit),
                                         Size, Align, DWARFAddressSpace);
-  else
-    return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
-                                      Align, DWARFAddressSpace, StringRef(),
-                                      Annotations);
+
+  return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
+                                    Align, DWARFAddressSpace, StringRef(),
+                                    Annotations);
 }
 
 llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
@@ -3345,9 +3380,6 @@
     case Type::Attributed:
       T = cast<AttributedType>(T)->getEquivalentType();
       break;
-    case Type::BTFTagAttributed:
-      T = cast<BTFTagAttributedType>(T)->getWrappedType();
-      break;
     case Type::Elaborated:
       T = cast<ElaboratedType>(T)->getNamedType();
       break;
@@ -3471,6 +3503,12 @@
 }
 
 llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
+  // For BTF type tag there is a finicky requirement to have type tag
+  // DIE as a parent for any qualifier DIEs.
+  if (Ty->getTypeClass() == Type::BTFTagAttributed)
+    return CreateType(cast<BTFTagAttributedType>(Ty), Ty.getLocalQualifiers(),
+                      Unit);
+
   // Handle qualifiers, which recursively handles what they refer to.
   if (Ty.hasLocalQualifiers())
     return CreateQualifiedType(Ty, Unit);
@@ -3540,7 +3578,6 @@
 
   case Type::Auto:
   case Type::Attributed:
-  case Type::BTFTagAttributed:
   case Type::Adjusted:
   case Type::Decayed:
   case Type::DeducedTemplateSpecialization:
@@ -3553,6 +3590,7 @@
   case Type::TypeOf:
   case Type::Decltype:
   case Type::UnaryTransform:
+  case Type::BTFTagAttributed:
     break;
   }
 
@@ -5678,6 +5716,35 @@
   TheCU->setDWOId(Signature);
 }
 
+static llvm::DIType *copyAnnotations(llvm::DIBuilder &DBuilder,
+                                     llvm::DIDerivedType *Placeholder) {
+  auto *WrappedDI = Placeholder->getBaseType();
+  SmallVector<llvm::Metadata *, 4> Annotations;
+
+  for (const llvm::Metadata *O : Placeholder->getAnnotations()->operands())
+    Annotations.push_back(const_cast<llvm::Metadata *>(O));
+
+  auto AddAnnotations = [&](auto *Type) {
+    if (llvm::DINodeArray OldAnnotations = Type->getAnnotations())
+      for (const llvm::Metadata *O : OldAnnotations->operands())
+        Annotations.push_back(const_cast<llvm::Metadata *>(O));
+    auto Clone = Type->clone();
+    Clone->replaceAnnotations(DBuilder.getOrCreateArray(Annotations));
+    return llvm::MDNode::replaceWithPermanent(std::move(Clone));
+  };
+
+  if (auto *Ty = dyn_cast<llvm::DIBasicType>(WrappedDI))
+    return AddAnnotations(Ty);
+  if (auto *Ty = dyn_cast<llvm::DICompositeType>(WrappedDI))
+    return AddAnnotations(Ty);
+  if (auto *Ty = dyn_cast<llvm::DIDerivedType>(WrappedDI))
+    return AddAnnotations(Ty);
+  if (auto *Ty = dyn_cast<llvm::DISubroutineType>(WrappedDI))
+    return AddAnnotations(Ty);
+
+  return WrappedDI;
+}
+
 void CGDebugInfo::finalize() {
   // Creating types might create further types - invalidating the current
   // element and the size(), so don't cache/reference them.
@@ -5751,6 +5818,10 @@
     if (auto MD = TypeCache[RT])
       DBuilder.retainType(cast<llvm::DIType>(MD));
 
+  for (auto &Placeholder : AnnotationPlaceholders)
+    DBuilder.replaceTemporary(llvm::TempDIType(Placeholder),
+                              copyAnnotations(DBuilder, Placeholder));
+
   DBuilder.finalize();
 }
 
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -4899,19 +4899,27 @@
   llvm::FoldingSetNodeID ID;
   BTFTagAttributedType::Profile(ID, Wrapped, BTFAttr);
 
+  // Split away local CVR qualifiers to make sure that
+  // BTFTagAttributedType is always applied to non-CVR qualified type.
+  // Apply CVR to a resulting QualType.
+  QualType WrappedNoCVR = Wrapped;
+  WrappedNoCVR.removeLocalCVRQualifiers(Qualifiers::CVRMask);
+  unsigned CVR = Wrapped.getLocalCVRQualifiers();
+
   void *InsertPos = nullptr;
   BTFTagAttributedType *Ty =
       BTFTagAttributedTypes.FindNodeOrInsertPos(ID, InsertPos);
   if (Ty)
-    return QualType(Ty, 0);
+    return QualType(Ty, CVR);
 
   QualType Canon = getCanonicalType(Wrapped);
-  Ty = new (*this, TypeAlignment) BTFTagAttributedType(Canon, Wrapped, BTFAttr);
+  Ty = new (*this, TypeAlignment)
+      BTFTagAttributedType(Canon, WrappedNoCVR, BTFAttr);
 
   Types.push_back(Ty);
   BTFTagAttributedTypes.InsertNode(Ty, InsertPos);
 
-  return QualType(Ty, 0);
+  return QualType(Ty, CVR);
 }
 
 /// Retrieve a substitution-result type.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to