IR: Avoid DIScopeRef in DIImportedEntity::getEntity()
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Wed, 18 Feb 2015 19:39:36 +0000 (19:39 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Wed, 18 Feb 2015 19:39:36 +0000 (19:39 +0000)
`DIImportedEntity::getEntity()` currently returns a `DIScopeRef`, but
the nodes it references aren't always `DIScope`s.  In particular, it can
reference global variables.

Introduce `DIDescriptorRef` to avoid the lie.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229733 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/DebugInfo.h
lib/IR/DebugInfo.cpp

index 73b4b1693b0218af9abe10f4e74e2b96ca89d08a..44c9ddf803b8c923016dce213832147c2587bc47 100644 (file)
@@ -294,6 +294,7 @@ public:
 };
 
 template <typename T> class DIRef;
+typedef DIRef<DIDescriptor> DIDescriptorRef;
 typedef DIRef<DIScope> DIScopeRef;
 typedef DIRef<DIType> DITypeRef;
 typedef DITypedArray<DITypeRef> DITypeArray;
@@ -383,6 +384,12 @@ template <typename T> StringRef DIRef<T>::getName() const {
   return MS->getString();
 }
 
+/// \brief Handle fields that are references to DIDescriptors.
+template <>
+DIDescriptorRef DIDescriptor::getFieldAs<DIDescriptorRef>(unsigned Elt) const;
+/// \brief Specialize DIRef constructor for DIDescriptorRef.
+template <> DIRef<DIDescriptor>::DIRef(const Metadata *V);
+
 /// \brief Handle fields that are references to DIScopes.
 template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
 /// \brief Specialize DIRef constructor for DIScopeRef.
@@ -1029,7 +1036,7 @@ class DIImportedEntity : public DIDescriptor {
 public:
   explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {}
   DIScope getContext() const { return getFieldAs<DIScope>(1); }
-  DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); }
+  DIDescriptorRef getEntity() const { return getFieldAs<DIDescriptorRef>(2); }
   unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); }
   StringRef getName() const { return getHeaderField(2); }
   bool Verify() const;
index 9a7ff062de061059e5a9d23e7a467a627f6187eb..32521b160a2e44abdcd3ce2f806fab90060fad4c 100644 (file)
@@ -426,6 +426,15 @@ static bool fieldIsScopeRef(const MDNode *DbgNode, unsigned Elt) {
   return isScopeRef(dyn_cast_or_null<Metadata>(getField(DbgNode, Elt)));
 }
 
+/// \brief Check if a value can be a DescriptorRef.
+static bool isDescriptorRef(const Metadata *MD) {
+  if (!MD)
+    return true;
+  if (auto *S = dyn_cast<MDString>(MD))
+    return !S->getString().empty();
+  return isa<MDNode>(MD);
+}
+
 bool DIType::Verify() const {
   if (!isType())
     return false;
@@ -1463,6 +1472,10 @@ void DIVariable::printExtendedName(raw_ostream &OS) const {
   }
 }
 
+template <> DIRef<DIDescriptor>::DIRef(const Metadata *V) : Val(V) {
+  assert(isDescriptorRef(V) &&
+         "DIDescriptorRef should be a MDString or MDNode");
+}
 template <> DIRef<DIScope>::DIRef(const Metadata *V) : Val(V) {
   assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode");
 }
@@ -1470,6 +1483,10 @@ template <> DIRef<DIType>::DIRef(const Metadata *V) : Val(V) {
   assert(isTypeRef(V) && "DITypeRef should be a MDString or MDNode");
 }
 
+template <>
+DIDescriptorRef DIDescriptor::getFieldAs<DIDescriptorRef>(unsigned Elt) const {
+  return DIDescriptorRef(cast_or_null<Metadata>(getField(DbgNode, Elt)));
+}
 template <>
 DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const {
   return DIScopeRef(cast_or_null<Metadata>(getField(DbgNode, Elt)));