diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-12-14 15:16:18 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-12-14 15:16:18 +0000 |
commit | 96881be75c9092dabbb19ccae56e64af7ad29e90 (patch) | |
tree | c9b12abbcccd5cf6d47b291289fbf7ba338cbdff /lib/Sema | |
parent | f19939b529be1bdd8adce0ff0e648ab3ae0faa6a (diff) |
[c++20] P0515R3: Parsing support and basic AST construction for operator <=>.
Adding the new enumerator forced a bunch more changes into this patch than I
would have liked. The -Wtautological-compare warning was extended to properly
check the new comparison operator, clang-format needed updating because it uses
precedence levels as weights for determining where to break lines (and several
operators increased their precedence levels with this change), thread-safety
analysis needed changes to build its own IL properly for the new operator.
All "real" semantic checking for this operator has been deferred to a future
patch. For now, we use the relational comparison rules and arbitrarily give
the builtin form of the operator a return type of 'void'.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@320707 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaOpenMP.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 37 |
4 files changed, 52 insertions, 19 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 9ed21daad6..94070bb9c9 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -7279,8 +7279,8 @@ static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E, if (!Size) return false; - // if E is binop and op is >, <, >=, <=, ==, &&, ||: - if (!Size->isComparisonOp() && !Size->isEqualityOp() && !Size->isLogicalOp()) + // if E is binop and op is <=>, >, <, >=, <=, ==, &&, ||: + if (!Size->isComparisonOp() && !Size->isLogicalOp()) return false; SourceRange SizeRange = Size->getSourceRange(); @@ -8433,6 +8433,8 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { if (const auto *BO = dyn_cast<BinaryOperator>(E)) { switch (BO->getOpcode()) { + case BO_Cmp: + llvm_unreachable("builtin <=> should have class type"); // Boolean-valued operations are single-bit and positive. case BO_LAnd: @@ -8747,9 +8749,18 @@ struct PromotedRange { llvm_unreachable("impossible compare result"); } - static llvm::Optional<bool> constantValue(BinaryOperatorKind Op, - ComparisonResult R, - bool ConstantOnRHS) { + static llvm::Optional<StringRef> + constantValue(BinaryOperatorKind Op, ComparisonResult R, bool ConstantOnRHS) { + if (Op == BO_Cmp) { + ComparisonResult LTFlag = LT, GTFlag = GT; + if (ConstantOnRHS) std::swap(LTFlag, GTFlag); + + if (R & EQ) return StringRef("'std::strong_ordering::equal'"); + if (R & LTFlag) return StringRef("'std::strong_ordering::less'"); + if (R & GTFlag) return StringRef("'std::strong_ordering::greater'"); + return llvm::None; + } + ComparisonResult TrueFlag, FalseFlag; if (Op == BO_EQ) { TrueFlag = EQ; @@ -8769,9 +8780,9 @@ struct PromotedRange { std::swap(TrueFlag, FalseFlag); } if (R & TrueFlag) - return true; + return StringRef("true"); if (R & FalseFlag) - return false; + return StringRef("false"); return llvm::None; } }; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8c6d11b495..929806ac6b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -11375,6 +11375,7 @@ BinaryOperatorKind Sema::ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind) { case tok::greater: Opc = BO_GT; break; case tok::exclaimequal: Opc = BO_NE; break; case tok::equalequal: Opc = BO_EQ; break; + case tok::spaceship: Opc = BO_Cmp; break; case tok::amp: Opc = BO_And; break; case tok::caret: Opc = BO_Xor; break; case tok::pipe: Opc = BO_Or; break; @@ -11683,6 +11684,13 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, ConvertHalfVec = true; ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, false); break; + case BO_Cmp: + // FIXME: Implement proper semantic checking of '<=>'. + ConvertHalfVec = true; + ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true); + if (!ResultTy.isNull()) + ResultTy = Context.VoidTy; + break; case BO_And: checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc); LLVM_FALLTHROUGH; diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index b932338857..b34bb3388d 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -10343,6 +10343,7 @@ static bool ActOnOMPReductionKindClause( case BO_GE: case BO_EQ: case BO_NE: + case BO_Cmp: case BO_AndAssign: case BO_XorAssign: case BO_OrAssign: diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 45b73f0a2b..ff0f4d9958 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -127,34 +127,47 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) { /// warning from firing. static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) { SourceLocation Loc; - bool IsNotEqual, CanAssign, IsRelational; + bool CanAssign; + enum { Equality, Inequality, Relational, ThreeWay } Kind; if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) { if (!Op->isComparisonOp()) return false; - IsRelational = Op->isRelationalOp(); + if (Op->getOpcode() == BO_EQ) + Kind = Equality; + else if (Op->getOpcode() == BO_NE) + Kind = Inequality; + else if (Op->getOpcode() == BO_Cmp) + Kind = ThreeWay; + else { + assert(Op->isRelationalOp()); + Kind = Relational; + } Loc = Op->getOperatorLoc(); - IsNotEqual = Op->getOpcode() == BO_NE; CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue(); } else if (const CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E)) { switch (Op->getOperator()) { - default: - return false; case OO_EqualEqual: + Kind = Equality; + break; case OO_ExclaimEqual: - IsRelational = false; + Kind = Inequality; break; case OO_Less: case OO_Greater: case OO_GreaterEqual: case OO_LessEqual: - IsRelational = true; + Kind = Relational; break; + case OO_Spaceship: + Kind = ThreeWay; + break; + default: + return false; } Loc = Op->getOperatorLoc(); - IsNotEqual = Op->getOperator() == OO_ExclaimEqual; CanAssign = Op->getArg(0)->IgnoreParenImpCasts()->isLValue(); } else { // Not a typo-prone comparison. @@ -167,15 +180,15 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) { return false; S.Diag(Loc, diag::warn_unused_comparison) - << (unsigned)IsRelational << (unsigned)IsNotEqual << E->getSourceRange(); + << (unsigned)Kind << E->getSourceRange(); // If the LHS is a plausible entity to assign to, provide a fixit hint to // correct common typos. - if (!IsRelational && CanAssign) { - if (IsNotEqual) + if (CanAssign) { + if (Kind == Inequality) S.Diag(Loc, diag::note_inequality_comparison_to_or_assign) << FixItHint::CreateReplacement(Loc, "|="); - else + else if (Kind == Equality) S.Diag(Loc, diag::note_equality_comparison_to_assign) << FixItHint::CreateReplacement(Loc, "="); } |