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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229733 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan P. N. Exon Smith 2015-02-18 19:39:36 +00:00
parent 7994fa0a0e
commit 1cfad01081
2 changed files with 25 additions and 1 deletions

View 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;

View 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)));