diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 22 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 9 | ||||
-rw-r--r-- | clang/test/CodeGen/complex-math.c | 51 | ||||
-rw-r--r-- | clang/test/SemaCXX/complex-folding.cpp | 8 |
5 files changed, 106 insertions, 12 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index db300c4fec4..532720666bc 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -6780,15 +6780,27 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { QualType LHSTy = E->getLHS()->getType(); QualType RHSTy = E->getRHS()->getType(); - if (LHSTy->isAnyComplexType()) { - assert(RHSTy->isAnyComplexType() && "Invalid comparison"); + if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) { ComplexValue LHS, RHS; - - bool LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); + bool LHSOK; + if (E->getLHS()->getType()->isRealFloatingType()) { + LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info); + if (LHSOK) { + LHS.makeComplexFloat(); + LHS.FloatImag = APFloat(LHS.FloatReal.getSemantics()); + } + } else { + LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); + } if (!LHSOK && !Info.keepEvaluatingAfterFailure()) return false; - if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) + if (E->getRHS()->getType()->isRealFloatingType()) { + if (!EvaluateFloat(E->getRHS(), RHS.FloatReal, Info) || !LHSOK) + return false; + RHS.makeComplexFloat(); + RHS.FloatImag = APFloat(RHS.FloatReal.getSemantics()); + } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) return false; if (LHS.isComplexFloat()) { diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index abde51f29e4..ac6afe48453 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2754,6 +2754,7 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc, TestAndClearIgnoreResultAssign(); Value *Result; QualType LHSTy = E->getLHS()->getType(); + QualType RHSTy = E->getRHS()->getType(); if (const MemberPointerType *MPT = LHSTy->getAs<MemberPointerType>()) { assert(E->getOpcode() == BO_EQ || E->getOpcode() == BO_NE); @@ -2761,7 +2762,7 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc, Value *RHS = CGF.EmitScalarExpr(E->getRHS()); Result = CGF.CGM.getCXXABI().EmitMemberPointerComparison( CGF, LHS, RHS, MPT, E->getOpcode() == BO_NE); - } else if (!LHSTy->isAnyComplexType()) { + } else if (!LHSTy->isAnyComplexType() && !RHSTy->isAnyComplexType()) { Value *LHS = Visit(E->getLHS()); Value *RHS = Visit(E->getRHS()); @@ -2849,10 +2850,27 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc, } else { // Complex Comparison: can only be an equality comparison. - CodeGenFunction::ComplexPairTy LHS = CGF.EmitComplexExpr(E->getLHS()); - CodeGenFunction::ComplexPairTy RHS = CGF.EmitComplexExpr(E->getRHS()); - - QualType CETy = LHSTy->getAs<ComplexType>()->getElementType(); + CodeGenFunction::ComplexPairTy LHS, RHS; + QualType CETy; + if (auto *CTy = LHSTy->getAs<ComplexType>()) { + LHS = CGF.EmitComplexExpr(E->getLHS()); + CETy = CTy->getElementType(); + } else { + LHS.first = Visit(E->getLHS()); + LHS.second = llvm::Constant::getNullValue(LHS.first->getType()); + CETy = LHSTy; + } + if (auto *CTy = RHSTy->getAs<ComplexType>()) { + RHS = CGF.EmitComplexExpr(E->getRHS()); + assert(CGF.getContext().hasSameUnqualifiedType(CETy, + CTy->getElementType()) && + "The element types must always match."); + } else { + RHS.first = Visit(E->getRHS()); + RHS.second = llvm::Constant::getNullValue(RHS.first->getType()); + assert(CGF.getContext().hasSameUnqualifiedType(CETy, RHSTy) && + "The element types must always match."); + } Value *ResultR, *ResultI; if (CETy->isRealFloatingType()) { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index a856c98bf05..58c626351f9 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5890,8 +5890,13 @@ static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { static void AnalyzeComparison(Sema &S, BinaryOperator *E) { // The type the comparison is being performed in. QualType T = E->getLHS()->getType(); - assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType()) - && "comparison with mismatched types"); + + // Only analyze comparison operators where both sides have been converted to + // the same type. + if (!S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType())) + return AnalyzeImpConvsInComparison(S, E); + + // Don't analyze value-dependent comparisons directly. if (E->isValueDependent()) return AnalyzeImpConvsInComparison(S, E); diff --git a/clang/test/CodeGen/complex-math.c b/clang/test/CodeGen/complex-math.c index ca04e8d94d1..27540c78f77 100644 --- a/clang/test/CodeGen/complex-math.c +++ b/clang/test/CodeGen/complex-math.c @@ -367,3 +367,54 @@ long double _Complex div_long_double_cc(long double _Complex a, long double _Com // X86: ret return a / b; } + +// Comparison operators don't rely on library calls or have interseting math +// properties, but test that mixed types work correctly here. +_Bool eq_float_cr(float _Complex a, float b) { + // X86-LABEL: @eq_float_cr( + // X86: fcmp oeq + // X86: fcmp oeq + // X86: and i1 + // X86: ret + return a == b; +} +_Bool eq_float_rc(float a, float _Complex b) { + // X86-LABEL: @eq_float_rc( + // X86: fcmp oeq + // X86: fcmp oeq + // X86: and i1 + // X86: ret + return a == b; +} +_Bool eq_float_cc(float _Complex a, float _Complex b) { + // X86-LABEL: @eq_float_cc( + // X86: fcmp oeq + // X86: fcmp oeq + // X86: and i1 + // X86: ret + return a == b; +} +_Bool ne_float_cr(float _Complex a, float b) { + // X86-LABEL: @ne_float_cr( + // X86: fcmp une + // X86: fcmp une + // X86: or i1 + // X86: ret + return a != b; +} +_Bool ne_float_rc(float a, float _Complex b) { + // X86-LABEL: @ne_float_rc( + // X86: fcmp une + // X86: fcmp une + // X86: or i1 + // X86: ret + return a != b; +} +_Bool ne_float_cc(float _Complex a, float _Complex b) { + // X86-LABEL: @ne_float_cc( + // X86: fcmp une + // X86: fcmp une + // X86: or i1 + // X86: ret + return a != b; +} diff --git a/clang/test/SemaCXX/complex-folding.cpp b/clang/test/SemaCXX/complex-folding.cpp index 6a77bfdb310..1c2f9c73eb3 100644 --- a/clang/test/SemaCXX/complex-folding.cpp +++ b/clang/test/SemaCXX/complex-folding.cpp @@ -3,6 +3,14 @@ // Test the constant folding of builtin complex numbers. static_assert((0.0 + 0.0j) == (0.0 + 0.0j)); +static_assert((0.0 + 0.0j) != (0.0 + 0.0j)); // expected-error {{static_assert}} + +static_assert((0.0 + 0.0j) == 0.0); +static_assert(0.0 == (0.0 + 0.0j)); +static_assert(0.0 == 0.0j); +static_assert((0.0 + 1.0j) != 0.0); +static_assert(1.0 != (0.0 + 0.0j)); +static_assert(0.0 != 1.0j); // Walk around the complex plane stepping between angular differences and // equality. |