+ /// Represents reference to a DIDescriptor, abstracts over direct and
+ /// identifier-based metadata references.
+ template <typename T>
+ class DIRef {
+ template <typename DescTy>
+ friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const;
+ friend DIScopeRef DIScope::getContext() const;
+ friend DIScopeRef DIScope::generateRef();
+
+ /// Val can be either a MDNode or a MDString, in the latter,
+ /// MDString specifies the type identifier.
+ const Value *Val;
+ explicit DIRef(const Value *V);
+ public:
+ T resolve(const DITypeIdentifierMap &Map) const {
+ if (!Val)
+ return T();
+
+ if (const MDNode *MD = dyn_cast<MDNode>(Val))
+ return T(MD);
+
+ const MDString *MS = cast<MDString>(Val);
+ // Find the corresponding MDNode.
+ DITypeIdentifierMap::const_iterator Iter = Map.find(MS);
+ assert(Iter != Map.end() && "Identifier not in the type map?");
+ assert(DIType(Iter->second).isType() &&
+ "MDNode in DITypeIdentifierMap should be a DIType.");
+ return T(Iter->second);
+ }
+ operator Value *() const { return const_cast<Value*>(Val); }
+ };
+
+ /// Specialize getFieldAs to handle fields that are references to DIScopes.
+ template <>
+ DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
+ /// Specialize DIRef constructor for DIScopeRef.
+ template <>
+ DIRef<DIScope>::DIRef(const Value *V);
+
+ typedef DIRef<DIType> DITypeRef;
+ /// Specialize getFieldAs to handle fields that are references to DITypes.
+ template <>
+ DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
+ /// Specialize DIRef constructor for DITypeRef.
+ template <>
+ DIRef<DIType>::DIRef(const Value *V);
+