[llvm] [DebugInfo] Add DW_TAG_property support to LLVM DebugInfo (PR #215776)

Piotr Jeremicz via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 06:49:36 PDT 2026


https://github.com/piotrekjeremicz updated https://github.com/llvm/llvm-project/pull/215776

>From e03090c031a33c21f4e3046863da46d01b04fced Mon Sep 17 00:00:00 2001
From: Piotrek Jeremicz <piotrek at jeremicz.com>
Date: Wed, 12 Aug 2026 22:15:52 +0200
Subject: [PATCH 1/3] [DebugInfo] Add DW_TAG_property support to LLVM DebugInfo

DWARF v6 adds DW_TAG_property to represent an entity accessed like a
data member but implemented via an accessor, such as an Objective-C
@property backed by an ivar. This adds a DIProperty metadata node,
plumbs it through the IR (LLParser/AsmWriter, bitcode, DIBuilder,
Verifier), and emits DW_TAG_property/DW_AT_property_forward DIEs in
DwarfUnit, anchored on the accessor's own subprogram DIE.

This covers the LLVM IR and DWARF layers only; Clang emission and
LLDB consumption are left for follow-up patches.

Assisted-by: Claude
---
 llvm/docs/LangRef.md                          | 14 ++++
 llvm/include/llvm-c/DebugInfo.h               |  1 +
 llvm/include/llvm/BinaryFormat/Dwarf.def      |  6 ++
 llvm/include/llvm/Bitcode/LLVMBitCodes.h      |  1 +
 llvm/include/llvm/IR/DIBuilder.h              | 13 +++
 llvm/include/llvm/IR/DebugInfoMetadata.h      | 80 +++++++++++++++++++
 llvm/include/llvm/IR/Metadata.def             |  1 +
 llvm/lib/AsmParser/LLParser.cpp               | 18 +++++
 llvm/lib/Bitcode/Reader/MetadataLoader.cpp    | 15 ++++
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp     | 16 ++++
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp    |  1 +
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp     | 35 ++++++++
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h       |  5 ++
 llvm/lib/DebugInfo/DWARF/DWARFDie.cpp         |  5 ++
 llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp    |  5 +-
 llvm/lib/IR/AsmWriter.cpp                     | 12 +++
 llvm/lib/IR/DIBuilder.cpp                     |  6 ++
 llvm/lib/IR/DebugInfo.cpp                     |  2 +
 llvm/lib/IR/DebugInfoMetadata.cpp             | 15 ++++
 llvm/lib/IR/LLVMContextImpl.h                 | 25 ++++++
 llvm/lib/IR/Verifier.cpp                      | 15 ++++
 .../DirectX/DXILWriter/DXILBitcodeWriter.cpp  |  4 +
 llvm/test/Assembler/diproperty.ll             | 20 +++++
 llvm/test/DebugInfo/Generic/property.ll       | 59 ++++++++++++++
 llvm/test/Verifier/diproperty.ll              | 18 +++++
 llvm/unittests/IR/MetadataTest.cpp            | 38 +++++++++
 26 files changed, 429 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Assembler/diproperty.ll
 create mode 100644 llvm/test/DebugInfo/Generic/property.ll
 create mode 100644 llvm/test/Verifier/diproperty.ll

diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index f2d19e4b6280c..6aa98e716343c 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -7253,6 +7253,20 @@ be used for the structure type.
                      getter: "getFoo", attributes: 7, type: !2)
 ```
 
+##### DIProperty
+
+`DIProperty` nodes represent DWARF `DW_TAG_property` entities: an entity
+that is syntactically accessed like a data member but whose access is
+implemented by an accessor. Currently only the getter is modelled, and it
+must point to the data member holding the property's backing storage (for
+example, an Objective-C `@property`'s backing ivar).
+
+```text
+!3 = !DIDerivedType(tag: DW_TAG_member, name: "_x", scope: !1, file: !2,
+                    line: 8, baseType: !4, size: 32)
+!5 = !DIProperty(name: "x", file: !2, line: 8, type: !4, getter: !3)
+```
+
 ##### DIImportedEntity
 
 `DIImportedEntity` nodes represent entities (such as modules) imported into a
diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h
index 155cbe32ee15e..2f7afa3f16aba 100644
--- a/llvm/include/llvm-c/DebugInfo.h
+++ b/llvm/include/llvm-c/DebugInfo.h
@@ -211,6 +211,7 @@ enum {
   LLVMDIAssignIDMetadataKind,
   LLVMDISubrangeTypeMetadataKind,
   LLVMDIFixedPointTypeMetadataKind,
+  LLVMDIPropertyMetadataKind,
 };
 typedef unsigned LLVMMetadataKind;
 
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 32195aae562c3..054fa292b7c53 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -237,6 +237,11 @@ HANDLE_DW_TAG(0x0048, call_site, 5, DWARF, DW_KIND_NONE)
 HANDLE_DW_TAG(0x0049, call_site_parameter, 5, DWARF, DW_KIND_NONE)
 HANDLE_DW_TAG(0x004a, skeleton_unit, 5, DWARF, DW_KIND_NONE)
 HANDLE_DW_TAG(0x004b, immutable_type, 5, DWARF, DW_KIND_TYPE)
+// New in DWARF v6:
+HANDLE_DW_TAG(0x004c, property, 6, DWARF, DW_KIND_NONE)
+HANDLE_DW_TAG(0x004d, property_getter, 6, DWARF, DW_KIND_NONE)
+HANDLE_DW_TAG(0x004e, property_setter, 6, DWARF, DW_KIND_NONE)
+HANDLE_DW_TAG(0x004f, property_stored, 6, DWARF, DW_KIND_NONE)
 // Vendor extensions:
 HANDLE_DW_TAG(0x4081, MIPS_loop, 0, MIPS, DW_KIND_NONE)
 // Conflicting:
@@ -432,6 +437,7 @@ HANDLE_DW_AT(0x8c, loclists_base, 5, DWARF)
 // New in Dwarf v6:
 HANDLE_DW_AT(0x90, language_name, 6, DWARF)
 HANDLE_DW_AT(0x91, language_version, 6, DWARF)
+HANDLE_DW_AT(0x95, property_forward, 6, DWARF)
 
 // Vendor extensions:
 HANDLE_DW_AT(0x806, GHS_namespace_alias, 0, GHS)
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 358f9a65a80af..013a6042d74aa 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -400,6 +400,7 @@ enum MetadataCodes {
   METADATA_ASSIGN_ID = 47,        // [distinct, ...]
   METADATA_SUBRANGE_TYPE = 48,    // [distinct, ...]
   METADATA_FIXED_POINT_TYPE = 49, // [distinct, ...]
+  METADATA_PROPERTY = 50,         // [distinct, name, file, line, type, getter]
 };
 
 // The constants block (CONSTANTS_BLOCK_ID) describes emission for each
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 3acb9c5f955e8..4f3031edb1ba1 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -554,6 +554,19 @@ namespace llvm {
                        StringRef GetterName, StringRef SetterName,
                        unsigned PropertyAttributes, DIType *Ty);
 
+    /// Create debugging information entry for a property, i.e. an entity that
+    /// is accessed like a data member but whose access is implemented by an
+    /// accessor.
+    /// \param Name          Property name.
+    /// \param File          File where this property is defined.
+    /// \param LineNumber    Line number.
+    /// \param Ty            Type of the property.
+    /// \param Getter        The data member the getter forwards to, holding
+    ///                      the property's backing storage.
+    LLVM_ABI DIProperty *createProperty(StringRef Name, DIFile *File,
+                                        unsigned LineNumber, DIType *Ty,
+                                        DIDerivedType *Getter);
+
     /// Create debugging information entry for a class.
     /// \param Scope        Scope in which this class is defined.
     /// \param Name         class name.
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 846342bee6071..8d793e2397931 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -223,6 +223,7 @@ class DINode : public MDNode {
     case DILocalVariableKind:
     case DILabelKind:
     case DIObjCPropertyKind:
+    case DIPropertyKind:
     case DIImportedEntityKind:
     case DIModuleKind:
     case DIGenericSubrangeKind:
@@ -4425,6 +4426,85 @@ class DIObjCProperty : public DINode {
   }
 };
 
+/// A property of a class or structure.
+///
+/// Represents a DWARF \c DW_TAG_property: an entity that is syntactically
+/// accessed like a data member, but whose access is implemented by invoking a
+/// user-defined or compiler-generated accessor.
+///
+/// Currently only the getter is modelled, and it must forward to a data
+/// member holding the property's backing storage.
+class DIProperty : public DINode {
+  friend class LLVMContextImpl;
+  friend class MDNode;
+
+  unsigned Line;
+
+  DIProperty(LLVMContext &C, StorageType Storage, unsigned Line,
+             ArrayRef<Metadata *> Ops);
+  ~DIProperty() = default;
+
+  static DIProperty *getImpl(LLVMContext &Context, StringRef Name, DIFile *File,
+                             unsigned Line, DIType *Type, DINode *Getter,
+                             StorageType Storage, bool ShouldCreate = true) {
+    return getImpl(Context, getCanonicalMDString(Context, Name), File, Line,
+                   Type, Getter, Storage, ShouldCreate);
+  }
+  LLVM_ABI static DIProperty *getImpl(LLVMContext &Context, MDString *Name,
+                                      Metadata *File, unsigned Line,
+                                      Metadata *Type, Metadata *Getter,
+                                      StorageType Storage,
+                                      bool ShouldCreate = true);
+
+  TempDIProperty cloneImpl() const {
+    return getTemporary(getContext(), getName(), getFile(), getLine(),
+                        getType(), getGetter());
+  }
+
+public:
+  DEFINE_MDNODE_GET(DIProperty,
+                    (StringRef Name, DIFile *File, unsigned Line, DIType *Type,
+                     DINode *Getter),
+                    (Name, File, Line, Type, Getter))
+  DEFINE_MDNODE_GET(DIProperty,
+                    (MDString * Name, Metadata *File, unsigned Line,
+                     Metadata *Type, Metadata *Getter),
+                    (Name, File, Line, Type, Getter))
+
+  TempDIProperty clone() const { return cloneImpl(); }
+
+  unsigned getLine() const { return Line; }
+  StringRef getName() const { return getStringOperand(0); }
+  DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
+  DIType *getType() const { return cast_or_null<DIType>(getRawType()); }
+
+  /// The entity the getter forwards to, i.e. the target of
+  /// \c DW_AT_property_forward on this property's \c DW_TAG_property_getter
+  /// child. This is the data member holding the property's backing storage.
+  DINode *getGetter() const { return cast_or_null<DINode>(getRawGetter()); }
+
+  StringRef getFilename() const {
+    if (auto *F = getFile())
+      return F->getFilename();
+    return "";
+  }
+
+  StringRef getDirectory() const {
+    if (auto *F = getFile())
+      return F->getDirectory();
+    return "";
+  }
+
+  MDString *getRawName() const { return getOperandAs<MDString>(0); }
+  Metadata *getRawFile() const { return getOperand(1); }
+  Metadata *getRawType() const { return getOperand(2); }
+  Metadata *getRawGetter() const { return getOperand(3); }
+
+  static bool classof(const Metadata *MD) {
+    return MD->getMetadataID() == DIPropertyKind;
+  }
+};
+
 /// An imported module (C++ using directive or similar).
 ///
 /// Uses the SubclassData32 Metadata slot.
diff --git a/llvm/include/llvm/IR/Metadata.def b/llvm/include/llvm/IR/Metadata.def
index 511bf48707f00..49404674f4e7b 100644
--- a/llvm/include/llvm/IR/Metadata.def
+++ b/llvm/include/llvm/IR/Metadata.def
@@ -110,6 +110,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariable)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocalVariable)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILabel)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIObjCProperty)
+HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIProperty)
 HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity)
 HANDLE_SPECIALIZED_MDNODE_LEAF(DIAssignID)
 HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode)
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index edff818b3b152..468373c82ff82 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -6700,6 +6700,24 @@ bool LLParser::parseDIObjCProperty(MDNode *&Result, bool IsDistinct) {
   return false;
 }
 
+/// parseDIProperty:
+///   ::= !DIProperty(name: "x", file: !1, line: 7, type: !2,
+///                   getter: !3)
+bool LLParser::parseDIProperty(MDNode *&Result, bool IsDistinct) {
+#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
+  OPTIONAL(name, MDStringField, );                                             \
+  OPTIONAL(file, MDField, );                                                   \
+  OPTIONAL(line, LineField, );                                                 \
+  OPTIONAL(type, MDField, );                                                   \
+  OPTIONAL(getter, MDField, );
+  PARSE_MD_FIELDS();
+#undef VISIT_MD_FIELDS
+
+  Result = GET_OR_DISTINCT(DIProperty, (Context, name.Val, file.Val, line.Val,
+                                        type.Val, getter.Val));
+  return false;
+}
+
 /// parseDIImportedEntity:
 ///   ::= !DIImportedEntity(tag: DW_TAG_imported_module, scope: !0, entity: !1,
 ///                         line: 7, name: "foo", elements: !2)
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 8b7beb1a8ff9e..11ba00ccfaec5 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -996,6 +996,7 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
       case bitc::METADATA_LABEL:
       case bitc::METADATA_EXPRESSION:
       case bitc::METADATA_OBJC_PROPERTY:
+      case bitc::METADATA_PROPERTY:
       case bitc::METADATA_IMPORTED_ENTITY:
       case bitc::METADATA_GLOBAL_VAR_EXPR:
       case bitc::METADATA_GENERIC_SUBRANGE:
@@ -2416,6 +2417,20 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     NextMetadataNo++;
     break;
   }
+  case bitc::METADATA_PROPERTY: {
+    if (Record.size() != 6)
+      return error("Invalid record");
+
+    IsDistinct = Record[0];
+    MetadataList.assignValue(
+        GET_OR_DISTINCT(DIProperty, (Context, getMDString(Record[1]),
+                                     getMDOrNull(Record[2]), Record[3],
+                                     getDITypeRefOrNull(Record[4]),
+                                     getMDOrNull(Record[5]))),
+        NextMetadataNo);
+    NextMetadataNo++;
+    break;
+  }
   case bitc::METADATA_IMPORTED_ENTITY: {
     if (Record.size() < 6 || Record.size() > 8)
       return error("Invalid DIImportedEntity record");
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 571336c217797..e08d5b403c552 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -410,6 +410,8 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase {
                                        unsigned Abbrev);
   void writeDIObjCProperty(const DIObjCProperty *N,
                            SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
+  void writeDIProperty(const DIProperty *N, SmallVectorImpl<uint64_t> &Record,
+                       unsigned Abbrev);
   void writeDIImportedEntity(const DIImportedEntity *N,
                              SmallVectorImpl<uint64_t> &Record,
                              unsigned Abbrev);
@@ -2510,6 +2512,20 @@ void ModuleBitcodeWriter::writeDIObjCProperty(const DIObjCProperty *N,
   Record.clear();
 }
 
+void ModuleBitcodeWriter::writeDIProperty(const DIProperty *N,
+                                          SmallVectorImpl<uint64_t> &Record,
+                                          unsigned Abbrev) {
+  Record.push_back(N->isDistinct());
+  Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
+  Record.push_back(VE.getMetadataOrNullID(N->getFile()));
+  Record.push_back(N->getLine());
+  Record.push_back(VE.getMetadataOrNullID(N->getType()));
+  Record.push_back(VE.getMetadataOrNullID(N->getGetter()));
+
+  Stream.EmitRecord(bitc::METADATA_PROPERTY, Record, Abbrev);
+  Record.clear();
+}
+
 void ModuleBitcodeWriter::writeDIImportedEntity(
     const DIImportedEntity *N, SmallVectorImpl<uint64_t> &Record,
     unsigned Abbrev) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 0b21819cb7bdf..c94ef946e20eb 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1340,6 +1340,7 @@ void DwarfDebug::finalizeModuleInfo() {
     // Emit DW_AT_containing_type attribute to connect types with their
     // vtable holding type.
     TheCU.constructContainingTypeDIEs();
+    TheCU.constructPropertyForwardDIEs();
 
     // Add CU specific attributes if we need to add any.
     // If we're splitting the dwarf out now that we've got the entire
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 78c0769e49161..60e850a2774c1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -510,6 +510,12 @@ void DwarfUnit::addSourceLine(DIE &Die, const DIObjCProperty *Ty) {
   addSourceLine(Die, Ty->getLine(), /*Column*/ 0, Ty->getFile());
 }
 
+void DwarfUnit::addSourceLine(DIE &Die, const DIProperty *P) {
+  assert(P);
+
+  addSourceLine(Die, P->getLine(), /*Column*/ 0, P->getFile());
+}
+
 void DwarfUnit::addConstantFPValue(DIE &Die, const ConstantFP *CFP) {
   // Pass this down to addConstantValue as an unsigned bag of bits.
   addConstantValue(Die, CFP->getValueAPF().bitcastToAPInt(), true);
@@ -1145,6 +1151,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
         if (unsigned PropertyAttributes = Property->getAttributes())
           addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, std::nullopt,
                   PropertyAttributes);
+      } else if (auto *Property = dyn_cast<DIProperty>(Element)) {
+        constructPropertyDIE(Buffer, Property);
       } else if (auto *Composite = dyn_cast<DICompositeType>(Element)) {
         if (Composite->getTag() == dwarf::DW_TAG_variant_part) {
           DIE &VariantPart = createAndAddDIE(Composite->getTag(), Buffer);
@@ -2012,6 +2020,33 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
   return MemberDie;
 }
 
+void DwarfUnit::constructPropertyDIE(DIE &Buffer, const DIProperty *P) {
+  DIE &PropertyDie = createAndAddDIE(dwarf::DW_TAG_property, Buffer, P);
+  addString(PropertyDie, dwarf::DW_AT_name, P->getName());
+  if (DIType *Ty = P->getType())
+    addType(PropertyDie, Ty);
+  addSourceLine(PropertyDie, P);
+
+  if (DINode *Getter = P->getGetter()) {
+    DIE &GetterDie =
+        createAndAddDIE(dwarf::DW_TAG_property_getter, PropertyDie);
+    PropertyForwardMap.insert(std::make_pair(&GetterDie, Getter));
+  }
+}
+
+void DwarfUnit::constructPropertyForwardDIEs() {
+  for (auto &P : PropertyForwardMap) {
+    DIE &GetterDie = *P.first;
+    const DINode *Target = P.second;
+    if (!Target)
+      continue;
+    DIE *TargetDie = getDIE(Target);
+    if (!TargetDie)
+      continue;
+    addDIEEntry(GetterDie, dwarf::DW_AT_property_forward, *TargetDie);
+  }
+}
+
 DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
   if (!DT)
     return nullptr;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 139fae5621940..42d537128642e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -73,6 +73,7 @@ class DwarfUnit : public DIEUnit {
   /// DW_AT_containing_type attribute. This attribute points to a DIE that
   /// corresponds to the MDNode mapped with the subprogram DIE.
   DenseMap<DIE *, const DINode *> ContainingTypeMap;
+  DenseMap<DIE *, const DINode *> PropertyForwardMap;
 
   DwarfUnit(dwarf::Tag, const DICompileUnit *Node, AsmPrinter *A,
             DwarfDebug *DW, DwarfFile *DWU, unsigned UniqueID = 0);
@@ -228,6 +229,7 @@ class DwarfUnit : public DIEUnit {
   void addSourceLine(DIE &Die, const DILabel *L);
   void addSourceLine(DIE &Die, const DIType *Ty);
   void addSourceLine(DIE &Die, const DIObjCProperty *Ty);
+  void addSourceLine(DIE &Die, const DIProperty *P);
 
   /// Add constant value entry in variable DIE.
   void addConstantValue(DIE &Die, const ConstantInt *CI, const DIType *Ty);
@@ -279,6 +281,8 @@ class DwarfUnit : public DIEUnit {
   /// Construct DIEs for types that contain vtables.
   void constructContainingTypeDIEs();
 
+  void constructPropertyForwardDIEs();
+
   /// Construct function argument DIEs.
   ///
   /// \returns The index of the object parameter in \c Args if one exists.
@@ -389,6 +393,7 @@ class DwarfUnit : public DIEUnit {
   void constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy);
   void constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy);
   DIE &constructMemberDIE(DIE &Buffer, const DIDerivedType *DT);
+  void constructPropertyDIE(DIE &Buffer, const DIProperty *P);
   void constructTemplateTypeParameterDIE(DIE &Buffer,
                                          const DITemplateTypeParameter *TP);
   void constructTemplateValueParameterDIE(DIE &Buffer,
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 997e2b60e8125..3deaa75b03f59 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -251,6 +251,11 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
             Die.getAttributeValueAsReferencedDie(FormValue).getName(
                 DINameKind::LinkageName))
       OS << Space << "\"" << Name << '\"';
+  } else if (Attr == DW_AT_property_forward) {
+    if (const char *Name =
+            Die.getAttributeValueAsReferencedDie(FormValue).getName(
+                DINameKind::ShortName))
+      OS << Space << "\"" << Name << '\"';
   } else if (Attr == DW_AT_APPLE_property) {
     auto PropDIE = Die.getAttributeValueAsReferencedDie(FormValue);
     if (auto PropNameOrErr = getApplePropertyName(PropDIE))
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 32775f348bb22..ebd54e18bbca9 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -1986,8 +1986,11 @@ void DWARFVerifier::verifyNameIndexCompleteness(
   case DW_TAG_GNU_template_template_param:
     return;
 
-  // Object members aren't globally visible.
+  // Object members aren't globally visible. Properties are accessed through
+  // their containing subprogram/type, not looked up globally by name, so
+  // they belong in the same category.
   case DW_TAG_member:
+  case DW_TAG_property:
     return;
 
   // DW_TAG_LLVM_annotation DIEs attach metadata to other DIEs.
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index cad4f17b0db91..35be0b18bad99 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2700,6 +2700,18 @@ static void writeDIObjCProperty(raw_ostream &Out, const DIObjCProperty *N,
   Out << ")";
 }
 
+static void writeDIProperty(raw_ostream &Out, const DIProperty *N,
+                            AsmWriterContext &WriterCtx) {
+  Out << "!DIProperty(";
+  MDFieldPrinter Printer(Out, WriterCtx);
+  Printer.printString("name", N->getName());
+  Printer.printMetadata("file", N->getRawFile());
+  Printer.printInt("line", N->getLine());
+  Printer.printMetadata("type", N->getRawType());
+  Printer.printMetadata("getter", N->getRawGetter());
+  Out << ")";
+}
+
 static void writeDIImportedEntity(raw_ostream &Out, const DIImportedEntity *N,
                                   AsmWriterContext &WriterCtx) {
   Out << "!DIImportedEntity(";
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index fb18fc3cc90c5..44719331589bb 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -572,6 +572,12 @@ DIBuilder::createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber,
                              SetterName, PropertyAttributes, Ty);
 }
 
+DIProperty *DIBuilder::createProperty(StringRef Name, DIFile *File,
+                                      unsigned LineNumber, DIType *Ty,
+                                      DIDerivedType *Getter) {
+  return DIProperty::get(VMContext, Name, File, LineNumber, Ty, Getter);
+}
+
 DITemplateTypeParameter *
 DIBuilder::createTemplateTypeParameter(DIScope *Context, StringRef Name,
                                        DIType *Ty, bool isDefault) {
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index e164ec54ead60..a42707604e61f 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -273,6 +273,8 @@ void DebugInfoFinder::processType(DIType *DT) {
         processType(T);
       else if (auto *SP = dyn_cast<DISubprogram>(D))
         processSubprogram(SP);
+      else if (auto *P = dyn_cast<DIProperty>(D))
+        processType(P->getType());
       else if (auto *SR = dyn_cast_or_null<DISubrange>(D)) {
         auto VisitBound = [&](DISubrange::BoundType Bound) {
           if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound))
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 88f7f2f6240e0..47b99613173b6 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -2624,6 +2624,21 @@ DIObjCProperty *DIObjCProperty::getImpl(
   DEFINE_GETIMPL_STORE(DIObjCProperty, (Line, Attributes), Ops);
 }
 
+DIProperty::DIProperty(LLVMContext &C, StorageType Storage, unsigned Line,
+                       ArrayRef<Metadata *> Ops)
+    : DINode(C, DIPropertyKind, Storage, dwarf::DW_TAG_property, Ops),
+      Line(Line) {}
+
+DIProperty *DIProperty::getImpl(LLVMContext &Context, MDString *Name,
+                                Metadata *File, unsigned Line, Metadata *Type,
+                                Metadata *Getter, StorageType Storage,
+                                bool ShouldCreate) {
+  assert(isCanonical(Name) && "Expected canonical MDString");
+  DEFINE_GETIMPL_LOOKUP(DIProperty, (Name, File, Line, Type, Getter));
+  Metadata *Ops[] = {Name, File, Type, Getter};
+  DEFINE_GETIMPL_STORE(DIProperty, (Line), Ops);
+}
+
 DIImportedEntity *DIImportedEntity::getImpl(LLVMContext &Context, unsigned Tag,
                                             Metadata *Scope, Metadata *Entity,
                                             Metadata *File, unsigned Line,
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 41c8a92c56eda..185b172423052 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1396,6 +1396,31 @@ template <> struct MDNodeKeyImpl<DIObjCProperty> {
   }
 };
 
+template <> struct MDNodeKeyImpl<DIProperty> {
+  MDString *Name;
+  Metadata *File;
+  unsigned Line;
+  Metadata *Type;
+  Metadata *Getter;
+
+  MDNodeKeyImpl(MDString *Name, Metadata *File, unsigned Line, Metadata *Type,
+                Metadata *Getter)
+      : Name(Name), File(File), Line(Line), Type(Type), Getter(Getter) {}
+  MDNodeKeyImpl(const DIProperty *N)
+      : Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()),
+        Type(N->getRawType()), Getter(N->getRawGetter()) {}
+
+  bool isKeyOf(const DIProperty *RHS) const {
+    return Name == RHS->getRawName() && File == RHS->getRawFile() &&
+           Line == RHS->getLine() && Type == RHS->getRawType() &&
+           Getter == RHS->getRawGetter();
+  }
+
+  unsigned getHashValue() const {
+    return hash_combine(Name, File, Line, Type, Getter);
+  }
+};
+
 template <> struct MDNodeKeyImpl<DIImportedEntity> {
   unsigned Tag;
   Metadata *Scope;
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 407c7a9122d3c..61b040cf91303 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1770,6 +1770,21 @@ void Verifier::visitDIObjCProperty(const DIObjCProperty &N) {
     CheckDI(isa<DIFile>(F), "invalid file", &N, F);
 }
 
+void Verifier::visitDIProperty(const DIProperty &N) {
+  CheckDI(N.getTag() == dwarf::DW_TAG_property, "invalid tag", &N);
+  if (auto *T = N.getRawType())
+    CheckDI(isType(T), "invalid type ref", &N, T);
+  if (auto *F = N.getRawFile())
+    CheckDI(isa<DIFile>(F), "invalid file", &N, F);
+  // DWARF allows a property getter to forward to a subprogram, variable, or
+  // constant too, but the backend only knows how to forward to a member.
+  if (DINode *G = N.getGetter()) {
+    auto *DT = dyn_cast<DIDerivedType>(G);
+    CheckDI(DT && DT->getTag() == dwarf::DW_TAG_member,
+            "property getter must be a member", &N, G);
+  }
+}
+
 void Verifier::visitDIImportedEntity(const DIImportedEntity &N) {
   CheckDI(N.getTag() == dwarf::DW_TAG_imported_module ||
               N.getTag() == dwarf::DW_TAG_imported_declaration,
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index 6f14f70014b01..99ea68b466206 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -325,6 +325,10 @@ class DXILBitcodeWriter {
   }
   void writeDIObjCProperty(const DIObjCProperty *N,
                            SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
+  void writeDIProperty(const DIProperty *N, SmallVectorImpl<uint64_t> &Record,
+                       unsigned Abbrev) {
+    llvm_unreachable("DXIL cannot contain DIProperty Nodes");
+  }
   void writeDIImportedEntity(const DIImportedEntity *N,
                              SmallVectorImpl<uint64_t> &Record,
                              unsigned Abbrev);
diff --git a/llvm/test/Assembler/diproperty.ll b/llvm/test/Assembler/diproperty.ll
new file mode 100644
index 0000000000000..fe42ac5953a44
--- /dev/null
+++ b/llvm/test/Assembler/diproperty.ll
@@ -0,0 +1,20 @@
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+; RUN: verify-uselistorder %s
+
+; !5 and !6 are identical, so uniquing collapses them to a single node.
+; CHECK: !named = !{!0, !1, !2, !3, !5, !6, !6}
+!named = !{!0, !1, !2, !3, !4, !5, !6}
+
+!0 = distinct !{}
+!1 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
+!2 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!3 = !DICompositeType(tag: DW_TAG_class_type, name: "Foo", elements: !{!4, !5})
+
+; CHECK: !5 = !DIDerivedType(tag: DW_TAG_member, name: "_x", scope: !3, file: !1, line: 8, baseType: !2, size: 32)
+!4 = !DIDerivedType(tag: DW_TAG_member, name: "_x", scope: !3, file: !1,
+                    line: 8, baseType: !2, size: 32)
+
+; CHECK-NEXT: !6 = !DIProperty(name: "x", file: !1, line: 8, type: !2, getter: !5)
+!5 = !DIProperty(name: "x", file: !1, line: 8, type: !2, getter: !4)
+
+!6 = !DIProperty(name: "x", file: !1, line: 8, type: !2, getter: !4)
diff --git a/llvm/test/DebugInfo/Generic/property.ll b/llvm/test/DebugInfo/Generic/property.ll
new file mode 100644
index 0000000000000..025e595c9e47b
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/property.ll
@@ -0,0 +1,59 @@
+; UNSUPPORTED:  target={{.*}}-aix{{.*}}
+;
+; RUN: llc -filetype=obj -o %t.o %s
+; RUN: llvm-dwarfdump --debug-info %t.o | FileCheck %s
+; RUN: llvm-dwarfdump --verify %t.o | FileCheck %s --check-prefix=VERIFY
+
+; VERIFY: No errors.
+
+; A property whose getter forwards to the data member holding its backing
+; storage. This models an Objective-C `@property`, where `x` is a synthesized
+; getter over the backing ivar `_x`, so a consumer can read the storage
+; directly instead of calling the getter.
+;
+; "Foo" lists the member before the property, "Bar" lists the property before
+; the member. Emission must not depend on that order.
+
+; CHECK: DW_TAG_class_type
+; CHECK:   DW_AT_name ("Foo")
+;
+; CHECK:   0x[[FOO_X:[0-9a-f]+]]: DW_TAG_member
+; CHECK:     DW_AT_name ("_x")
+;
+; CHECK:   DW_TAG_property
+; CHECK:     DW_AT_name ("x")
+; CHECK:     DW_AT_type {{.*}} "Int"
+; CHECK:     DW_AT_decl_line (8)
+; CHECK:     DW_TAG_property_getter
+; CHECK:       DW_AT_property_forward (0x[[FOO_X]] "_x")
+
+; CHECK: DW_TAG_class_type
+; CHECK:   DW_AT_name ("Bar")
+;
+; CHECK:   DW_TAG_property
+; CHECK:     DW_AT_name ("y")
+; CHECK:     DW_TAG_property_getter
+; CHECK:       DW_AT_property_forward (0x[[BAR_Y:[0-9a-f]+]] "_y")
+;
+; CHECK:   0x[[BAR_Y]]: DW_TAG_member
+; CHECK:     DW_AT_name ("_y")
+
+!llvm.module.flags = !{!0, !1}
+!llvm.dbg.cu = !{!2}
+
+!0 = !{i32 7, !"Dwarf Version", i32 5}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !3, producer: "hand written", isOptimized: false, emissionKind: FullDebug, retainedTypes: !4)
+!3 = !DIFile(filename: "t.m", directory: "/tmp")
+!4 = !{!5, !10}
+
+!5 = !DICompositeType(tag: DW_TAG_class_type, name: "Foo", scope: !3, file: !3, line: 7, size: 64, elements: !6)
+!6 = !{!7, !9}
+!7 = !DIDerivedType(tag: DW_TAG_member, name: "_x", scope: !5, file: !3, line: 8, baseType: !8, size: 64)
+!8 = !DIBasicType(name: "Int", size: 64, encoding: DW_ATE_signed)
+!9 = !DIProperty(name: "x", file: !3, line: 8, type: !8, getter: !7)
+
+!10 = !DICompositeType(tag: DW_TAG_class_type, name: "Bar", scope: !3, file: !3, line: 12, size: 64, elements: !11)
+!11 = !{!13, !12}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "_y", scope: !10, file: !3, line: 13, baseType: !8, size: 64)
+!13 = !DIProperty(name: "y", file: !3, line: 13, type: !8, getter: !12)
diff --git a/llvm/test/Verifier/diproperty.ll b/llvm/test/Verifier/diproperty.ll
new file mode 100644
index 0000000000000..53f2f6de3acde
--- /dev/null
+++ b/llvm/test/Verifier/diproperty.ll
@@ -0,0 +1,18 @@
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+!named = !{!0, !1, !2, !3, !4}
+
+!0 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
+!1 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+; A getter must forward to the data member holding the backing storage.
+; CHECK: property getter must be a member
+!2 = !DIProperty(name: "x", file: !0, line: 8, type: !1, getter: !1)
+
+; CHECK: property getter must be a member
+!3 = !DIProperty(name: "x", file: !0, line: 8, type: !1, getter: !0)
+
+; A pointer is a DIDerivedType, but not a DW_TAG_member.
+; CHECK: property getter must be a member
+!4 = !DIProperty(name: "x", file: !0, line: 8, type: !1, getter: !5)
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !1, size: 64)
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 65398b5ca2b1f..cbd190efb2f2d 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -4840,6 +4840,44 @@ TEST_F(DIObjCPropertyTest, get) {
   EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
 }
 
+typedef MetadataTest DIPropertyTest;
+
+TEST_F(DIPropertyTest, get) {
+  // The backing storage a property getter forwards to.
+  auto GetMember = [&](StringRef Name) {
+    return DIDerivedType::getDistinct(
+        Context, dwarf::DW_TAG_member, Name, nullptr, 0, nullptr,
+        getBasicType("basictype"), 8, 8, 0, std::nullopt, {}, DINode::FlagZero);
+  };
+
+  StringRef Name = "x";
+  DIFile *File = getFile();
+  unsigned Line = 5;
+  DIType *Type = getBasicType("basic");
+  DIDerivedType *Getter = GetMember("_x");
+
+  auto *N = DIProperty::get(Context, Name, File, Line, Type, Getter);
+
+  EXPECT_EQ(dwarf::DW_TAG_property, N->getTag());
+  EXPECT_EQ(Name, N->getName());
+  EXPECT_EQ(File, N->getFile());
+  EXPECT_EQ(Line, N->getLine());
+  EXPECT_EQ(Type, N->getType());
+  EXPECT_EQ(Getter, N->getGetter());
+  EXPECT_EQ(N, DIProperty::get(Context, Name, File, Line, Type, Getter));
+
+  EXPECT_NE(N, DIProperty::get(Context, "other", File, Line, Type, Getter));
+  EXPECT_NE(N, DIProperty::get(Context, Name, getFile(), Line, Type, Getter));
+  EXPECT_NE(N, DIProperty::get(Context, Name, File, Line + 1, Type, Getter));
+  EXPECT_NE(N, DIProperty::get(Context, Name, File, Line, getBasicType("other"),
+                               Getter));
+  EXPECT_NE(
+      N, DIProperty::get(Context, Name, File, Line, Type, GetMember("_other")));
+
+  TempDIProperty Temp = N->clone();
+  EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
 typedef MetadataTest DIImportedEntityTest;
 
 TEST_F(DIImportedEntityTest, get) {

>From 33d2ce3d88210f41a590021c02ce29d1d22f362c Mon Sep 17 00:00:00 2001
From: Piotrek Jeremicz <piotrek at jeremicz.com>
Date: Tue, 25 Aug 2026 21:59:42 +0200
Subject: [PATCH 2/3] Renamed `getter` into `backing_storage` + PR fixes

---
 llvm/docs/LangRef.md                      | 12 ++++----
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |  2 +-
 llvm/include/llvm/IR/DIBuilder.h          |  6 ++--
 llvm/include/llvm/IR/DebugInfoMetadata.h  | 37 ++++++++++++-----------
 llvm/lib/AsmParser/LLParser.cpp           |  6 ++--
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp |  2 +-
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp |  4 +--
 llvm/lib/IR/AsmWriter.cpp                 |  2 +-
 llvm/lib/IR/DIBuilder.cpp                 |  4 +--
 llvm/lib/IR/DebugInfoMetadata.cpp         |  6 ++--
 llvm/lib/IR/LLVMContextImpl.h             | 13 ++++----
 llvm/lib/IR/Verifier.cpp                  |  6 ++--
 llvm/test/Assembler/diproperty.ll         |  6 ++--
 llvm/test/DebugInfo/Generic/property.ll   | 11 +++----
 llvm/test/Verifier/diproperty.ll          | 14 ++++-----
 llvm/unittests/IR/MetadataTest.cpp        | 24 +++++++++------
 16 files changed, 81 insertions(+), 74 deletions(-)

diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index c6700e7aa8414..56484b76f9d91 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -7265,16 +7265,16 @@ be used for the structure type.
 
 ##### DIProperty
 
-`DIProperty` nodes represent DWARF `DW_TAG_property` entities: an entity
-that is syntactically accessed like a data member but whose access is
-implemented by an accessor. Currently only the getter is modelled, and it
-must point to the data member holding the property's backing storage (for
-example, an Objective-C `@property`'s backing ivar).
+`DIProperty` nodes represent an entity that is syntactically accessed like a
+data member but whose access is implemented by an accessor. No getter or
+setter is modelled yet; the node only records the data member holding the
+property's backing storage (for example, an Objective-C `@property`'s
+backing ivar).
 
 ```text
 !3 = !DIDerivedType(tag: DW_TAG_member, name: "_x", scope: !1, file: !2,
                     line: 8, baseType: !4, size: 32)
