summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-12-14 15:16:18 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-12-14 15:16:18 +0000
commit96881be75c9092dabbb19ccae56e64af7ad29e90 (patch)
treec9b12abbcccd5cf6d47b291289fbf7ba338cbdff /lib/Sema
parentf19939b529be1bdd8adce0ff0e648ab3ae0faa6a (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.cpp25
-rw-r--r--lib/Sema/SemaExpr.cpp8
-rw-r--r--lib/Sema/SemaOpenMP.cpp1
-rw-r--r--lib/Sema/SemaStmt.cpp37
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, "=");
}