DebugInfo: Add MDLexicalBlockBase::getLine(), etc.
[oota-llvm.git] / include / llvm / IR / DebugInfoMetadata.h
index 18619f374208f11bf70aa36ef4c9f8af9fd7b30c..e16e4319aa94ec49a208ea3172e39ef7faa6567c 100644 (file)
@@ -50,6 +50,7 @@ template <class T> class TypedDebugNodeRef {
   const Metadata *MD = nullptr;
 
 public:
+  TypedDebugNodeRef() = default;
   TypedDebugNodeRef(std::nullptr_t) {}
 
   /// \brief Construct from a raw pointer.
@@ -151,7 +152,7 @@ protected:
     assert(Tag < 1u << 16);
     SubclassData16 = Tag;
   }
-  ~DebugNode() {}
+  ~DebugNode() = default;
 
   template <class Ty> Ty *getOperandAs(unsigned I) const {
     return cast_or_null<Ty>(getOperand(I));
@@ -327,7 +328,7 @@ class MDSubrange : public DebugNode {
       : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type,
                   None),
         Count(Count), LowerBound(LowerBound) {}
-  ~MDSubrange() {}
+  ~MDSubrange() = default;
 
   static MDSubrange *getImpl(LLVMContext &Context, int64_t Count,
                              int64_t LowerBound, StorageType Storage,
@@ -365,7 +366,7 @@ class MDEnumerator : public DebugNode {
                ArrayRef<Metadata *> Ops)
       : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
         Value(Value) {}
-  ~MDEnumerator() {}
+  ~MDEnumerator() = default;
 
   static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value,
                                StringRef Name, StorageType Storage,
@@ -410,11 +411,17 @@ protected:
   MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
           ArrayRef<Metadata *> Ops)
       : DebugNode(C, ID, Storage, Tag, Ops) {}
-  ~MDScope() {}
+  ~MDScope() = default;
 
 public:
   MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); }
 
+  inline StringRef getFilename() const;
+  inline StringRef getDirectory() const;
+
+  StringRef getName() const;
+  MDScopeRef getScope() const;
+
   /// \brief Return the raw underlying file.
   ///
   /// An \a MDFile is an \a MDScope, but it doesn't point at a separate file
@@ -457,7 +464,7 @@ class MDFile : public MDScope {
 
   MDFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops)
       : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {}
-  ~MDFile() {}
+  ~MDFile() = default;
 
   static MDFile *getImpl(LLVMContext &Context, StringRef Filename,
                          StringRef Directory, StorageType Storage,
@@ -493,6 +500,18 @@ public:
   }
 };
 
+StringRef MDScope::getFilename() const {
+  if (auto *F = getFile())
+    return F->getFilename();
+  return "";
+}
+
+StringRef MDScope::getDirectory() const {
+  if (auto *F = getFile())
+    return F->getDirectory();
+  return "";
+}
+
 /// \brief Base class for types.
 ///
 /// TODO: Remove the hardcoded name and context, since many types don't use
@@ -512,7 +531,7 @@ protected:
       : MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags),
         SizeInBits(SizeInBits), AlignInBits(AlignInBits),
         OffsetInBits(OffsetInBits) {}
-  ~MDType() {}
+  ~MDType() = default;
 
 public:
   TempMDType clone() const {
@@ -591,7 +610,7 @@ class MDBasicType : public MDType {
       : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
                0, Ops),
         Encoding(Encoding) {}
-  ~MDBasicType() {}
+  ~MDBasicType() = default;
 
   static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag,
                               StringRef Name, uint64_t SizeInBits,
@@ -642,7 +661,7 @@ protected:
                     ArrayRef<Metadata *> Ops)
       : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits,
                Flags, Ops) {}
-  ~MDDerivedTypeBase() {}
+  ~MDDerivedTypeBase() = default;
 
 public:
   MDTypeRef getBaseType() const { return MDTypeRef(getRawBaseType()); }