-!5 = !DIProperty(name: "x", file: !2, line: 8, type: !4, getter: !3)
+!5 = !DIProperty(name: "x", file: !2, line: 8, type: !4, backing_storage: !3)
 ```
 
 ##### DIImportedEntity
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 013a6042d74aa..1868e8c57dd00 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -400,7 +400,7 @@ enum MetadataCodes {
   METADATA_ASSIGN_ID = 47,        // [distinct, ...]
   METADATA_SUBRANGE_TYPE = 48,    // [distinct, ...]
   METADATA_FIXED_POINT_TYPE = 49, // [distinct, ...]
-  METADATA_PROPERTY = 50,         // [distinct, name, file, line, type, getter]
+  METADATA_PROPERTY = 50,         // [distinct, name, file, line, type, backing_storage]
 };
 
 // The constants block (CONSTANTS_BLOCK_ID) describes emission for each
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index fa55b1cb40bc2..64541779e726c 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -555,11 +555,11 @@ namespace llvm {
     /// \param File          File where this property is defined.
     /// \param LineNumber    Line number.
     /// \param Ty            Type of the property.
-    /// \param Getter        The data member the getter forwards to, holding
-    ///                      the property's backing storage.
+    /// \param BackingStorage The data member holding the property's backing
+    ///                      storage.
     LLVM_ABI DIProperty *createProperty(StringRef Name, DIFile *File,
                                         unsigned LineNumber, DIType *Ty,
-                                        DIDerivedType *Getter);
+                                        DIDerivedType *BackingStorage);
 
     /// Create debugging information entry for a class.
     /// \param Scope        Scope in which this class is defined.
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 55939031d17ba..d6b580581bf88 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -4616,8 +4616,8 @@ class DIObjCProperty : public DINode {
 /// accessed like a data member, but whose access is implemented by invoking a
 /// user-defined or compiler-generated accessor.
 ///
-/// Currently only the getter is modelled, and it must forward to a data
-/// member holding the property's backing storage.
+/// Currently only the backing storage is modelled, and it must be a data
+/// member holding the property's storage.
 class DIProperty : public DINode {
   friend class LLVMContextImpl;
   friend class MDNode;
@@ -4628,32 +4628,33 @@ class DIProperty : public DINode {
              ArrayRef<Metadata *> Ops);
   ~DIProperty() = default;
 
-  static DIProperty *getImpl(LLVMContext &Context, StringRef Name, DIFile *File,
-                             unsigned Line, DIType *Type, DINode *Getter,
-                             StorageType Storage, bool ShouldCreate = true) {
+  static DIProperty *getImpl(LLVMContext &Context, StringRef Name,
+                             DIFile *File, unsigned Line, DIType *Type,
+                             DINode *BackingStorage, StorageType Storage,
+                             bool ShouldCreate = true) {
     return getImpl(Context, getCanonicalMDString(Context, Name), File, Line,
-                   Type, Getter, Storage, ShouldCreate);
+                   Type, BackingStorage, Storage, ShouldCreate);
   }
   LLVM_ABI static DIProperty *getImpl(LLVMContext &Context, MDString *Name,
                                       Metadata *File, unsigned Line,
-                                      Metadata *Type, Metadata *Getter,
+                                      Metadata *Type, Metadata *BackingStorage,
                                       StorageType Storage,
                                       bool ShouldCreate = true);
 
   TempDIProperty cloneImpl() const {
     return getTemporary(getContext(), getName(), getFile(), getLine(),
-                        getType(), getGetter());
+                        getType(), getBackingStorage());
   }
 
 public:
   DEFINE_MDNODE_GET(DIProperty,
                     (StringRef Name, DIFile *File, unsigned Line, DIType *Type,
-                     DINode *Getter),
-                    (Name, File, Line, Type, Getter))
+                     DINode *BackingStorage),
+                    (Name, File, Line, Type, BackingStorage))
   DEFINE_MDNODE_GET(DIProperty,
                     (MDString * Name, Metadata *File, unsigned Line,
-                     Metadata *Type, Metadata *Getter),
-                    (Name, File, Line, Type, Getter))
+                     Metadata *Type, Metadata *BackingStorage),
+                    (Name, File, Line, Type, BackingStorage))
 
   TempDIProperty clone() const { return cloneImpl(); }
 
@@ -4662,10 +4663,12 @@ class DIProperty : public DINode {
   DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
   DIType *getType() const { return cast_or_null<DIType>(getRawType()); }
 
-  /// The entity the getter forwards to, i.e. the target of
-  /// \c DW_AT_property_forward on this property's \c DW_TAG_property_getter
-  /// child. This is the data member holding the property's backing storage.
-  DINode *getGetter() const { return cast_or_null<DINode>(getRawGetter()); }
+  /// The data member holding the property's backing storage, i.e. the target
+  /// of \c DW_AT_property_forward on this property's
+  /// \c DW_TAG_property_getter child.
+  DINode *getBackingStorage() const {
+    return cast_or_null<DINode>(getRawBackingStorage());
+  }
 
   StringRef getFilename() const {
     if (auto *F = getFile())
@@ -4682,7 +4685,7 @@ class DIProperty : public DINode {
   MDString *getRawName() const { return getOperandAs<MDString>(0); }
   Metadata *getRawFile() const { return getOperand(1); }
   Metadata *getRawType() const { return getOperand(2); }
-  Metadata *getRawGetter() const { return getOperand(3); }
+  Metadata *getRawBackingStorage() const { return getOperand(3); }
 
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == DIPropertyKind;
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 468373c82ff82..237722334a489 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -6702,19 +6702,19 @@ bool LLParser::parseDIObjCProperty(MDNode *&Result, bool IsDistinct) {
 
 /// parseDIProperty:
 ///   ::= !DIProperty(name: "x", file: !1, line: 7, type: !2,
-///                   getter: !3)
+///                   backing_storage: !3)
 bool LLParser::parseDIProperty(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
   OPTIONAL(name, MDStringField, );                                             \
   OPTIONAL(file, MDField, );                                                   \
   OPTIONAL(line, LineField, );                                                 \
   OPTIONAL(type, MDField, );                                                   \
-  OPTIONAL(getter, MDField, );
+  OPTIONAL(backing_storage, MDField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
   Result = GET_OR_DISTINCT(DIProperty, (Context, name.Val, file.Val, line.Val,
-                                        type.Val, getter.Val));
+                                        type.Val, backing_storage.Val));
   return false;
 }
 
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index e08d5b403c552..e3054e91fc12c 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2520,7 +2520,7 @@ void ModuleBitcodeWriter::writeDIProperty(const DIProperty *N,
   Record.push_back(VE.getMetadataOrNullID(N->getFile()));
   Record.push_back(N->getLine());
   Record.push_back(VE.getMetadataOrNullID(N->getType()));
-  Record.push_back(VE.getMetadataOrNullID(N->getGetter()));
+  Record.push_back(VE.getMetadataOrNullID(N->getBackingStorage()));
 
   Stream.EmitRecord(bitc::METADATA_PROPERTY, Record, Abbrev);
   Record.clear();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 34d58ae5d8b2c..107a11d30d249 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -2027,10 +2027,10 @@ void DwarfUnit::constructPropertyDIE(DIE &Buffer, const DIProperty *P) {
     addType(PropertyDie, Ty);
   addSourceLine(PropertyDie, P);
 
-  if (DINode *Getter = P->getGetter()) {
+  if (DINode *BackingStorage = P->getBackingStorage()) {
     DIE &GetterDie =
         createAndAddDIE(dwarf::DW_TAG_property_getter, PropertyDie);
-    PropertyForwardMap.insert(std::make_pair(&GetterDie, Getter));
+    PropertyForwardMap.insert(std::make_pair(&GetterDie, BackingStorage));
   }
 }
 
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 8df4d07d01ff1..40f8c67b9958c 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2708,7 +2708,7 @@ static void writeDIProperty(raw_ostream &Out, const DIProperty *N,
   Printer.printMetadata("file", N->getRawFile());
   Printer.printInt("line", N->getLine());
   Printer.printMetadata("type", N->getRawType());
-  Printer.printMetadata("getter", N->getRawGetter());
+  Printer.printMetadata("backing_storage", N->getRawBackingStorage());
   Out << ")";
 }
 
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index d0dc4bdb57f70..37791652a4375 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -573,8 +573,8 @@ DIBuilder::createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber,
 
 DIProperty *DIBuilder::createProperty(StringRef Name, DIFile *File,
                                       unsigned LineNumber, DIType *Ty,
-                                      DIDerivedType *Getter) {
-  return DIProperty::get(VMContext, Name, File, LineNumber, Ty, Getter);
+                                      DIDerivedType *BackingStorage) {
+  return DIProperty::get(VMContext, Name, File, LineNumber, Ty, BackingStorage);
 }
 
 DITemplateTypeParameter *
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index ad6bf7ed42945..c25b8c6796bbc 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -2680,11 +2680,11 @@ DIProperty::DIProperty(LLVMContext &C, StorageType Storage, unsigned Line,
 
 DIProperty *DIProperty::getImpl(LLVMContext &Context, MDString *Name,
                                 Metadata *File, unsigned Line, Metadata *Type,
-                                Metadata *Getter, StorageType Storage,
+                                Metadata *BackingStorage, StorageType Storage,
                                 bool ShouldCreate) {
   assert(isCanonical(Name) && "Expected canonical MDString");
-  DEFINE_GETIMPL_LOOKUP(DIProperty, (Name, File, Line, Type, Getter));
-  Metadata *Ops[] = {Name, File, Type, Getter};
+  DEFINE_GETIMPL_LOOKUP(DIProperty, (Name, File, Line, Type, BackingStorage));
+  Metadata *Ops[] = {Name, File, Type, BackingStorage};
   DEFINE_GETIMPL_STORE(DIProperty, (Line), Ops);
 }
 
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 185b172423052..2d22484d2ffb7 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1401,23 +1401,24 @@ template <> struct MDNodeKeyImpl<DIProperty> {
   Metadata *File;
   unsigned Line;
   Metadata *Type;
-  Metadata *Getter;
+  Metadata *BackingStorage;
 
   MDNodeKeyImpl(MDString *Name, Metadata *File, unsigned Line, Metadata *Type,
-                Metadata *Getter)
-      : Name(Name), File(File), Line(Line), Type(Type), Getter(Getter) {}
+                Metadata *BackingStorage)
+      : Name(Name), File(File), Line(Line), Type(Type),
+        BackingStorage(BackingStorage) {}
   MDNodeKeyImpl(const DIProperty *N)
       : Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()),
-        Type(N->getRawType()), Getter(N->getRawGetter()) {}
+        Type(N->getRawType()), BackingStorage(N->getRawBackingStorage()) {}
 
   bool isKeyOf(const DIProperty *RHS) const {
     return Name == RHS->getRawName() && File == RHS->getRawFile() &&
            Line == RHS->getLine() && Type == RHS->getRawType() &&
-           Getter == RHS->getRawGetter();
+           BackingStorage == RHS->getRawBackingStorage();
   }
 
   unsigned getHashValue() const {
-    return hash_combine(Name, File, Line, Type, Getter);
+    return hash_combine(Name, File, Line, Type, BackingStorage);
   }
 };
 
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 8dd9f0a8ec617..662b4def1056c 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1781,10 +1781,10 @@ void Verifier::visitDIProperty(const DIProperty &N) {
     CheckDI(isa<DIFile>(F), "invalid file", &N, F);
   // DWARF allows a property getter to forward to a subprogram, variable, or
   // constant too, but the backend only knows how to forward to a member.
-  if (DINode *G = N.getGetter()) {
-    auto *DT = dyn_cast<DIDerivedType>(G);
+  if (DINode *BackingStorage = N.getBackingStorage()) {
+    auto *DT = dyn_cast<DIDerivedType>(BackingStorage);
     CheckDI(DT && DT->getTag() == dwarf::DW_TAG_member,
-            "property getter must be a member", &N, G);
+            "property backing storage must be a member", &N, BackingStorage);
   }
 }
 
diff --git a/llvm/test/Assembler/diproperty.ll b/llvm/test/Assembler/diproperty.ll
index fe42ac5953a44..2d4ae1ee51c62 100644
--- a/llvm/test/Assembler/diproperty.ll
+++ b/llvm/test/Assembler/diproperty.ll
@@ -14,7 +14,7 @@
 !4 = !DIDerivedType(tag: DW_TAG_member, name: "_x", scope: !3, file: !1,
                     line: 8, baseType: !2, size: 32)
 
-; CHECK-NEXT: !6 = !DIProperty(name: "x", file: !1, line: 8, type: !2, getter: !5)
-!5 = !DIProperty(name: "x", file: !1, line: 8, type: !2, getter: !4)
+; CHECK-NEXT: !6 = !DIProperty(name: "x", file: !1, line: 8, type: !2, backing_storage: !5)
+!5 = !DIProperty(name: "x", file: !1, line: 8, type: !2, backing_storage: !4)
 
-!6 = !DIProperty(name: "x", file: !1, line: 8, type: !2, getter: !4)
+!6 = !DIProperty(name: "x", file: !1, line: 8, type: !2, backing_storage: !4)
diff --git a/llvm/test/DebugInfo/Generic/property.ll b/llvm/test/DebugInfo/Generic/property.ll
index 025e595c9e47b..3d3413403e1ca 100644
--- a/llvm/test/DebugInfo/Generic/property.ll
+++ b/llvm/test/DebugInfo/Generic/property.ll
@@ -6,10 +6,9 @@
 
 ; VERIFY: No errors.
 
-; A property whose getter forwards to the data member holding its backing
-; storage. This models an Objective-C `@property`, where `x` is a synthesized
-; getter over the backing ivar `_x`, so a consumer can read the storage
-; directly instead of calling the getter.
+; A property that forwards to the data member holding its backing storage.
+; This models an Objective-C `@property` synthesized over the backing ivar
+; `_x`, so a consumer can read the storage directly.
 ;
 ; "Foo" lists the member before the property, "Bar" lists the property before
 ; the member. Emission must not depend on that order.
@@ -51,9 +50,9 @@
 !6 = !{!7, !9}
 !7 = !DIDerivedType(tag: DW_TAG_member, name: "_x", scope: !5, file: !3, line: 8, baseType: !8, size: 64)
 !8 = !DIBasicType(name: "Int", size: 64, encoding: DW_ATE_signed)
-!9 = !DIProperty(name: "x", file: !3, line: 8, type: !8, getter: !7)
+!9 = !DIProperty(name: "x", file: !3, line: 8, type: !8, backing_storage: !7)
 
 !10 = !DICompositeType(tag: DW_TAG_class_type, name: "Bar", scope: !3, file: !3, line: 12, size: 64, elements: !11)
 !11 = !{!13, !12}
 !12 = !DIDerivedType(tag: DW_TAG_member, name: "_y", scope: !10, file: !3, line: 13, baseType: !8, size: 64)
-!13 = !DIProperty(name: "y", file: !3, line: 13, type: !8, getter: !12)
+!13 = !DIProperty(name: "y", file: !3, line: 13, type: !8, backing_storage: !12)
diff --git a/llvm/test/Verifier/diproperty.ll b/llvm/test/Verifier/diproperty.ll
index 53f2f6de3acde..9421835bc502d 100644
--- a/llvm/test/Verifier/diproperty.ll
+++ b/llvm/test/Verifier/diproperty.ll
@@ -5,14 +5,14 @@
 !0 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
 !1 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 
-; A getter must forward to the data member holding the backing storage.
-; CHECK: property getter must be a member
-!2 = !DIProperty(name: "x", file: !0, line: 8, type: !1, getter: !1)
+; The backing storage must be the data member holding the property's storage.
+; CHECK: property backing storage must be a member
+!2 = !DIProperty(name: "x", file: !0, line: 8, type: !1, backing_storage: !1)
 
-; CHECK: property getter must be a member
-!3 = !DIProperty(name: "x", file: !0, line: 8, type: !1, getter: !0)
+; CHECK: property backing storage must be a member
+!3 = !DIProperty(name: "x", file: !0, line: 8, type: !1, backing_storage: !0)
 
 ; A pointer is a DIDerivedType, but not a DW_TAG_member.
-; CHECK: property getter must be a member
-!4 = !DIProperty(name: "x", file: !0, line: 8, type: !1, getter: !5)
+; CHECK: property backing storage must be a member
+!4 = !DIProperty(name: "x", file: !0, line: 8, type: !1, backing_storage: !5)
 !5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !1, size: 64)
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 7a1232852e601..6586c65badde3 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -5060,7 +5060,7 @@ TEST_F(DIObjCPropertyTest, get) {
 typedef MetadataTest DIPropertyTest;
 
 TEST_F(DIPropertyTest, get) {
-  // The backing storage a property getter forwards to.
+  // The data member holding a property's backing storage.
   auto GetMember = [&](StringRef Name) {
     return DIDerivedType::getDistinct(
         Context, dwarf::DW_TAG_member, Name, nullptr, 0, nullptr,
@@ -5071,23 +5071,27 @@ TEST_F(DIPropertyTest, get) {
   DIFile *File = getFile();
   unsigned Line = 5;
   DIType *Type = getBasicType("basic");
-  DIDerivedType *Getter = GetMember("_x");
+  DIDerivedType *BackingStorage = GetMember("_x");
 
-  auto *N = DIProperty::get(Context, Name, File, Line, Type, Getter);
+  auto *N = DIProperty::get(Context, Name, File, Line, Type, BackingStorage);
 
   EXPECT_EQ(dwarf::DW_TAG_property, N->getTag());
   EXPECT_EQ(Name, N->getName());
   EXPECT_EQ(File, N->getFile());
   EXPECT_EQ(Line, N->getLine());
   EXPECT_EQ(Type, N->getType());
-  EXPECT_EQ(Getter, N->getGetter());
-  EXPECT_EQ(N, DIProperty::get(Context, Name, File, Line, Type, Getter));
-
-  EXPECT_NE(N, DIProperty::get(Context, "other", File, Line, Type, Getter));
-  EXPECT_NE(N, DIProperty::get(Context, Name, getFile(), Line, Type, Getter));
-  EXPECT_NE(N, DIProperty::get(Context, Name, File, Line + 1, Type, Getter));
+  EXPECT_EQ(BackingStorage, N->getBackingStorage());
+  EXPECT_EQ(N,
+            DIProperty::get(Context, Name, File, Line, Type, BackingStorage));
+
+  EXPECT_NE(N, DIProperty::get(Context, "other", File, Line, Type,
+                               BackingStorage));
+  EXPECT_NE(N, DIProperty::get(Context, Name, getFile(), Line, Type,
+                               BackingStorage));
+  EXPECT_NE(N, DIProperty::get(Context, Name, File, Line + 1, Type,
+                               BackingStorage));
   EXPECT_NE(N, DIProperty::get(Context, Name, File, Line, getBasicType("other"),
-                               Getter));
+                               BackingStorage));
   EXPECT_NE(
       N, DIProperty::get(Context, Name, File, Line, Type, GetMember("_other")));
 

>From da1cdc7a3410700344c12bdc5fb720497255fc8b Mon Sep 17 00:00:00 2001
From: Piotrek Jeremicz <piotrek at jeremicz.com>
Date: Wed, 26 Aug 2026 15:49:17 +0200
Subject: [PATCH 3/3] Address remaining review comments on DIProperty docs

Drop the direct DWARF reference from the DIProperty class comment in
DebugInfoMetadata.h, matching the earlier LangRef.md fix, per Augusto's
review comment. Also simplify the LangRef.md DIProperty description:
instead of stating what isn't modelled yet (getter/setter), just state
that the node models the property's backing variable.

Also apply the git-clang-format formatting fixes flagged by CI.

Assisted-by: Claude
---
 llvm/docs/LangRef.md                     |  5 ++---
 llvm/include/llvm/Bitcode/LLVMBitCodes.h |  2 +-
 llvm/include/llvm/IR/DebugInfoMetadata.h | 10 +++++-----
 llvm/unittests/IR/MetadataTest.cpp       | 12 ++++++------
 4 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index 56484b76f9d91..ab498662c6c29 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -7266,9 +7266,8 @@ be used for the structure type.
 ##### DIProperty
 
 `DIProperty` nodes represent an entity that is syntactically accessed like a
-data member but whose access is implemented by an accessor. No getter or
-setter is modelled yet; the node only records the data member holding the
-property's backing storage (for example, an Objective-C `@property`'s
+data member but whose access is implemented by an accessor. The node models
+the property's backing variable (for example, an Objective-C `@property`'s
 backing ivar).
 
 ```text
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 1868e8c57dd00..48d045ed1f190 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -400,7 +400,7 @@ enum MetadataCodes {
   METADATA_ASSIGN_ID = 47,        // [distinct, ...]
   METADATA_SUBRANGE_TYPE = 48,    // [distinct, ...]
   METADATA_FIXED_POINT_TYPE = 49, // [distinct, ...]
-  METADATA_PROPERTY = 50,         // [distinct, name, file, line, type, backing_storage]
+  METADATA_PROPERTY = 50, // [distinct, name, file, line, type, backing_storage]
 };
 
 // The constants block (CONSTANTS_BLOCK_ID) describes emission for each
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index d6b580581bf88..9d3a81cb2bb4f 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -4612,9 +4612,9 @@ class DIObjCProperty : public DINode {
 
 /// A property of a class or structure.
 ///
-/// Represents a DWARF \c DW_TAG_property: an entity that is syntactically
-/// accessed like a data member, but whose access is implemented by invoking a
-/// user-defined or compiler-generated accessor.
+/// An entity that is syntactically accessed like a data member, but whose
+/// access is implemented by invoking a user-defined or compiler-generated
+/// accessor.
 ///
 /// Currently only the backing storage is modelled, and it must be a data
 /// member holding the property's storage.
@@ -4628,8 +4628,8 @@ class DIProperty : public DINode {
              ArrayRef<Metadata *> Ops);
   ~DIProperty() = default;
 
-  static DIProperty *getImpl(LLVMContext &Context, StringRef Name,
-                             DIFile *File, unsigned Line, DIType *Type,
+  static DIProperty *getImpl(LLVMContext &Context, StringRef Name, DIFile *File,
+                             unsigned Line, DIType *Type,
                              DINode *BackingStorage, StorageType Storage,
                              bool ShouldCreate = true) {
     return getImpl(Context, getCanonicalMDString(Context, Name), File, Line,
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 6586c65badde3..f2c55c0f2a534 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -5084,12 +5084,12 @@ TEST_F(DIPropertyTest, get) {
   EXPECT_EQ(N,
             DIProperty::get(Context, Name, File, Line, Type, BackingStorage));
 
-  EXPECT_NE(N, DIProperty::get(Context, "other", File, Line, Type,
-                               BackingStorage));
-  EXPECT_NE(N, DIProperty::get(Context, Name, getFile(), Line, Type,
-                               BackingStorage));
-  EXPECT_NE(N, DIProperty::get(Context, Name, File, Line + 1, Type,
-                               BackingStorage));
+  EXPECT_NE(
+      N, DIProperty::get(Context, "other", File, Line, Type, BackingStorage));
+  EXPECT_NE(
+      N, DIProperty::get(Context, Name, getFile(), Line, Type, BackingStorage));
+  EXPECT_NE(
+      N, DIProperty::get(Context, Name, File, Line + 1, Type, BackingStorage));
   EXPECT_NE(N, DIProperty::get(Context, Name, File, Line, getBasicType("other"),
                                BackingStorage));
   EXPECT_NE(



More information about the llvm-commits mailing list