Skip to content

Commit

Permalink
Merge from 'main' to 'sycl-web' (#3)
Browse files Browse the repository at this point in the history
  CONFLICT (content): Merge conflict in clang/lib/Driver/ToolChains/Clang.cpp
  • Loading branch information
asudarsa committed Apr 17, 2021
2 parents e78a828 + eaa9ef0 commit 6ae70da
Show file tree
Hide file tree
Showing 2,087 changed files with 57,573 additions and 21,597 deletions.
6 changes: 6 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "FoldInitTypeCheck.h"
#include "ForwardDeclarationNamespaceCheck.h"
#include "ForwardingReferenceOverloadCheck.h"
#include "ImplicitWideningOfMultiplicationResultCheck.h"
#include "InaccurateEraseCheck.h"
#include "IncorrectRoundingsCheck.h"
#include "InfiniteLoopCheck.h"
Expand Down Expand Up @@ -60,6 +61,7 @@
#include "TooSmallLoopVariableCheck.h"
#include "UndefinedMemoryManipulationCheck.h"
#include "UndelegatedConstructorCheck.h"
#include "UnhandledExceptionAtNewCheck.h"
#include "UnhandledSelfAssignmentCheck.h"
#include "UnusedRaiiCheck.h"
#include "UnusedReturnValueCheck.h"
Expand Down Expand Up @@ -97,6 +99,8 @@ class BugproneModule : public ClangTidyModule {
"bugprone-forward-declaration-namespace");
CheckFactories.registerCheck<ForwardingReferenceOverloadCheck>(
"bugprone-forwarding-reference-overload");
CheckFactories.registerCheck<ImplicitWideningOfMultiplicationResultCheck>(
"bugprone-implicit-widening-of-multiplication-result");
CheckFactories.registerCheck<InaccurateEraseCheck>(
"bugprone-inaccurate-erase");
CheckFactories.registerCheck<IncorrectRoundingsCheck>(
Expand Down Expand Up @@ -175,6 +179,8 @@ class BugproneModule : public ClangTidyModule {
"bugprone-undelegated-constructor");
CheckFactories.registerCheck<UnhandledSelfAssignmentCheck>(
"bugprone-unhandled-self-assignment");
CheckFactories.registerCheck<UnhandledExceptionAtNewCheck>(
"bugprone-unhandled-exception-at-new");
CheckFactories.registerCheck<UnusedRaiiCheck>(
"bugprone-unused-raii");
CheckFactories.registerCheck<UnusedReturnValueCheck>(
Expand Down
2 changes: 2 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_clang_library(clangTidyBugproneModule
FoldInitTypeCheck.cpp
ForwardDeclarationNamespaceCheck.cpp
ForwardingReferenceOverloadCheck.cpp
ImplicitWideningOfMultiplicationResultCheck.cpp
InaccurateEraseCheck.cpp
IncorrectRoundingsCheck.cpp
InfiniteLoopCheck.cpp
Expand Down Expand Up @@ -55,6 +56,7 @@ add_clang_library(clangTidyBugproneModule
TooSmallLoopVariableCheck.cpp
UndefinedMemoryManipulationCheck.cpp
UndelegatedConstructorCheck.cpp
UnhandledExceptionAtNewCheck.cpp
UnhandledSelfAssignmentCheck.cpp
UnusedRaiiCheck.cpp
UnusedReturnValueCheck.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
//===--- ImplicitWideningOfMultiplicationResultCheck.cpp - clang-tidy -----===//
//
// 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 "ImplicitWideningOfMultiplicationResultCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

using namespace clang::ast_matchers;

namespace clang {
namespace {
AST_MATCHER(ImplicitCastExpr, isPartOfExplicitCast) {
return Node.isPartOfExplicitCast();
}
} // namespace
} // namespace clang

namespace clang {
namespace tidy {
namespace bugprone {

static const Expr *getLHSOfMulBinOp(const Expr *E) {
assert(E == E->IgnoreParens() && "Already skipped all parens!");
// Is this: long r = int(x) * int(y); ?
// FIXME: shall we skip brackets/casts/etc?
const auto *BO = dyn_cast<BinaryOperator>(E);
if (!BO || BO->getOpcode() != BO_Mul)
// FIXME: what about: long r = int(x) + (int(y) * int(z)); ?
return nullptr;
return BO->getLHS()->IgnoreParens();
}

ImplicitWideningOfMultiplicationResultCheck::
ImplicitWideningOfMultiplicationResultCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
UseCXXStaticCastsInCppSources(
Options.get("UseCXXStaticCastsInCppSources", true)),
UseCXXHeadersInCppSources(Options.get("UseCXXHeadersInCppSources", true)),
IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::IS_LLVM)) {
}

void ImplicitWideningOfMultiplicationResultCheck::registerPPCallbacks(
const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
IncludeInserter.registerPreprocessor(PP);
}

void ImplicitWideningOfMultiplicationResultCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "UseCXXStaticCastsInCppSources",
UseCXXStaticCastsInCppSources);
Options.store(Opts, "UseCXXHeadersInCppSources", UseCXXHeadersInCppSources);
Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
}

llvm::Optional<FixItHint>
ImplicitWideningOfMultiplicationResultCheck::includeStddefHeader(
SourceLocation File) {
return IncludeInserter.createIncludeInsertion(
Result->SourceManager->getFileID(File),
ShouldUseCXXHeader ? "<cstddef>" : "<stddef.h>");
}

void ImplicitWideningOfMultiplicationResultCheck::handleImplicitCastExpr(
const ImplicitCastExpr *ICE) {
ASTContext *Context = Result->Context;

const Expr *E = ICE->getSubExpr()->IgnoreParens();
QualType Ty = ICE->getType();
QualType ETy = E->getType();

assert(!ETy->isDependentType() && !Ty->isDependentType() &&
"Don't expect to ever get here in template Context.");

// This must be a widening cast. Else we do not care.
unsigned SrcWidth = Context->getIntWidth(ETy);
unsigned TgtWidth = Context->getIntWidth(Ty);
if (TgtWidth <= SrcWidth)
return;

// Does the index expression look like it might be unintentionally computed
// in a narrower-than-wanted type?
const Expr *LHS = getLHSOfMulBinOp(E);
if (!LHS)
return;

// Ok, looks like we should diagnose this.
diag(E->getBeginLoc(), "performing an implicit widening conversion to type "
"%0 of a multiplication performed in type %1")
<< Ty << E->getType();

{
auto Diag = diag(E->getBeginLoc(),
"make conversion explicit to silence this warning",
DiagnosticIDs::Note)
<< E->getSourceRange();

if (ShouldUseCXXStaticCast)
Diag << FixItHint::CreateInsertion(
E->getBeginLoc(), "static_cast<" + Ty.getAsString() + ">(")
<< FixItHint::CreateInsertion(E->getEndLoc(), ")");
else
Diag << FixItHint::CreateInsertion(E->getBeginLoc(),
"(" + Ty.getAsString() + ")(")
<< FixItHint::CreateInsertion(E->getEndLoc(), ")");
Diag << includeStddefHeader(E->getBeginLoc());
}

QualType WideExprTy;
// Get Ty of the same signedness as ExprTy, because we only want to suggest
// to widen the computation, but not change it's signedness domain.
if (Ty->isSignedIntegerType() == ETy->isSignedIntegerType())
WideExprTy = Ty;
else if (Ty->isSignedIntegerType()) {
assert(ETy->isUnsignedIntegerType() &&
"Expected source type to be signed.");
WideExprTy = Context->getCorrespondingUnsignedType(Ty);
} else {
assert(Ty->isUnsignedIntegerType() &&
"Expected target type to be unsigned.");
assert(ETy->isSignedIntegerType() &&
"Expected source type to be unsigned.");
WideExprTy = Context->getCorrespondingSignedType(Ty);
}

{
auto Diag = diag(E->getBeginLoc(), "perform multiplication in a wider type",
DiagnosticIDs::Note)
<< LHS->getSourceRange();

if (ShouldUseCXXStaticCast)
Diag << FixItHint::CreateInsertion(LHS->getBeginLoc(),
"static_cast<" +
WideExprTy.getAsString() + ">(")
<< FixItHint::CreateInsertion(LHS->getEndLoc(), ")");
else
Diag << FixItHint::CreateInsertion(LHS->getBeginLoc(),
"(" + WideExprTy.getAsString() + ")");
Diag << includeStddefHeader(LHS->getBeginLoc());
}
}

void ImplicitWideningOfMultiplicationResultCheck::handlePointerOffsetting(
const Expr *E) {
ASTContext *Context = Result->Context;

// We are looking for a pointer offset operation,
// with one hand being a pointer, and another one being an offset.
const Expr *PointerExpr, *IndexExpr;
if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
PointerExpr = BO->getLHS();
IndexExpr = BO->getRHS();
} else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
PointerExpr = ASE->getLHS();
IndexExpr = ASE->getRHS();
} else
return;

if (IndexExpr->getType()->isPointerType())
std::swap(PointerExpr, IndexExpr);

if (!PointerExpr->getType()->isPointerType() ||
IndexExpr->getType()->isPointerType())
return;

IndexExpr = IndexExpr->IgnoreParens();

QualType IndexExprType = IndexExpr->getType();

// If the index expression's type is not known (i.e. we are in a template),
// we can't do anything here.
if (IndexExprType->isDependentType())
return;

QualType SSizeTy = Context->getPointerDiffType();
QualType USizeTy = Context->getSizeType();
QualType SizeTy = IndexExprType->isSignedIntegerType() ? SSizeTy : USizeTy;
// FIXME: is there a way to actually get the QualType for size_t/ptrdiff_t?
// Note that SizeTy.getAsString() will be unsigned long/..., NOT size_t!
StringRef TyAsString =
IndexExprType->isSignedIntegerType() ? "ptrdiff_t" : "size_t";

// So, is size_t actually wider than the result of the multiplication?
if (Context->getIntWidth(IndexExprType) >= Context->getIntWidth(SizeTy))
return;

// Does the index expression look like it might be unintentionally computed
// in a narrower-than-wanted type?
const Expr *LHS = getLHSOfMulBinOp(IndexExpr);
if (!LHS)
return;

// Ok, looks like we should diagnose this.
diag(E->getBeginLoc(),
"result of multiplication in type %0 is used as a pointer offset after "
"an implicit widening conversion to type '%1'")
<< IndexExprType << TyAsString;

{
auto Diag = diag(IndexExpr->getBeginLoc(),
"make conversion explicit to silence this warning",
DiagnosticIDs::Note)
<< IndexExpr->getSourceRange();

if (ShouldUseCXXStaticCast)
Diag << FixItHint::CreateInsertion(
IndexExpr->getBeginLoc(),
(Twine("static_cast<") + TyAsString + ">(").str())
<< FixItHint::CreateInsertion(IndexExpr->getEndLoc(), ")");
else
Diag << FixItHint::CreateInsertion(IndexExpr->getBeginLoc(),
(Twine("(") + TyAsString + ")(").str())
<< FixItHint::CreateInsertion(IndexExpr->getEndLoc(), ")");
Diag << includeStddefHeader(IndexExpr->getBeginLoc());
}

{
auto Diag =
diag(IndexExpr->getBeginLoc(), "perform multiplication in a wider type",
DiagnosticIDs::Note)
<< LHS->getSourceRange();

if (ShouldUseCXXStaticCast)
Diag << FixItHint::CreateInsertion(
LHS->getBeginLoc(),
(Twine("static_cast<") + TyAsString + ">(").str())
<< FixItHint::CreateInsertion(LHS->getEndLoc(), ")");
else
Diag << FixItHint::CreateInsertion(LHS->getBeginLoc(),
(Twine("(") + TyAsString + ")").str());
Diag << includeStddefHeader(LHS->getBeginLoc());
}
}

void ImplicitWideningOfMultiplicationResultCheck::registerMatchers(
MatchFinder *Finder) {
Finder->addMatcher(implicitCastExpr(unless(anyOf(isInTemplateInstantiation(),
isPartOfExplicitCast())),
hasCastKind(CK_IntegralCast))
.bind("x"),
this);
Finder->addMatcher(
arraySubscriptExpr(unless(isInTemplateInstantiation())).bind("x"), this);
Finder->addMatcher(binaryOperator(unless(isInTemplateInstantiation()),
hasType(isAnyPointer()),
hasAnyOperatorName("+", "-", "+=", "-="))
.bind("x"),
this);
}

void ImplicitWideningOfMultiplicationResultCheck::check(
const MatchFinder::MatchResult &Result) {
this->Result = &Result;
ShouldUseCXXStaticCast =
UseCXXStaticCastsInCppSources && Result.Context->getLangOpts().CPlusPlus;
ShouldUseCXXHeader =
UseCXXHeadersInCppSources && Result.Context->getLangOpts().CPlusPlus;

if (const auto *MatchedDecl = Result.Nodes.getNodeAs<ImplicitCastExpr>("x"))
handleImplicitCastExpr(MatchedDecl);
else if (const auto *MatchedDecl =
Result.Nodes.getNodeAs<ArraySubscriptExpr>("x"))
handlePointerOffsetting(MatchedDecl);
else if (const auto *MatchedDecl =
Result.Nodes.getNodeAs<BinaryOperator>("x"))
handlePointerOffsetting(MatchedDecl);
}

} // namespace bugprone
} // namespace tidy
} // namespace clang
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===--- ImplicitWideningOfMultiplicationResultCheck.h ----------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_IMPLICITWIDENINGOFMULTIPLICATIONRESULTCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_IMPLICITWIDENINGOFMULTIPLICATIONRESULTCHECK_H

#include "../ClangTidyCheck.h"
#include "../utils/IncludeInserter.h"

namespace clang {
namespace tidy {
namespace bugprone {

/// Diagnoses instances of an implicit widening of multiplication result.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-implicit-widening-of-multiplication-result.html
class ImplicitWideningOfMultiplicationResultCheck : public ClangTidyCheck {
const ast_matchers::MatchFinder::MatchResult *Result;
bool ShouldUseCXXStaticCast;
bool ShouldUseCXXHeader;

llvm::Optional<FixItHint> includeStddefHeader(SourceLocation File);

void handleImplicitCastExpr(const ImplicitCastExpr *ICE);
void handlePointerOffsetting(const Expr *E);

public:
ImplicitWideningOfMultiplicationResultCheck(StringRef Name,
ClangTidyContext *Context);
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
Preprocessor *ModuleExpanderPP) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;

private:
const bool UseCXXStaticCastsInCppSources;
const bool UseCXXHeadersInCppSources;
utils::IncludeInserter IncludeInserter;
};

} // namespace bugprone
} // namespace tidy
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_IMPLICITWIDENINGOFMULTIPLICATIONRESULTCHECK_H
Loading

0 comments on commit 6ae70da

Please sign in to comment.