forked from triSYCL/sycl
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge from 'master' to 'sycl-web' (#1)
CONFLICT (content): Merge conflict in clang/lib/Driver/ToolChains/Clang.cpp
- Loading branch information
Showing
1,877 changed files
with
66,872 additions
and
31,694 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
189 changes: 189 additions & 0 deletions
189
clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.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,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 |
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,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 |
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
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 |
Oops, something went wrong.