<span style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">>   case Float:</span><br style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)"><span style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">>     return A.getFloat().bitwiseIsEqual(B.</span><span style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">getFloat());</span><div>
<font face="arial, sans-serif"><br></font><div><font face="arial, sans-serif">I don't think that this comparison is correct for IEEE floating point numbers. For example, two bit-identical NaN's will compare equal, when they should compare not-equal. I haven't used APFloat before, but from browsing the Doxygen, I think the comparison should be:</font></div>
<div><span style="font-family:arial,sans-serif"><br></span></div><div><span style="font-family:arial,sans-serif">    A.getFloat().compare(B.getFloat()) == cmpEqual</span></div><div><font face="arial, sans-serif"><br></font></div>
<div><font face="arial, sans-serif">--Sean Silva<br></font><br><div class="gmail_quote">On Fri, Jun 15, 2012 at 12:38 AM, Andy Gibbs <span dir="ltr"><<a href="mailto:andyg1001@hotmail.co.uk" target="_blank">andyg1001@hotmail.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Jordan,<br>
<br>
Thanks for your pointers.  I've implemented an "isEqual" function as below.<br>
If you have time, would you mind having a quick skim through please to see<br>
if I've caught the right idea.  At the moment, it holds up to the testing I<br>
have performed so far, but I'm always working on more test-cases!<br>
<br>
At this point, my concern is not that isEqual may not fully distinguish two<br>
APValues that *are* equal, more that it should never say two APValues are<br>
equal when they aren't.  False negatives are much less of an issue than<br>
false positives!<br>
<br>
I haven't implemented equality checking for member pointers, yet.  Again,<br>
this is due to a lack of understand on exactly how to implement this check<br>
(it seems even the dump / printPretty functions have not been fully<br>
implemented for this type).<br>
<br>
If you think my approach is valid, then I will post a tentative patch for<br>
<a href="http://llvm.org/bugs/show_bug.cgi?id=12850" target="_blank">http://llvm.org/bugs/show_bug.cgi?id=12850</a>.<br>
<br>
Many, many thanks<br>
<br>
Andy<br>
<br>
<br>
// static member function of APValue<br>
bool APValue::isEqual(const APValue &A, const APValue &B) {<br>
  if (A.getKind() != B.getKind())<br>
    return false;<br>
<br>
  switch (A.getKind()) {<br>
    case Uninitialized:<br>
      return true;<br>
<br>
    case Int:<br>
      return (A.getInt() == B.getInt());<br>
<br>
    case Float:<br>
      return A.getFloat().bitwiseIsEqual(B.getFloat());<br>
<br>
    case ComplexInt:<br>
      return (A.getComplexIntReal() == B.getComplexIntReal()) &&<br>
             (A.getComplexIntImag() == B.getComplexIntImag());<br>
<br>
    case ComplexFloat:<br>
      return A.getComplexFloatReal().bitwiseIsEqual(B.getComplexFloatReal())<br>
&&<br>
             A.getComplexFloatImag().bitwiseIsEqual(B.getComplexFloatImag());<br>
<br>
    case Vector: {<br>
      unsigned len = A.getVectorLength();<br>
      if (len != B.getVectorLength()) return false;<br>
      for (unsigned i = 0; i != len; ++i) {<br>
        if (!isEqual(A.getVectorElt(i), B.getVectorElt(i)))<br>
          return false;<br>
      }<br>
      return true;<br>
    }<br>
<br>
    case Array: {<br>
      unsigned len = A.getArraySize();<br>
      if (len != B.getArraySize()) return false;<br>
<br>
      APValue FillerA, FillerB;<br>
      if (A.hasArrayFiller()) FillerA = A.getArrayFiller();<br>
      if (B.hasArrayFiller()) FillerB = B.getArrayFiller();<br>
<br>
      // Two arrays are equal if their initialised elements are equal,<br>
      // but also where one array is more initialised than another, where<br>
      // those additional initialised elements are equal to the filler<br>
      // of the other.  If they both contain uninitialised elements, the<br>
      // fillers must also match.<br>
      for (unsigned i = 0, a = A.getArrayInitializedElts(),<br>
                           b = B.getArrayInitializedElts(); i != len; ++i) {<br>
        if (!isEqual(<br>
              (i < a) ? A.getArrayInitializedElt(i) : FillerA,<br>
              (i < b) ? B.getArrayInitializedElt(i) : FillerB))<br>
          return false;<br>
        if (i >= a && i >= b) // all the initialised elements *and* the<br>
          break;              // fillers have been compared; we're equal!<br>
      }<br>
      return true;<br>
    }<br>
<br>
    case Struct: {<br>
      unsigned bases = A.getStructNumBases();<br>
      if (bases != B.getStructNumBases()) return false;<br>
<br>
      unsigned fields = A.getStructNumFields();<br>
      if (fields != B.getStructNumFields()) return false;<br>
<br>
      for (unsigned i = 0; i != bases; ++i) {<br>
        if (!isEqual(A.getStructBase(i), B.getStructBase(i)))<br>
          return false;<br>
      }<br>
<br>
      for (unsigned i = 0; i != fields; ++i) {<br>
        if (!isEqual(A.getStructField(i), B.getStructField(i)))<br>
          return false;<br>
      }<br>
<br>
      return true;<br>
    }<br>
<br>
    case Union:<br>
      return (A.getUnionField() == B.getUnionField()) &&<br>
             (isEqual(A.getUnionValue(), B.getUnionValue()));<br>
<br>
    case AddrLabelDiff:<br>
      return (A.getAddrLabelDiffLHS() == B.getAddrLabelDiffLHS()) &&<br>
             (A.getAddrLabelDiffRHS() == B.getAddrLabelDiffRHS());<br>
<br>
    case LValue: {<br>
      LValueBase BaseA = A.getLValueBase();<br>
      LValueBase BaseB = B.getLValueBase();<br>
<br>
      // null pointers are not comparable<br>
      if (!BaseA || !BaseB || BaseA.isNull() || BaseB.isNull()) return<br>
false;<br>
<br>
      bool IsValueDecl = BaseA.is<const ValueDecl*>();<br>
      if (IsValueDecl != BaseB.is<const ValueDecl*>()) return false;<br>
<br>
      QualType ElemTy;<br>
      if (IsValueDecl) {<br>
        const ValueDecl *VD = BaseA.get<const ValueDecl*>();<br>
        ElemTy = VD->getType();<br>
        if (VD != BaseB.get<const ValueDecl*>()) return false;<br>
      } else {<br>
        const Expr *E = BaseA.get<const Expr*>();<br>
        ElemTy = E->getType();<br>
        if (E != BaseB.get<const Expr*>()) return false;<br>
      }<br>
<br>
      bool HasPath = A.hasLValuePath();<br>
      if (HasPath != B.hasLValuePath()) return false;<br>
<br>
      if (!HasPath) {<br>
        return A.getLValueOffset() == B.getLValueOffset();<br>
      }<br>
<br>
      ArrayRef<LValuePathEntry> PathA = A.getLValuePath();<br>
      ArrayRef<LValuePathEntry> PathB = B.getLValuePath();<br>
      if (PathA.size() != PathB.size()) return false;<br>
<br>
      for (unsigned I = 0, N = PathA.size(); I != N; ++I) {<br>
        if (ElemTy->getAs<RecordType>()) {<br>
          const Decl *BaseOrMemberA =<br>
BaseOrMemberType::getFromOpaqueValue(PathA[I].BaseOrMember).getPointer();<br>
          const Decl *BaseOrMemberB =<br>
BaseOrMemberType::getFromOpaqueValue(PathB[I].BaseOrMember).getPointer();<br>
<br>
          if (BaseOrMemberA != BaseOrMemberB) return false;<br>
          if (const CXXRecordDecl *RD =<br>
dyn_cast<CXXRecordDecl>(BaseOrMemberA)) {<br>
            const Type *T = RD->getTypeForDecl();<br>
            assert(T && "getTypeForDecl did not return a valid value");<br>
            ElemTy = QualType(T, 0);<br>
          } else {<br>
            const ValueDecl *VD = cast<ValueDecl>(BaseOrMemberA);<br>
            ElemTy = VD->getType();<br>
          }<br>
        } else {<br>
          if (PathA[I].ArrayIndex != PathB[I].ArrayIndex) return false;<br>
<br>
          assert(dyn_cast<ArrayType>(ElemTy) && "Unexpected ElemTy");<br>
          ElemTy = dyn_cast<ArrayType>(ElemTy)->getElementType();<br>
        }<br>
      }<br>
<br>
      return true;<br>
    }<br>
<br>
    case MemberPointer:<br>
      llvm_unreachable("isEqual unimplemented for this APValue kind!");<br>
      return false;<br>
  }<br>
  llvm_unreachable("Unknown APValue kind!");<br>
  return false;<br>
<div class="HOEnZb"><div class="h5">}<br>
<br>
<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
</div></div></blockquote></div><br></div></div>