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 | c70f1d63f89258d1da24e7419b15fa58a61e6607 (patch) | |
tree | 4f781286647f9e7a65b4fdf6b6c7a6760bd4b057 /clang/lib/Sema/SemaStmt.cpp | |
parent | ee27d2ebae8b57f3d2e6788efaed75494ff2d2ac (diff) | |
download | bcm5719-llvm-c70f1d63f89258d1da24e7419b15fa58a61e6607.tar.gz bcm5719-llvm-c70f1d63f89258d1da24e7419b15fa58a61e6607.zip |
[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'.
llvm-svn: 320707
Diffstat (limited to 'clang/lib/Sema/SemaStmt.cpp')
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 45b73f0a2bf..ff0f4d99585 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/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, "="); } |