Skip to content

Commit

Permalink
Merge from 'master' to 'sycl-web' (#1)
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
bader committed Sep 24, 2019
2 parents d88e790 + 1282889 commit 851ca24
Show file tree
Hide file tree
Showing 1,877 changed files with 66,872 additions and 31,694 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
<< FixItHint::CreateInsertion(Args[I]->getBeginLoc(), ArgComment);
}
}
} // namespace bugprone
}

void ArgumentCommentCheck::check(const MatchFinder::MatchResult &Result) {
const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
Expand All @@ -337,7 +337,7 @@ void ArgumentCommentCheck::check(const MatchFinder::MatchResult &Result) {
llvm::makeArrayRef(Call->getArgs(), Call->getNumArgs()));
} else {
const auto *Construct = cast<CXXConstructExpr>(E);
if (Construct->getNumArgs() == 1 &&
if (Construct->getNumArgs() > 0 &&
Construct->getArg(0)->getSourceRange() == Construct->getSourceRange()) {
// Ignore implicit construction.
return;
Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "ForwardingReferenceOverloadCheck.h"
#include "InaccurateEraseCheck.h"
#include "IncorrectRoundingsCheck.h"
#include "InfiniteLoopCheck.h"
#include "IntegerDivisionCheck.h"
#include "LambdaFunctionNameCheck.h"
#include "MacroParenthesesCheck.h"
Expand Down Expand Up @@ -88,6 +89,8 @@ class BugproneModule : public ClangTidyModule {
"bugprone-inaccurate-erase");
CheckFactories.registerCheck<IncorrectRoundingsCheck>(
"bugprone-incorrect-roundings");
CheckFactories.registerCheck<InfiniteLoopCheck>(
"bugprone-infinite-loop");
CheckFactories.registerCheck<IntegerDivisionCheck>(
"bugprone-integer-division");
CheckFactories.registerCheck<LambdaFunctionNameCheck>(
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_clang_library(clangTidyBugproneModule
ForwardingReferenceOverloadCheck.cpp
InaccurateEraseCheck.cpp
IncorrectRoundingsCheck.cpp
InfiniteLoopCheck.cpp
IntegerDivisionCheck.cpp
LambdaFunctionNameCheck.cpp
MacroParenthesesCheck.cpp
Expand Down
189 changes: 189 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
//===--- InfiniteLoopCheck.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 "InfiniteLoopCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace bugprone {

static internal::Matcher<Stmt>
loopEndingStmt(internal::Matcher<Stmt> Internal) {
return stmt(anyOf(breakStmt(Internal), returnStmt(Internal),
gotoStmt(Internal), cxxThrowExpr(Internal),
callExpr(Internal, callee(functionDecl(isNoReturn())))));
}

/// \brief Return whether `S` is a reference to the declaration of `Var`.
static bool isAccessForVar(const Stmt *S, const VarDecl *Var) {
if (const auto *DRE = dyn_cast<DeclRefExpr>(S))
return DRE->getDecl() == Var;

return false;
}

/// \brief Return whether `Var` has a pointer of reference in `S`.
static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var) {
if (const auto *DS = dyn_cast<DeclStmt>(S)) {
for (const Decl *D : DS->getDeclGroup()) {
if (const auto *LeftVar = dyn_cast<VarDecl>(D)) {
if (LeftVar->hasInit() && LeftVar->getType()->isReferenceType()) {
return isAccessForVar(LeftVar->getInit(), Var);
}
}
}
} else if (const auto *UnOp = dyn_cast<UnaryOperator>(S)) {
if (UnOp->getOpcode() == UO_AddrOf)
return isAccessForVar(UnOp->getSubExpr(), Var);
}

return false;
}

/// \brief Return whether `Var` has a pointer of reference in `S`.
static bool hasPtrOrReferenceInStmt(const Stmt *S, const VarDecl *Var) {
if (isPtrOrReferenceForVar(S, Var))
return true;

for (const Stmt *Child : S->children()) {
if (!Child)
continue;

if (hasPtrOrReferenceInStmt(Child, Var))
return true;
}

return false;
}

/// \brief Return whether `Var` has a pointer of reference in `Func`.
static bool hasPtrOrReferenceInFunc(const FunctionDecl *Func,
const VarDecl *Var) {
return hasPtrOrReferenceInStmt(Func->getBody(), Var);
}

/// \brief Return whether `Var` was changed in `LoopStmt`.
static bool isChanged(const Stmt *LoopStmt, const VarDecl *Var,
ASTContext *Context) {
if (const auto *ForLoop = dyn_cast<ForStmt>(LoopStmt))
return (ForLoop->getInc() &&
ExprMutationAnalyzer(*ForLoop->getInc(), *Context)
.isMutated(Var)) ||
(ForLoop->getBody() &&
ExprMutationAnalyzer(*ForLoop->getBody(), *Context)
.isMutated(Var)) ||
(ForLoop->getCond() &&
ExprMutationAnalyzer(*ForLoop->getCond(), *Context).isMutated(Var));

return ExprMutationAnalyzer(*LoopStmt, *Context).isMutated(Var);
}

/// \brief Return whether `Cond` is a variable that is possibly changed in
/// `LoopStmt`.
static bool isVarThatIsPossiblyChanged(const FunctionDecl *Func,
const Stmt *LoopStmt, const Stmt *Cond,
ASTContext *Context) {
if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
if (!Var->isLocalVarDeclOrParm())
return true;

if (Var->getType().isVolatileQualified())
return true;

if (!Var->getType().getTypePtr()->isIntegerType())
return true;

return hasPtrOrReferenceInFunc(Func, Var) ||
isChanged(LoopStmt, Var, Context);
// FIXME: Track references.
}
} else if (isa<MemberExpr>(Cond) || isa<CallExpr>(Cond)) {
// FIXME: Handle MemberExpr.
return true;
}

return false;
}

/// \brief Return whether at least one variable of `Cond` changed in `LoopStmt`.
static bool isAtLeastOneCondVarChanged(const FunctionDecl *Func,
const Stmt *LoopStmt, const Stmt *Cond,
ASTContext *Context) {
if (isVarThatIsPossiblyChanged(Func, LoopStmt, Cond, Context))
return true;

for (const Stmt *Child : Cond->children()) {
if (!Child)
continue;

if (isAtLeastOneCondVarChanged(Func, LoopStmt, Child, Context))
return true;
}
return false;
}

/// \brief Return the variable names in `Cond`.
static std::string getCondVarNames(const Stmt *Cond) {
if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl()))
return Var->getName();
}

