[PATCH] Fix UBSan error reports in ValueMapCallbackVH and AssertingVH<T> empty/tombstone keys generation.

Duncan P. N. Exon Smith dexonsmith at apple.com
Fri Jan 9 14:20:10 PST 2015


> On 2015-Jan-09, at 13:52, Chandler Carruth <chandlerc at gmail.com> wrote:
> 
> ================
> Comment at: include/llvm/IR/ValueHandle.h:192-203
> @@ -191,14 +191,14 @@
> 
> #ifndef NDEBUG
>   ValueTy *getValPtr() const {
>     return static_cast<ValueTy*>(ValueHandleBase::getValPtr());
>   }
>   void setValPtr(ValueTy *P) {
>     ValueHandleBase::operator=(GetAsValue(P));
>   }
> #else
> -  ValueTy *ThePtr;
> -  ValueTy *getValPtr() const { return ThePtr; }
> -  void setValPtr(ValueTy *P) { ThePtr = P; }
> +  Value *ThePtr;
> +  ValueTy *getValPtr() const { return static_cast<ValueTy *>(ThePtr); }
> +  void setValPtr(ValueTy *P) { ThePtr = GetAsValue(P); }
> #endif
> 
> ----------------
> I would define helpers here for getRawValPtr and setRawValPtr which do the indirection between NDEBUG and debug builds. Then use them below (see comments).
> 
> ================
> Comment at: include/llvm/IR/ValueHandle.h:239-272
> @@ -239,23 +238,36 @@
> struct DenseMapInfo<AssertingVH<T> > {
> -  typedef DenseMapInfo<T*> PointerInfo;
>   static inline AssertingVH<T> getEmptyKey() {
> -    return AssertingVH<T>(PointerInfo::getEmptyKey());
> +    AssertingVH<T> Res;
> +    Value *V = DenseMapInfo<Value *>::getEmptyKey();
> +#ifndef NDEBUG
> +    Res.ValueHandleBase::operator=(V);
> +#else
> +    Res.ThePtr = V;
> +#endif
> +    return Res;
>   }
> -  static inline T* getTombstoneKey() {
> -    return AssertingVH<T>(PointerInfo::getTombstoneKey());
> +  static inline AssertingVH<T> getTombstoneKey() {
> +    AssertingVH<T> Res;
> +    Value *V = DenseMapInfo<Value *>::getTombstoneKey();
> +#ifndef NDEBUG
> +    Res.ValueHandleBase::operator=(V);
> +#else
> +    Res.ThePtr = V;
> +#endif
> +    return Res;
>   }
>   static unsigned getHashValue(const AssertingVH<T> &Val) {
> -    return PointerInfo::getHashValue(Val);
> +    return DenseMapInfo<T *>::getHashValue(Val);
>   }
> #ifndef NDEBUG
>   static bool isEqual(const AssertingVH<T> &LHS, const AssertingVH<T> &RHS) {
>     // Avoid downcasting AssertingVH<T> to T*, as empty/tombstone keys may not
>     // be properly aligned pointers to T*.
>     return LHS.ValueHandleBase::getValPtr() == RHS.ValueHandleBase::getValPtr();
>   }
> #else
>   static bool isEqual(const AssertingVH<T> &LHS, const AssertingVH<T> &RHS) {
>     return LHS == RHS;
>   }
> #endif
> };
> ----------------
> All of these NDEBUG vs. not can go away by using helpers defined once in the class above to get the raw Value* and set the raw Value*.
> 
> I also think you want to have both isEqual and getHashValue use the raw Value* and delegate to DenseMapInfo<Value *>.
> 

Just in case you're waiting for something from me, this LGTM (once
Chandler's happy).  Thanks for doing this.

> http://reviews.llvm.org/D6903
> 
> EMAIL PREFERENCES
>  http://reviews.llvm.org/settings/panel/emailpreferences/
> 
> 





More information about the llvm-commits mailing list