@@ -670,7 +689,7 @@ class MDDerivedType : public MDDerivedTypeBase {
                 uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops)
       : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits,
                           AlignInBits, OffsetInBits, Flags, Ops) {}
-  ~MDDerivedType() {}
+  ~MDDerivedType() = default;
 
   static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
                                 StringRef Name, MDFile *File, unsigned Line,
@@ -727,6 +746,23 @@ public:
   Metadata *getExtraData() const { return getRawExtraData(); }
   Metadata *getRawExtraData() const { return getOperand(4); }
 
+  /// \brief Get casted version of extra data.
+  /// @{
+  MDTypeRef getClassType() const {
+    assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
+    return MDTypeRef(getExtraData());
+  }
+  MDObjCProperty *getObjCProperty() const {
+    return dyn_cast_or_null<MDObjCProperty>(getExtraData());
+  }
+  Constant *getConstant() const {
+    assert(getTag() == dwarf::DW_TAG_member && isStaticMember());
+    if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
+      return C->getValue();
+    return nullptr;
+  }
+  /// @}
+
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == MDDerivedTypeKind;
   }
@@ -747,10 +783,16 @@ protected:
       : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits,
                           OffsetInBits, Flags, Ops),
         RuntimeLang(RuntimeLang) {}
-  ~MDCompositeTypeBase() {}
+  ~MDCompositeTypeBase() = default;
 
 public:
+  /// \brief Get the elements of the composite type.
+  ///
+  /// \note Calling this is only valid for \a MDCompositeType.  This assertion
+  /// can be removed once \a MDSubroutineType has been separated from
+  /// "composite types".
   DebugNodeArray getElements() const {
+    assert(!isa<MDSubroutineType>(this) && "no elements for DISubroutineType");
     return cast_or_null<MDTuple>(getRawElements());
   }
   MDTypeRef getVTableHolder() const { return MDTypeRef(getRawVTableHolder()); }
@@ -808,7 +850,7 @@ class MDCompositeType : public MDCompositeTypeBase {
       : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line,
                             RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
                             Flags, Ops) {}
-  ~MDCompositeType() {}
+  ~MDCompositeType() = default;
 
   static MDCompositeType *
   getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File,
@@ -891,7 +933,7 @@ class MDSubroutineType : public MDCompositeTypeBase {
       : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage,
                             dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags,
                             Ops) {}
-  ~MDSubroutineType() {}
+  ~MDSubroutineType() = default;
 
   static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
                                    MDTypeRefArray TypeArray,
@@ -942,7 +984,7 @@ class MDCompileUnit : public MDScope {
       : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),
         SourceLanguage(SourceLanguage), IsOptimized(IsOptimized),
         RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {}
-  ~MDCompileUnit() {}
+  ~MDCompileUnit() = default;
 
   static MDCompileUnit *
   getImpl(LLVMContext &Context, unsigned SourceLanguage, MDFile *File,
@@ -1067,7 +1109,7 @@ protected:
   MDLocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
                ArrayRef<Metadata *> Ops)
       : MDScope(C, ID, Storage, Tag, Ops) {}
-  ~MDLocalScope() {}
+  ~MDLocalScope() = default;
 
 public:
   /// \brief Get the subprogram for this scope.
@@ -1136,6 +1178,10 @@ public:
     return cast_or_null<MDLocation>(getRawInlinedAt());
   }
 
+  MDFile *getFile() const { return getScope()->getFile(); }
+  StringRef getFilename() const { return getScope()->getFilename(); }
+  StringRef getDirectory() const { return getScope()->getDirectory(); }
+
   /// \brief Get the scope where this is inlined.
   ///
   /// Walk through \a getInlinedAt() and return \a getScope() from the deepest
@@ -1146,6 +1192,38 @@ public:
     return getScope();
   }
 