std::string Result;
for (const Stmt *Child : Cond->children()) {
if (!Child)
continue;

std::string NewNames = getCondVarNames(Child);
if (!Result.empty() && !NewNames.empty())
Result += ", ";
Result += NewNames;
}
return Result;
}

void InfiniteLoopCheck::registerMatchers(MatchFinder *Finder) {
const auto LoopCondition = allOf(
hasCondition(
expr(forFunction(functionDecl().bind("func"))).bind("condition")),
unless(hasBody(hasDescendant(
loopEndingStmt(forFunction(equalsBoundNode("func")))))));

Finder->addMatcher(stmt(anyOf(whileStmt(LoopCondition), doStmt(LoopCondition),
forStmt(LoopCondition)))
.bind("loop-stmt"),
this);
}

void InfiniteLoopCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Cond = Result.Nodes.getNodeAs<Expr>("condition");
const auto *LoopStmt = Result.Nodes.getNodeAs<Stmt>("loop-stmt");
const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");

if (isAtLeastOneCondVarChanged(Func, LoopStmt, Cond, Result.Context))
return;

std::string CondVarNames = getCondVarNames(Cond);
if (CondVarNames.empty())
return;

diag(LoopStmt->getBeginLoc(),
"this loop is infinite; none of its condition variables (%0)"
" are updated in the loop body")
<< CondVarNames;
}

} // namespace bugprone
} // namespace tidy
} // namespace clang
35 changes: 35 additions & 0 deletions clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===--- InfiniteLoopCheck.h - clang-tidy -----------------------*- 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_INFINITELOOPCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INFINITELOOPCHECK_H

#include "../ClangTidyCheck.h"

