Fix for PR5718: implement equality comparisons for member function pointers.

llvm-svn: 91108
This commit is contained in:
Eli Friedman 2009-12-11 07:36:43 +00:00
parent f6d9cebafd
commit 1762cf2ad0
2 changed files with 36 additions and 1 deletions

View File

@ -1571,7 +1571,34 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
TestAndClearIgnoreResultAssign();
Value *Result;
QualType LHSTy = E->getLHS()->getType();
if (!LHSTy->isAnyComplexType()) {
if (LHSTy->isMemberFunctionPointerType()) {
Value *LHSPtr = CGF.EmitAnyExprToTemp(E->getLHS()).getAggregateAddr();
Value *RHSPtr = CGF.EmitAnyExprToTemp(E->getRHS()).getAggregateAddr();
llvm::Value *LHSFunc = Builder.CreateStructGEP(LHSPtr, 0);
LHSFunc = Builder.CreateLoad(LHSFunc);
llvm::Value *RHSFunc = Builder.CreateStructGEP(RHSPtr, 0);
RHSFunc = Builder.CreateLoad(RHSFunc);
Value *ResultF = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
LHSFunc, RHSFunc, "cmp.func");
Value *NullPtr = llvm::Constant::getNullValue(LHSFunc->getType());
Value *ResultNull = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
LHSFunc, NullPtr, "cmp.null");
llvm::Value *LHSAdj = Builder.CreateStructGEP(LHSPtr, 1);
LHSAdj = Builder.CreateLoad(LHSAdj);
llvm::Value *RHSAdj = Builder.CreateStructGEP(RHSPtr, 1);
RHSAdj = Builder.CreateLoad(RHSAdj);
Value *ResultA = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
LHSAdj, RHSAdj, "cmp.adj");
if (E->getOpcode() == BinaryOperator::EQ) {
Result = Builder.CreateOr(ResultNull, ResultA, "or.na");
Result = Builder.CreateAnd(Result, ResultF, "and.f");
} else {
assert(E->getOpcode() == BinaryOperator::NE &&
"Member pointer comparison other than == or != ?");
Result = Builder.CreateAnd(ResultNull, ResultA, "and.na");
Result = Builder.CreateOr(Result, ResultF, "or.f");
}
} else if (!LHSTy->isAnyComplexType()) {
Value *LHS = Visit(E->getLHS());
Value *RHS = Visit(E->getRHS());

View File

@ -105,3 +105,11 @@ namespace PR5593 {
return f && f;
}
}
namespace PR5718 {
struct A { };
bool f(void (A::*f)(), void (A::*g)()) {
return f == g;
}
}