+  /// \brief Check whether this can be discriminated from another location.
+  ///
+  /// Check \c this can be discriminated from \c RHS in a linetable entry.
+  /// Scope and inlined-at chains are not recorded in the linetable, so they
+  /// cannot be used to distinguish basic blocks.
+  ///
+  /// The current implementation is weaker than it should be, since it just
+  /// checks filename and line.
+  ///
+  /// FIXME: Add a check for getDiscriminator().
+  /// FIXME: Add a check for getColumn().
+  /// FIXME: Change the getFilename() check to getFile() (or add one for
+  /// getDirectory()).
+  bool canDiscriminate(const MDLocation &RHS) const {
+    return getFilename() != RHS.getFilename() || getLine() != RHS.getLine();
+  }
+
+  /// \brief Get the DWARF discriminator.
+  ///
+  /// DWARF discriminators distinguish identical file locations between
+  /// instructions that are on different basic blocks.
+  inline unsigned getDiscriminator() const;
+
+  /// \brief Compute new discriminator in the given context.
+  ///
+  /// This modifies the \a LLVMContext that \c this is in to increment the next
+  /// discriminator for \c this's line/filename combination.
+  ///
+  /// FIXME: Delete this.  See comments in implementation and at the only call
+  /// site in \a AddDiscriminators::runOnFunction().
+  unsigned computeNewDiscriminator() const;
+
   Metadata *getRawScope() const { return getOperand(0); }
   Metadata *getRawInlinedAt() const {
     if (getNumOperands() == 2)
@@ -1184,7 +1262,7 @@ class MDSubprogram : public MDLocalScope {
         Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality),
         VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit),
         IsDefinition(IsDefinition), IsOptimized(IsOptimized) {}
-  ~MDSubprogram() {}
+  ~MDSubprogram() = default;
 
   static MDSubprogram *
   getImpl(LLVMContext &Context, MDScopeRef Scope, StringRef Name,
@@ -1192,13 +1270,14 @@ class MDSubprogram : public MDLocalScope {
           MDSubroutineType *Type, bool IsLocalToUnit, bool IsDefinition,
           unsigned ScopeLine, MDTypeRef ContainingType, unsigned Virtuality,
           unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
-          ConstantAsMetadata *Function, MDTemplateParameterArray TemplateParams,
+          Constant *Function, MDTemplateParameterArray TemplateParams,
           MDSubprogram *Declaration, MDLocalVariableArray Variables,
           StorageType Storage, bool ShouldCreate = true) {
     return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
                    getCanonicalMDString(Context, LinkageName), File, Line, Type,
                    IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
-                   Virtuality, VirtualIndex, Flags, IsOptimized, Function,
+                   Virtuality, VirtualIndex, Flags, IsOptimized,
+                   Function ? ConstantAsMetadata::get(Function) : nullptr,
                    TemplateParams.get(), Declaration, Variables.get(), Storage,
                    ShouldCreate);
   }
@@ -1216,8 +1295,8 @@ class MDSubprogram : public MDLocalScope {
                         getFile(), getLine(), getType(), isLocalToUnit(),
                         isDefinition(), getScopeLine(), getContainingType(),
                         getVirtuality(), getVirtualIndex(), getFlags(),
-                        isOptimized(), getFunction(), getTemplateParams(),
-                        getDeclaration(), getVariables());
+                        isOptimized(), getFunctionConstant(),
+                        getTemplateParams(), getDeclaration(), getVariables());
   }
 
 public:
@@ -1227,7 +1306,7 @@ public:
                      bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
                      MDTypeRef ContainingType, unsigned Virtuality,
                      unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
-                     ConstantAsMetadata *Function = nullptr,
+                     Constant *Function = nullptr,
                      MDTemplateParameterArray TemplateParams = nullptr,
                      MDSubprogram *Declaration = nullptr,
                      MDLocalVariableArray Variables = nullptr),
@@ -1304,8 +1383,10 @@ public:
     return MDTypeRef(getRawContainingType());
   }
 
