summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-02-18 19:39:36 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-02-18 19:39:36 +0000
commit2a78e9bcb5b0f05e60e9a4820c40ca3c53664221 (patch)
tree0947d2b985d2ae0d4258114c9d07f7d2a5cc0608
parentf5f9badbbeb905e8a979ee7813232233bc8bc2f1 (diff)
downloadbcm5719-llvm-2a78e9bcb5b0f05e60e9a4820c40ca3c53664221.tar.gz
bcm5719-llvm-2a78e9bcb5b0f05e60e9a4820c40ca3c53664221.zip
IR: Avoid DIScopeRef in DIImportedEntity::getEntity()
`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. llvm-svn: 229733
-rw-r--r--llvm/include/llvm/IR/DebugInfo.h9
-rw-r--r--llvm/lib/IR/DebugInfo.cpp17
2 files changed, 25 insertions, 1 deletions
diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h
index 73b4b1693b0..44c9ddf803b 100644
--- a/llvm/include/llvm/IR/DebugInfo.h
+++ b/llvm/include/llvm/IR/DebugInfo.h
@@ -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;
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 9a7ff062de0..32521b160a2 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -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");
}
@@ -1471,6 +1484,10 @@ template <> DIRef<DIType>::DIRef(const Metadata *V) : Val(V) {
}
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)));
}
OpenPOWER on IntegriCloud