diff options
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc/MisplacedWideningCastCheck.cpp')
| -rw-r--r-- | clang-tools-extra/clang-tidy/misc/MisplacedWideningCastCheck.cpp | 233 |
1 files changed, 0 insertions, 233 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/MisplacedWideningCastCheck.cpp b/clang-tools-extra/clang-tidy/misc/MisplacedWideningCastCheck.cpp deleted file mode 100644 index 2ba38b3120a..00000000000 --- a/clang-tools-extra/clang-tidy/misc/MisplacedWideningCastCheck.cpp +++ /dev/null @@ -1,233 +0,0 @@ -//===--- MisplacedWideningCastCheck.cpp - clang-tidy-----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "MisplacedWideningCastCheck.h" -#include "../utils/Matchers.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { -namespace misc { - -MisplacedWideningCastCheck::MisplacedWideningCastCheck( - StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), - CheckImplicitCasts(Options.get("CheckImplicitCasts", false)) {} - -void MisplacedWideningCastCheck::storeOptions( - ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "CheckImplicitCasts", CheckImplicitCasts); -} - -void MisplacedWideningCastCheck::registerMatchers(MatchFinder *Finder) { - const auto Calc = - expr(anyOf(binaryOperator( - anyOf(hasOperatorName("+"), hasOperatorName("-"), - hasOperatorName("*"), hasOperatorName("<<"))), - unaryOperator(hasOperatorName("~"))), - hasType(isInteger())) - .bind("Calc"); - - const auto ExplicitCast = explicitCastExpr(hasDestinationType(isInteger()), - has(ignoringParenImpCasts(Calc))); - const auto ImplicitCast = - implicitCastExpr(hasImplicitDestinationType(isInteger()), - has(ignoringParenImpCasts(Calc))); - const auto Cast = expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast"); - - Finder->addMatcher(varDecl(hasInitializer(Cast)), this); - Finder->addMatcher(returnStmt(hasReturnValue(Cast)), this); - Finder->addMatcher(callExpr(hasAnyArgument(Cast)), this); - Finder->addMatcher(binaryOperator(hasOperatorName("="), hasRHS(Cast)), this); - Finder->addMatcher( - binaryOperator(matchers::isComparisonOperator(), hasEitherOperand(Cast)), - this); -} - -static unsigned getMaxCalculationWidth(const ASTContext &Context, - const Expr *E) { - E = E->IgnoreParenImpCasts(); - - if (const auto *Bop = dyn_cast<BinaryOperator>(E)) { - unsigned LHSWidth = getMaxCalculationWidth(Context, Bop->getLHS()); - unsigned RHSWidth = getMaxCalculationWidth(Context, Bop->getRHS()); - if (Bop->getOpcode() == BO_Mul) - return LHSWidth + RHSWidth; - if (Bop->getOpcode() == BO_Add) - return std::max(LHSWidth, RHSWidth) + 1; - if (Bop->getOpcode() == BO_Rem) { - llvm::APSInt Val; - if (Bop->getRHS()->EvaluateAsInt(Val, Context)) - return Val.getActiveBits(); - } else if (Bop->getOpcode() == BO_Shl) { - llvm::APSInt Bits; - if (Bop->getRHS()->EvaluateAsInt(Bits, Context)) { - // We don't handle negative values and large values well. It is assumed - // that compiler warnings are written for such values so the user will - // fix that. - return LHSWidth + Bits.getExtValue(); - } - - // Unknown bitcount, assume there is truncation. - return 1024U; - } - } else if (const auto *Uop = dyn_cast<UnaryOperator>(E)) { - // There is truncation when ~ is used. - if (Uop->getOpcode() == UO_Not) - return 1024U; - - QualType T = Uop->getType(); - return T->isIntegerType() ? Context.getIntWidth(T) : 1024U; - } else if (const auto *I = dyn_cast<IntegerLiteral>(E)) { - return I->getValue().getActiveBits(); - } - - return Context.getIntWidth(E->getType()); -} - -static int relativeIntSizes(BuiltinType::Kind Kind) { - switch (Kind) { - case BuiltinType::UChar: - return 1; - case BuiltinType::SChar: - return 1; - case BuiltinType::Char_U: - return 1; - case BuiltinType::Char_S: - return 1; - case BuiltinType::UShort: - return 2; - case BuiltinType::Short: - return 2; - case BuiltinType::UInt: - return 3; - case BuiltinType::Int: - return 3; - case BuiltinType::ULong: - return 4; - case BuiltinType::Long: - return 4; - case BuiltinType::ULongLong: - return 5; - case BuiltinType::LongLong: - return 5; - case BuiltinType::UInt128: - return 6; - case BuiltinType::Int128: - return 6; - default: - return 0; - } -} - -static int relativeCharSizes(BuiltinType::Kind Kind) { - switch (Kind) { - case BuiltinType::UChar: - return 1; - case BuiltinType::SChar: - return 1; - case BuiltinType::Char_U: - return 1; - case BuiltinType::Char_S: - return 1; - case BuiltinType::Char16: - return 2; - case BuiltinType::Char32: - return 3; - default: - return 0; - } -} - -static int relativeCharSizesW(BuiltinType::Kind Kind) { - switch (Kind) { - case BuiltinType::UChar: - return 1; - case BuiltinType::SChar: - return 1; - case BuiltinType::Char_U: - return 1; - case BuiltinType::Char_S: - return 1; - case BuiltinType::WChar_U: - return 2; - case BuiltinType::WChar_S: - return 2; - default: - return 0; - } -} - -static bool isFirstWider(BuiltinType::Kind First, BuiltinType::Kind Second) { - int FirstSize, SecondSize; - if ((FirstSize = relativeIntSizes(First)) != 0 && - (SecondSize = relativeIntSizes(Second)) != 0) - return FirstSize > SecondSize; - if ((FirstSize = relativeCharSizes(First)) != 0 && - (SecondSize = relativeCharSizes(Second)) != 0) - return FirstSize > SecondSize; - if ((FirstSize = relativeCharSizesW(First)) != 0 && - (SecondSize = relativeCharSizesW(Second)) != 0) - return FirstSize > SecondSize; - return false; -} - -void MisplacedWideningCastCheck::check(const MatchFinder::MatchResult &Result) { - const auto *Cast = Result.Nodes.getNodeAs<CastExpr>("Cast"); - if (!CheckImplicitCasts && isa<ImplicitCastExpr>(Cast)) - return; - if (Cast->getLocStart().isMacroID()) - return; - - const auto *Calc = Result.Nodes.getNodeAs<Expr>("Calc"); - if (Calc->getLocStart().isMacroID()) - return; - - if (Cast->isTypeDependent() || Cast->isValueDependent() || - Calc->isTypeDependent() || Calc->isValueDependent()) - return; - - ASTContext &Context = *Result.Context; - - QualType CastType = Cast->getType(); - QualType CalcType = Calc->getType(); - - // Explicit truncation using cast. - if (Context.getIntWidth(CastType) < Context.getIntWidth(CalcType)) - return; - - // If CalcType and CastType have same size then there is no real danger, but - // there can be a portability problem. - - if (Context.getIntWidth(CastType) == Context.getIntWidth(CalcType)) { - const auto *CastBuiltinType = - dyn_cast<BuiltinType>(CastType->getUnqualifiedDesugaredType()); - const auto *CalcBuiltinType = - dyn_cast<BuiltinType>(CalcType->getUnqualifiedDesugaredType()); - if (CastBuiltinType && CalcBuiltinType && - !isFirstWider(CastBuiltinType->getKind(), CalcBuiltinType->getKind())) - return; - } - - // Don't write a warning if we can easily see that the result is not - // truncated. - if (Context.getIntWidth(CalcType) >= getMaxCalculationWidth(Context, Calc)) - return; - - diag(Cast->getLocStart(), "either cast from %0 to %1 is ineffective, or " - "there is loss of precision before the conversion") - << CalcType << CastType; -} - -} // namespace misc -} // namespace tidy -} // namespace clang |