-  ConstantAsMetadata *getFunction() const {
-    return cast_or_null<ConstantAsMetadata>(getRawFunction());
+  Constant *getFunctionConstant() const {
+    if (auto *C = cast_or_null<ConstantAsMetadata>(getRawFunction()))
+      return C->getValue();
+    return nullptr;
   }
   MDTemplateParameterArray getTemplateParams() const {
     return cast_or_null<MDTuple>(getRawTemplateParams());
@@ -1325,6 +1406,13 @@ public:
   Metadata *getRawDeclaration() const { return getOperand(9); }
   Metadata *getRawVariables() const { return getOperand(10); }
 
+  /// \brief Get a pointer to the function this subprogram describes.
+  ///
+  /// This dyn_casts \a getFunctionConstant() to \a Function.
+  ///
+  /// FIXME: Should this be looking through bitcasts?
+  Function *getFunction() const;
+
   /// \brief Replace the function.
   ///
   /// If \a isUniqued() and not \a isResolved(), this could node will be
@@ -1336,6 +1424,11 @@ public:
   void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); }
   /// @}
 
+  /// \brief Check if this subprogram decribes the given function.
+  ///
+  /// FIXME: Should this be looking through bitcasts?
+  bool describes(const Function *F) const;
+
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == MDSubprogramKind;
   }
@@ -1346,13 +1439,20 @@ protected:
   MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage,
                      ArrayRef<Metadata *> Ops)
       : MDLocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {}
-  ~MDLexicalBlockBase() {}
+  ~MDLexicalBlockBase() = default;
 
 public:
   MDLocalScope *getScope() const { return cast<MDLocalScope>(getRawScope()); }
 
   Metadata *getRawScope() const { return getOperand(1); }
 
+  /// \brief Forwarding accessors to LexicalBlock.
+  ///
+  /// TODO: Remove these and update code to use \a MDLexicalBlock directly.
+  /// @{
+  inline unsigned getLine() const;
+  inline unsigned getColumn() const;
+  /// @}
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == MDLexicalBlockKind ||
            MD->getMetadataID() == MDLexicalBlockFileKind;
@@ -1370,7 +1470,7 @@ class MDLexicalBlock : public MDLexicalBlockBase {
                  unsigned Column, ArrayRef<Metadata *> Ops)
       : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line),
         Column(Column) {}
-  ~MDLexicalBlock() {}
+  ~MDLexicalBlock() = default;
 
   static MDLexicalBlock *getImpl(LLVMContext &Context, MDLocalScope *Scope,
                                  MDFile *File, unsigned Line, unsigned Column,
@@ -1408,6 +1508,18 @@ public:
   }
 };
 
+unsigned MDLexicalBlockBase::getLine() const {
+  if (auto *N = dyn_cast<MDLexicalBlock>(this))
+    return N->getLine();
+  return 0;
+}
+
+unsigned MDLexicalBlockBase::getColumn() const {
+  if (auto *N = dyn_cast<MDLexicalBlock>(this))
+    return N->getColumn();
+  return 0;
+}
+
 class MDLexicalBlockFile : public MDLexicalBlockBase {
   friend class LLVMContextImpl;
   friend class MDNode;
@@ -1418,7 +1530,7 @@ class MDLexicalBlockFile : public MDLexicalBlockBase {
                      unsigned Discriminator, ArrayRef<Metadata *> Ops)
       : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops),
         Discriminator(Discriminator) {}
-  ~MDLexicalBlockFile() {}
+  ~MDLexicalBlockFile() = default;
 
   static MDLexicalBlockFile *getImpl(LLVMContext &Context, MDLocalScope *Scope,
                                      MDFile *File, unsigned Discriminator,
@@ -1449,6 +1561,10 @@ public:
 
   TempMDLexicalBlockFile clone() const { return cloneImpl(); }
 
+  // TODO: Remove these once they're gone from MDLexicalBlockBase.
+  unsigned getLine() const = delete;
+  unsigned getColumn() const = delete;
+
   unsigned getDiscriminator() const { return Discriminator; }
 
   static bool classof(const Metadata *MD) {
@@ -1456,6 +1572,12 @@ public:
   }
 };
 
