summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/AST/ExprConstant.cpp22
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp28
-rw-r--r--clang/lib/Sema/SemaChecking.cpp9
-rw-r--r--clang/test/CodeGen/complex-math.c51
-rw-r--r--clang/test/SemaCXX/complex-folding.cpp8
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.
OpenPOWER on IntegriCloud