namespace clang {
namespace tidy {
namespace bugprone {

/// Finds obvious infinite loops (loops where the condition variable is
/// not changed at all).
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-infinite-loop.html
class InfiniteLoopCheck : public ClangTidyCheck {
public:
InfiniteLoopCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

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

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INFINITELOOPCHECK_H
35 changes: 20 additions & 15 deletions clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,31 @@ static StringRef getFunctionSpelling(const MatchFinder::MatchResult &Result,
}

void PosixReturnCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(binaryOperator(hasOperatorName("<"),
hasLHS(callExpr(callee(functionDecl(
matchesName("^::posix_"),
unless(hasName("::posix_openpt")))))),
hasRHS(integerLiteral(equals(0))))
.bind("ltzop"),
this);
Finder->addMatcher(binaryOperator(hasOperatorName(">="),
hasLHS(callExpr(callee(functionDecl(
matchesName("^::posix_"),
unless(hasName("::posix_openpt")))))),
hasRHS(integerLiteral(equals(0))))
.bind("atop"),
this);
Finder->addMatcher(
binaryOperator(
hasOperatorName("<"),
hasLHS(callExpr(callee(functionDecl(
anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
unless(hasName("::posix_openpt")))))),
hasRHS(integerLiteral(equals(0))))
.bind("ltzop"),
this);
Finder->addMatcher(
binaryOperator(
hasOperatorName(">="),
hasLHS(callExpr(callee(functionDecl(
anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
unless(hasName("::posix_openpt")))))),
hasRHS(integerLiteral(equals(0))))
.bind("atop"),
this);
Finder->addMatcher(
binaryOperator(
anyOf(hasOperatorName("=="), hasOperatorName("!="),
hasOperatorName("<="), hasOperatorName("<")),
hasLHS(callExpr(callee(functionDecl(
matchesName("^::posix_"), unless(hasName("::posix_openpt")))))),
anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
unless(hasName("::posix_openpt")))))),
hasRHS(unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral()))))
.bind("binop"),
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===--- PosixReturnCheck.h - clang-tidy-------------------------*- C++ -*-===//
//===--- PosixReturnCheck.h - clang-tidy ------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/objc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_clang_library(clangTidyObjCModule
AvoidNSErrorInitCheck.cpp
AvoidSpinlockCheck.cpp
ForbiddenSubclassingCheck.cpp
MissingHashCheck.cpp
ObjCTidyModule.cpp
PropertyDeclarationCheck.cpp
SuperSelfCheck.cpp
Expand Down
62 changes: 62 additions & 0 deletions clang-tools-extra/clang-tidy/objc/MissingHashCheck.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===--- MissingHashCheck.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 "MissingHashCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace objc {

namespace {

AST_MATCHER_P(ObjCImplementationDecl, hasInterface,
ast_matchers::internal::Matcher<ObjCInterfaceDecl>, Base) {
const ObjCInterfaceDecl *InterfaceDecl = Node.getClassInterface();
return Base.matches(*InterfaceDecl, Finder, Builder);
}

AST_MATCHER_P(ObjCContainerDecl, hasInstanceMethod,
ast_matchers::internal::Matcher<ObjCMethodDecl>, Base) {
// Check each instance method against the provided matcher.
for (const auto *I : Node.instance_methods()) {
if (Base.matches(*I, Finder, Builder))
return true;
}
return false;
}

} // namespace

void MissingHashCheck::registerMatchers(MatchFinder *Finder) {
// This check should only be applied to Objective-C sources.
if (!getLangOpts().ObjC)
return;

Finder->addMatcher(
objcMethodDecl(
hasName("isEqual:"), isInstanceMethod(),
hasDeclContext(objcImplementationDecl(
hasInterface(isDirectlyDerivedFrom("NSObject")),
unless(hasInstanceMethod(hasName("hash"))))
.bind("impl"))),
this);
}

void MissingHashCheck::check(const MatchFinder::MatchResult &Result) {
const auto *ID = Result.Nodes.getNodeAs<ObjCImplementationDecl>("impl");
diag(ID->getLocation(), "%0 implements -isEqual: without implementing -hash")
<< ID;
}

} // namespace objc
} // namespace tidy
} // namespace clang
Loading

0 comments on commit 851ca24

Please sign in to comment.