+unsigned MDLocation::getDiscriminator() const {
+  if (auto *F = dyn_cast<MDLexicalBlockFile>(getScope()))
+    return F->getDiscriminator();
+  return 0;
+}
+
 class MDNamespace : public MDScope {
   friend class LLVMContextImpl;
   friend class MDNode;
@@ -1467,7 +1589,7 @@ class MDNamespace : public MDScope {
       : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace,
                 Ops),
         Line(Line) {}
-  ~MDNamespace() {}
+  ~MDNamespace() = default;
 
   static MDNamespace *getImpl(LLVMContext &Context, MDScope *Scope,
                               MDFile *File, StringRef Name, unsigned Line,
@@ -1512,7 +1634,7 @@ protected:
   MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage,
                       unsigned Tag, ArrayRef<Metadata *> Ops)
       : DebugNode(Context, ID, Storage, Tag, Ops) {}
-  ~MDTemplateParameter() {}
+  ~MDTemplateParameter() = default;
 
 public:
   StringRef getName() const { return getStringOperand(0); }
@@ -1535,7 +1657,7 @@ class MDTemplateTypeParameter : public MDTemplateParameter {
                           ArrayRef<Metadata *> Ops)
       : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage,
                             dwarf::DW_TAG_template_type_parameter, Ops) {}
-  ~MDTemplateTypeParameter() {}
+  ~MDTemplateTypeParameter() = default;
 
   static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name,
                                           MDTypeRef Type, StorageType Storage,
@@ -1572,7 +1694,7 @@ class MDTemplateValueParameter : public MDTemplateParameter {
                            unsigned Tag, ArrayRef<Metadata *> Ops)
       : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag,
                             Ops) {}
-  ~MDTemplateValueParameter() {}
+  ~MDTemplateValueParameter() = default;
 
   static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag,
                                            StringRef Name, MDTypeRef Type,
@@ -1618,7 +1740,7 @@ protected:
   MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
              unsigned Line, ArrayRef<Metadata *> Ops)
       : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {}
-  ~MDVariable() {}
+  ~MDVariable() = default;
 
 public:
   unsigned getLine() const { return Line; }
@@ -1627,6 +1749,17 @@ public:
   MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); }
   MDTypeRef getType() const { return MDTypeRef(getRawType()); }
 
+  StringRef getFilename() const {
+    if (auto *F = getFile())
+      return F->getFilename();
+    return "";
+  }
+  StringRef getDirectory() const {
+    if (auto *F = getFile())
+      return F->getDirectory();
+    return "";
+  }
+
   Metadata *getRawScope() const { return getOperand(0); }
   MDString *getRawName() const { return getOperandAs<MDString>(1); }
   Metadata *getRawFile() const { return getOperand(2); }
@@ -1654,17 +1787,18 @@ class MDGlobalVariable : public MDVariable {
       : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable,
                    Line, Ops),
         IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {}
-  ~MDGlobalVariable() {}
+  ~MDGlobalVariable() = default;
 
   static MDGlobalVariable *
   getImpl(LLVMContext &Context, MDScope *Scope, StringRef Name,
           StringRef LinkageName, MDFile *File, unsigned Line, MDTypeRef Type,
-          bool IsLocalToUnit, bool IsDefinition, ConstantAsMetadata *Variable,
+          bool IsLocalToUnit, bool IsDefinition, Constant *Variable,
           MDDerivedType *StaticDataMemberDeclaration, StorageType Storage,
           bool ShouldCreate = true) {
     return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
                    getCanonicalMDString(Context, LinkageName), File, Line, Type,
-                   IsLocalToUnit, IsDefinition, Variable,
+                   IsLocalToUnit, IsDefinition,
+                   Variable ? ConstantAsMetadata::get(Variable) : nullptr,
                    StaticDataMemberDeclaration, Storage, ShouldCreate);
   }
   static MDGlobalVariable *
