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