forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Catches us up, but there are issues: this xfails 3 tests llvm/test/CodeGen/AMDGPU/tail-call-inreg-arguments.error.ll clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp fixme section in llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp Change-Id: Ia1367740343fba1dd5e4d46f6ffb4a56c2ca8600
- Loading branch information
Showing
1,079 changed files
with
25,902 additions
and
14,065 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
216 changes: 216 additions & 0 deletions
216
clang-tools-extra/clangd/refactor/tweaks/SwapBinaryOperands.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
//===--- SwapBinaryOperands.cpp ----------------------------------*- C++-*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
#include "ParsedAST.h" | ||
#include "Protocol.h" | ||
#include "Selection.h" | ||
#include "SourceCode.h" | ||
#include "refactor/Tweak.h" | ||
#include "support/Logger.h" | ||
#include "clang/AST/ASTContext.h" | ||
#include "clang/AST/Expr.h" | ||
#include "clang/AST/OperationKinds.h" | ||
#include "clang/AST/Stmt.h" | ||
#include "clang/Basic/LLVM.h" | ||
#include "clang/Basic/SourceLocation.h" | ||
#include "clang/Tooling/Core/Replacement.h" | ||
#include "llvm/ADT/StringRef.h" | ||
#include "llvm/Support/Casting.h" | ||
#include "llvm/Support/FormatVariadic.h" | ||
#include <string> | ||
#include <utility> | ||
|
||
namespace clang { | ||
namespace clangd { | ||
namespace { | ||
/// Check whether it makes logical sense to swap operands to an operator. | ||
/// Assignment or member access operators are rarely swappable | ||
/// while keeping the meaning intact, whereas comparison operators, mathematical | ||
/// operators, etc. are often desired to be swappable for readability, avoiding | ||
/// bugs by assigning to nullptr when comparison was desired, etc. | ||
bool isOpSwappable(const BinaryOperatorKind Opcode) { | ||
switch (Opcode) { | ||
case BinaryOperatorKind::BO_Mul: | ||
case BinaryOperatorKind::BO_Add: | ||
case BinaryOperatorKind::BO_LT: | ||
case BinaryOperatorKind::BO_GT: | ||
case BinaryOperatorKind::BO_LE: | ||
case BinaryOperatorKind::BO_GE: | ||
case BinaryOperatorKind::BO_EQ: | ||
case BinaryOperatorKind::BO_NE: | ||
case BinaryOperatorKind::BO_And: | ||
case BinaryOperatorKind::BO_Xor: | ||
case BinaryOperatorKind::BO_Or: | ||
case BinaryOperatorKind::BO_LAnd: | ||
case BinaryOperatorKind::BO_LOr: | ||
case BinaryOperatorKind::BO_Comma: | ||
return true; | ||
// Noncommutative operators: | ||
case BinaryOperatorKind::BO_Div: | ||
case BinaryOperatorKind::BO_Sub: | ||
case BinaryOperatorKind::BO_Shl: | ||
case BinaryOperatorKind::BO_Shr: | ||
case BinaryOperatorKind::BO_Rem: | ||
// <=> is noncommutative | ||
case BinaryOperatorKind::BO_Cmp: | ||
// Member access: | ||
case BinaryOperatorKind::BO_PtrMemD: | ||
case BinaryOperatorKind::BO_PtrMemI: | ||
// Assignment: | ||
case BinaryOperatorKind::BO_Assign: | ||
case BinaryOperatorKind::BO_MulAssign: | ||
case BinaryOperatorKind::BO_DivAssign: | ||
case BinaryOperatorKind::BO_RemAssign: | ||
case BinaryOperatorKind::BO_AddAssign: | ||
case BinaryOperatorKind::BO_SubAssign: | ||
case BinaryOperatorKind::BO_ShlAssign: | ||
case BinaryOperatorKind::BO_ShrAssign: | ||
case BinaryOperatorKind::BO_AndAssign: | ||
case BinaryOperatorKind::BO_XorAssign: | ||
case BinaryOperatorKind::BO_OrAssign: | ||
return false; | ||
} | ||
return false; | ||
} | ||
|
||
/// Some operators are asymmetric and need to be flipped when swapping their | ||
/// operands | ||
/// @param[out] Opcode the opcode to potentially swap | ||
/// If the opcode does not need to be swapped or is not swappable, does nothing | ||
BinaryOperatorKind swapOperator(const BinaryOperatorKind Opcode) { | ||
switch (Opcode) { | ||
case BinaryOperatorKind::BO_LT: | ||
return BinaryOperatorKind::BO_GT; | ||
|
||
case BinaryOperatorKind::BO_GT: | ||
return BinaryOperatorKind::BO_LT; | ||
|
||
case BinaryOperatorKind::BO_LE: | ||
return BinaryOperatorKind::BO_GE; | ||
|
||
case BinaryOperatorKind::BO_GE: | ||
return BinaryOperatorKind::BO_LE; | ||
|
||
case BinaryOperatorKind::BO_Mul: | ||
case BinaryOperatorKind::BO_Add: | ||
case BinaryOperatorKind::BO_Cmp: | ||
case BinaryOperatorKind::BO_EQ: | ||
case BinaryOperatorKind::BO_NE: | ||
case BinaryOperatorKind::BO_And: | ||
case BinaryOperatorKind::BO_Xor: | ||
case BinaryOperatorKind::BO_Or: | ||
case BinaryOperatorKind::BO_LAnd: | ||
case BinaryOperatorKind::BO_LOr: | ||
case BinaryOperatorKind::BO_Comma: | ||
case BinaryOperatorKind::BO_Div: | ||
case BinaryOperatorKind::BO_Sub: | ||
case BinaryOperatorKind::BO_Shl: | ||
case BinaryOperatorKind::BO_Shr: | ||
case BinaryOperatorKind::BO_Rem: | ||
case BinaryOperatorKind::BO_PtrMemD: | ||
case BinaryOperatorKind::BO_PtrMemI: | ||
case BinaryOperatorKind::BO_Assign: | ||
case BinaryOperatorKind::BO_MulAssign: | ||
case BinaryOperatorKind::BO_DivAssign: | ||
case BinaryOperatorKind::BO_RemAssign: | ||
case BinaryOperatorKind::BO_AddAssign: | ||
case BinaryOperatorKind::BO_SubAssign: | ||
case BinaryOperatorKind::BO_ShlAssign: | ||
case BinaryOperatorKind::BO_ShrAssign: | ||
case BinaryOperatorKind::BO_AndAssign: | ||
case BinaryOperatorKind::BO_XorAssign: | ||
case BinaryOperatorKind::BO_OrAssign: | ||
return Opcode; | ||
} | ||
} | ||
|
||
/// Swaps the operands to a binary operator | ||
/// Before: | ||
/// x != nullptr | ||
/// ^ ^^^^^^^ | ||
/// After: | ||
/// nullptr != x | ||
class SwapBinaryOperands : public Tweak { | ||
public: | ||
const char *id() const final; | ||
|
||
bool prepare(const Selection &Inputs) override; | ||
Expected<Effect> apply(const Selection &Inputs) override; | ||
std::string title() const override { | ||
return llvm::formatv("Swap operands to {0}", | ||
Op ? Op->getOpcodeStr() : "binary operator"); | ||
} | ||
llvm::StringLiteral kind() const override { | ||
return CodeAction::REFACTOR_KIND; | ||
} | ||
bool hidden() const override { return false; } | ||
|
||
private: | ||
const BinaryOperator *Op; | ||
}; | ||
|
||
REGISTER_TWEAK(SwapBinaryOperands) | ||
|
||
bool SwapBinaryOperands::prepare(const Selection &Inputs) { | ||
for (const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor(); | ||
N && !Op; N = N->Parent) { | ||
// Stop once we hit a block, e.g. a lambda in one of the operands. | ||
// This makes sure that the selection point is in the 'scope' of the binary | ||
// operator, not from somewhere inside a lambda for example | ||
// (5 < [](){ ^return 1; }) | ||
if (llvm::isa_and_nonnull<CompoundStmt>(N->ASTNode.get<Stmt>())) | ||
return false; | ||
Op = dyn_cast_or_null<BinaryOperator>(N->ASTNode.get<Stmt>()); | ||
// If we hit upon a nonswappable binary operator, ignore and keep going | ||
if (Op && !isOpSwappable(Op->getOpcode())) { | ||
Op = nullptr; | ||
} | ||
} | ||
return Op != nullptr; | ||
} | ||
|
||
Expected<Tweak::Effect> SwapBinaryOperands::apply(const Selection &Inputs) { | ||
const auto &Ctx = Inputs.AST->getASTContext(); | ||
const auto &SrcMgr = Inputs.AST->getSourceManager(); | ||
|
||
const auto LHSRng = toHalfOpenFileRange(SrcMgr, Ctx.getLangOpts(), | ||
Op->getLHS()->getSourceRange()); | ||
if (!LHSRng) | ||
return error( | ||
"Could not obtain range of the 'lhs' of the operator. Macros?"); | ||
const auto RHSRng = toHalfOpenFileRange(SrcMgr, Ctx.getLangOpts(), | ||
Op->getRHS()->getSourceRange()); | ||
if (!RHSRng) | ||
return error( | ||
"Could not obtain range of the 'rhs' of the operator. Macros?"); | ||
const auto OpRng = | ||
toHalfOpenFileRange(SrcMgr, Ctx.getLangOpts(), Op->getOperatorLoc()); | ||
if (!OpRng) | ||
return error("Could not obtain range of the operator itself. Macros?"); | ||
|
||
const auto LHSCode = toSourceCode(SrcMgr, *LHSRng); | ||
const auto RHSCode = toSourceCode(SrcMgr, *RHSRng); | ||
const auto OperatorCode = toSourceCode(SrcMgr, *OpRng); | ||
|
||
tooling::Replacements Result; | ||
if (auto Err = Result.add(tooling::Replacement( | ||
Ctx.getSourceManager(), LHSRng->getBegin(), LHSCode.size(), RHSCode))) | ||
return std::move(Err); | ||
if (auto Err = Result.add(tooling::Replacement( | ||
Ctx.getSourceManager(), RHSRng->getBegin(), RHSCode.size(), LHSCode))) | ||
return std::move(Err); | ||
const auto SwappedOperator = swapOperator(Op->getOpcode()); | ||
if (auto Err = Result.add(tooling::Replacement( | ||
Ctx.getSourceManager(), OpRng->getBegin(), OperatorCode.size(), | ||
Op->getOpcodeStr(SwappedOperator)))) | ||
return std::move(Err); | ||
return Effect::mainFileEdit(SrcMgr, std::move(Result)); | ||
} | ||
|
||
} // namespace | ||
} // namespace clangd | ||
} // namespace clang |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.