@@ -1685,8 +1819,7 @@ public:
   DEFINE_MDNODE_GET(MDGlobalVariable,
                     (MDScope * Scope, StringRef Name, StringRef LinkageName,
                      MDFile *File, unsigned Line, MDTypeRef Type,
-                     bool IsLocalToUnit, bool IsDefinition,
-                     ConstantAsMetadata *Variable,
+                     bool IsLocalToUnit, bool IsDefinition, Constant *Variable,
                      MDDerivedType *StaticDataMemberDeclaration),
                     (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
                      IsDefinition, Variable, StaticDataMemberDeclaration))
@@ -1704,8 +1837,10 @@ public:
   bool isDefinition() const { return IsDefinition; }
   StringRef getDisplayName() const { return getStringOperand(4); }
   StringRef getLinkageName() const { return getStringOperand(5); }
-  ConstantAsMetadata *getVariable() const {
-    return cast_or_null<ConstantAsMetadata>(getRawVariable());
+  Constant *getVariable() const {
+    if (auto *C = cast_or_null<ConstantAsMetadata>(getRawVariable()))
+      return dyn_cast<Constant>(C->getValue());
+    return nullptr;
   }
   MDDerivedType *getStaticDataMemberDeclaration() const {
     return cast_or_null<MDDerivedType>(getRawStaticDataMemberDeclaration());
@@ -1737,7 +1872,7 @@ class MDLocalVariable : public MDVariable {
                   ArrayRef<Metadata *> Ops)
       : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg),
         Flags(Flags) {}
-  ~MDLocalVariable() {}
+  ~MDLocalVariable() = default;
 
   static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag,
                                   MDScope *Scope, StringRef Name, MDFile *File,
@@ -1822,6 +1957,12 @@ public:
 
 /// \brief DWARF expression.
 ///
+/// This is (almost) a DWARF expression that modifies the location of a
+/// variable or (or the location of a single piece of a variable).
+///
+/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const
+/// and have DW_OP_plus consume the topmost elements on the stack.
+///
 /// TODO: Co-allocate the expression elements.
 /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary
 /// storage types.
@@ -1834,7 +1975,7 @@ class MDExpression : public MDNode {
   MDExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements)
       : MDNode(C, MDExpressionKind, Storage, None),
         Elements(Elements.begin(), Elements.end()) {}
-  ~MDExpression() {}
+  ~MDExpression() = default;
 
   static MDExpression *getImpl(LLVMContext &Context,
                                ArrayRef<uint64_t> Elements, StorageType Storage,
@@ -1973,7 +2114,7 @@ class MDObjCProperty : public DebugNode {
       : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property,
                   Ops),
         Line(Line), Attributes(Attributes) {}
-  ~MDObjCProperty() {}
+  ~MDObjCProperty() = default;
 
   static MDObjCProperty *
   getImpl(LLVMContext &Context, StringRef Name, MDFile *File, unsigned Line,
@@ -2018,8 +2159,24 @@ public:
   MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); }
   StringRef getGetterName() const { return getStringOperand(2); }
   StringRef getSetterName() const { return getStringOperand(3); }
+
+  /// \brief Get the type.
+  ///
+  /// \note Objective-C doesn't have an ODR, so there is no benefit in storing
+  /// the type as a DITypeRef here.
   MDType *getType() const { return cast_or_null<MDType>(getRawType()); }
 
+  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); }
   MDString *getRawGetterName() const { return getOperandAs<MDString>(2); }
@@ -2031,6 +2188,7 @@ public:
   }
 };
 
+/// \brief An imported module (C++ using directive or similar).
 class MDImportedEntity : public DebugNode {
   friend class LLVMContextImpl;
   friend class MDNode;
@@ -2040,7 +2198,7 @@ class MDImportedEntity : public DebugNode {
   MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag,
                    unsigned Line, ArrayRef<Metadata *> Ops)
       : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {}
-  ~MDImportedEntity() {}
+  ~MDImportedEntity() = default;
 
   static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag,
                                    MDScope *Scope, DebugNodeRef Entity,