Skip to content

Commit 49bde1f

Browse files
authored
Merge pull request #698 LLVM pulldown for 6713f82
2 parents f4d182f + 9f2ca62 commit 49bde1f

File tree

3,568 files changed

+119248
-56023
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

3,568 files changed

+119248
-56023
lines changed

clang-tools-extra/clang-tidy/CMakeLists.txt

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,15 @@ if(CLANG_ENABLE_STATIC_ANALYZER)
3737
)
3838
endif()
3939

40+
# Checks.
41+
# If you add a check, also add it to ClangTidyForceLinker.h in this directory.
4042
add_subdirectory(android)
4143
add_subdirectory(abseil)
4244
add_subdirectory(boost)
4345
add_subdirectory(bugprone)
4446
add_subdirectory(cert)
4547
add_subdirectory(cppcoreguidelines)
48+
add_subdirectory(darwin)
4649
add_subdirectory(fuchsia)
4750
add_subdirectory(google)
4851
add_subdirectory(hicpp)
@@ -56,9 +59,38 @@ endif()
5659
add_subdirectory(objc)
5760
add_subdirectory(openmp)
5861
add_subdirectory(performance)
59-
add_subdirectory(plugin)
6062
add_subdirectory(portability)
6163
add_subdirectory(readability)
64+
add_subdirectory(zircon)
65+
set(ALL_CLANG_TIDY_CHECKS
66+
clangTidyAndroidModule
67+
clangTidyAbseilModule
68+
clangTidyBoostModule
69+
clangTidyBugproneModule
70+
clangTidyCERTModule
71+
clangTidyCppCoreGuidelinesModule
72+
clangTidyDarwinModule
73+
clangTidyFuchsiaModule
74+
clangTidyGoogleModule
75+
clangTidyHICPPModule
76+
clangTidyLinuxKernelModule
77+
clangTidyLLVMModule
78+
clangTidyMiscModule
79+
clangTidyModernizeModule
80+
clangTidyObjCModule
81+
clangTidyOpenMPModule
82+
clangTidyPerformanceModule
83+
clangTidyPortabilityModule
84+
clangTidyReadabilityModule
85+
clangTidyZirconModule
86+
)
87+
if(CLANG_ENABLE_STATIC_ANALYZER)
88+
list(APPEND ALL_CLANG_TIDY_CHECKS clangTidyMPIModule)
89+
endif()
90+
set(ALL_CLANG_TIDY_CHECKS ${ALL_CLANG_TIDY_CHECKS} PARENT_SCOPE)
91+
92+
# Other subtargets. These may reference ALL_CLANG_TIDY_CHECKS
93+
# and must be below its definition.
94+
add_subdirectory(plugin)
6295
add_subdirectory(tool)
6396
add_subdirectory(utils)
64-
add_subdirectory(zircon)

clang-tools-extra/clang-tidy/ClangTidy.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,8 @@ ClangTidyASTConsumerFactory::CreateASTConsumer(
384384
if (WorkingDir)
385385
Context.setCurrentBuildDirectory(WorkingDir.get());
386386

387-
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
388-
CheckFactories->createChecks(&Context, Checks);
387+
std::vector<std::unique_ptr<ClangTidyCheck>> Checks =
388+
CheckFactories->createChecks(&Context);
389389

390390
ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
391391

@@ -459,8 +459,8 @@ std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
459459

460460
ClangTidyOptions::OptionMap ClangTidyASTConsumerFactory::getCheckOptions() {
461461
ClangTidyOptions::OptionMap Options;
462-
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
463-
CheckFactories->createChecks(&Context, Checks);
462+
std::vector<std::unique_ptr<ClangTidyCheck>> Checks =
463+
CheckFactories->createChecks(&Context);
464464
for (const auto &Check : Checks)
465465
Check->storeOptions(Options);
466466
return Options;

clang-tools-extra/clang-tidy/ClangTidyForceLinker.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ extern volatile int CppCoreGuidelinesModuleAnchorSource;
5050
static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination =
5151
CppCoreGuidelinesModuleAnchorSource;
5252

53+
// This anchor is used to force the linker to link the DarwinModule.
54+
extern volatile int DarwinModuleAnchorSource;
55+
static int LLVM_ATTRIBUTE_UNUSED DarwinModuleAnchorDestination =
56+
DarwinModuleAnchorSource;
57+
5358
// This anchor is used to force the linker to link the FuchsiaModule.
5459
extern volatile int FuchsiaModuleAnchorSource;
5560
static int LLVM_ATTRIBUTE_UNUSED FuchsiaModuleAnchorDestination =
@@ -75,7 +80,8 @@ extern volatile int ModernizeModuleAnchorSource;
7580
static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
7681
ModernizeModuleAnchorSource;
7782

78-
#if CLANG_ENABLE_STATIC_ANALYZER
83+
#if CLANG_ENABLE_STATIC_ANALYZER && \
84+
!defined(CLANG_TIDY_DISABLE_STATIC_ANALYZER_CHECKS)
7985
// This anchor is used to force the linker to link the MPIModule.
8086
extern volatile int MPIModuleAnchorSource;
8187
static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination =

clang-tools-extra/clang-tidy/ClangTidyModule.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ void ClangTidyCheckFactories::registerCheckFactory(StringRef Name,
2020
Factories[Name] = std::move(Factory);
2121
}
2222

23-
void ClangTidyCheckFactories::createChecks(
24-
ClangTidyContext *Context,
25-
std::vector<std::unique_ptr<ClangTidyCheck>> &Checks) {
23+
std::vector<std::unique_ptr<ClangTidyCheck>>
24+
ClangTidyCheckFactories::createChecks(ClangTidyContext *Context) {
25+
std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
2626
for (const auto &Factory : Factories) {
2727
if (Context->isCheckEnabled(Factory.first))
2828
Checks.emplace_back(Factory.second(Factory.first, Context));
2929
}
30+
return Checks;
3031
}
3132

3233
ClangTidyOptions ClangTidyModule::getModuleOptions() {

clang-tools-extra/clang-tidy/ClangTidyModule.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/ADT/StringRef.h"
1414
#include <functional>
1515
#include <map>
16+
#include <memory>
1617
#include <string>
1718
#include <utility>
1819

@@ -25,9 +26,8 @@ namespace tidy {
2526
/// this object.
2627
class ClangTidyCheckFactories {
2728
public:
28-
typedef std::function<ClangTidyCheck *(StringRef Name,
29-
ClangTidyContext *Context)>
30-
CheckFactory;
29+
using CheckFactory = std::function<std::unique_ptr<ClangTidyCheck>(
30+
StringRef Name, ClangTidyContext *Context)>;
3131

3232
/// Registers check \p Factory with name \p Name.
3333
///
@@ -58,16 +58,13 @@ class ClangTidyCheckFactories {
5858
template <typename CheckType> void registerCheck(StringRef CheckName) {
5959
registerCheckFactory(CheckName,
6060
[](StringRef Name, ClangTidyContext *Context) {
61-
return new CheckType(Name, Context);
61+
return std::make_unique<CheckType>(Name, Context);
6262
});
6363
}
6464

65-
/// Create instances of all checks matching \p CheckRegexString and
66-
/// store them in \p Checks.
67-
///
68-
/// The caller takes ownership of the return \c ClangTidyChecks.
69-
void createChecks(ClangTidyContext *Context,
70-
std::vector<std::unique_ptr<ClangTidyCheck>> &Checks);
65+
/// Create instances of checks that are enabled.
66+
std::vector<std::unique_ptr<ClangTidyCheck>>
67+
createChecks(ClangTidyContext *Context);
7168

7269
typedef std::map<std::string, CheckFactory> FactoryMap;
7370
FactoryMap::const_iterator begin() const { return Factories.begin(); }

clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx,
324324
<< FixItHint::CreateInsertion(Args[I]->getBeginLoc(), ArgComment);
325325
}
326326
}
327-
} // namespace bugprone
327+
}
328328

329329
void ArgumentCommentCheck::check(const MatchFinder::MatchResult &Result) {
330330
const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
@@ -337,7 +337,7 @@ void ArgumentCommentCheck::check(const MatchFinder::MatchResult &Result) {
337337
llvm::makeArrayRef(Call->getArgs(), Call->getNumArgs()));
338338
} else {
339339
const auto *Construct = cast<CXXConstructExpr>(E);
340-
if (Construct->getNumArgs() == 1 &&
340+
if (Construct->getNumArgs() > 0 &&
341341
Construct->getArg(0)->getSourceRange() == Construct->getSourceRange()) {
342342
// Ignore implicit construction.
343343
return;

clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "ForwardingReferenceOverloadCheck.h"
2424
#include "InaccurateEraseCheck.h"
2525
#include "IncorrectRoundingsCheck.h"
26+
#include "InfiniteLoopCheck.h"
2627
#include "IntegerDivisionCheck.h"
2728
#include "LambdaFunctionNameCheck.h"
2829
#include "MacroParenthesesCheck.h"
@@ -88,6 +89,8 @@ class BugproneModule : public ClangTidyModule {
8889
"bugprone-inaccurate-erase");
8990
CheckFactories.registerCheck<IncorrectRoundingsCheck>(
9091
"bugprone-incorrect-roundings");
92+
CheckFactories.registerCheck<InfiniteLoopCheck>(
93+
"bugprone-infinite-loop");
9194
CheckFactories.registerCheck<IntegerDivisionCheck>(
9295
"bugprone-integer-division");
9396
CheckFactories.registerCheck<LambdaFunctionNameCheck>(

clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ add_clang_library(clangTidyBugproneModule
1515
ForwardingReferenceOverloadCheck.cpp
1616
InaccurateEraseCheck.cpp
1717
IncorrectRoundingsCheck.cpp
18+
InfiniteLoopCheck.cpp
1819
IntegerDivisionCheck.cpp
1920
LambdaFunctionNameCheck.cpp
2021
MacroParenthesesCheck.cpp
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
//===--- InfiniteLoopCheck.cpp - clang-tidy -------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "InfiniteLoopCheck.h"
10+
#include "clang/AST/ASTContext.h"
11+
#include "clang/ASTMatchers/ASTMatchFinder.h"
12+
#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
13+
14+
using namespace clang::ast_matchers;
15+
16+
namespace clang {
17+
namespace tidy {
18+
namespace bugprone {
19+
20+
static internal::Matcher<Stmt>
21+
loopEndingStmt(internal::Matcher<Stmt> Internal) {
22+
return stmt(anyOf(breakStmt(Internal), returnStmt(Internal),
23+
gotoStmt(Internal), cxxThrowExpr(Internal),
24+
callExpr(Internal, callee(functionDecl(isNoReturn())))));
25+
}
26+
27+
/// Return whether `S` is a reference to the declaration of `Var`.
28+
static bool isAccessForVar(const Stmt *S, const VarDecl *Var) {
29+
if (const auto *DRE = dyn_cast<DeclRefExpr>(S))
30+
return DRE->getDecl() == Var;
31+
32+
return false;
33+
}
34+
35+
/// Return whether `Var` has a pointer or reference in `S`.
36+
static bool isPtrOrReferenceForVar(const Stmt *S, const VarDecl *Var) {
37+
if (const auto *DS = dyn_cast<DeclStmt>(S)) {
38+
for (const Decl *D : DS->getDeclGroup()) {
39+
if (const auto *LeftVar = dyn_cast<VarDecl>(D)) {
40+
if (LeftVar->hasInit() && LeftVar->getType()->isReferenceType()) {
41+
return isAccessForVar(LeftVar->getInit(), Var);
42+
}
43+
}
44+
}
45+
} else if (const auto *UnOp = dyn_cast<UnaryOperator>(S)) {
46+
if (UnOp->getOpcode() == UO_AddrOf)
47+
return isAccessForVar(UnOp->getSubExpr(), Var);
48+
}
49+
50+
return false;
51+
}
52+
53+
/// Return whether `Var` has a pointer or reference in `S`.
54+
static bool hasPtrOrReferenceInStmt(const Stmt *S, const VarDecl *Var) {
55+
if (isPtrOrReferenceForVar(S, Var))
56+
return true;
57+
58+
for (const Stmt *Child : S->children()) {
59+
if (!Child)
60+
continue;
61+
62+
if (hasPtrOrReferenceInStmt(Child, Var))
63+
return true;
64+
}
65+
66+
return false;
67+
}
68+
69+
/// Return whether `Var` has a pointer or reference in `Func`.
70+
static bool hasPtrOrReferenceInFunc(const FunctionDecl *Func,
71+
const VarDecl *Var) {
72+
return hasPtrOrReferenceInStmt(Func->getBody(), Var);
73+
}
74+
75+
/// Return whether `Var` was changed in `LoopStmt`.
76+
static bool isChanged(const Stmt *LoopStmt, const VarDecl *Var,
77+
ASTContext *Context) {
78+
if (const auto *ForLoop = dyn_cast<ForStmt>(LoopStmt))
79+
return (ForLoop->getInc() &&
80+
ExprMutationAnalyzer(*ForLoop->getInc(), *Context)
81+
.isMutated(Var)) ||
82+
(ForLoop->getBody() &&
83+
ExprMutationAnalyzer(*ForLoop->getBody(), *Context)
84+
.isMutated(Var)) ||
85+
(ForLoop->getCond() &&
86+
ExprMutationAnalyzer(*ForLoop->getCond(), *Context).isMutated(Var));
87+
88+
return ExprMutationAnalyzer(*LoopStmt, *Context).isMutated(Var);
89+
}
90+
91+
/// Return whether `Cond` is a variable that is possibly changed in `LoopStmt`.
92+
static bool isVarThatIsPossiblyChanged(const FunctionDecl *Func,
93+
const Stmt *LoopStmt, const Stmt *Cond,
94+
ASTContext *Context) {
95+
if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
96+
if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
97+
if (!Var->isLocalVarDeclOrParm())
98+
return true;
99+
100+
if (Var->getType().isVolatileQualified())
101+
return true;
102+
103+
if (!Var->getType().getTypePtr()->isIntegerType())
104+
return true;
105+
106+
return hasPtrOrReferenceInFunc(Func, Var) ||
107+
isChanged(LoopStmt, Var, Context);
108+
// FIXME: Track references.
109+
}
110+
} else if (isa<MemberExpr>(Cond) || isa<CallExpr>(Cond)) {
111+
// FIXME: Handle MemberExpr.
112+
return true;
113+
}
114+
115+
return false;
116+
}
117+
118+
/// Return whether at least one variable of `Cond` changed in `LoopStmt`.
119+
static bool isAtLeastOneCondVarChanged(const FunctionDecl *Func,
120+
const Stmt *LoopStmt, const Stmt *Cond,
121+
ASTContext *Context) {
122+
if (isVarThatIsPossiblyChanged(Func, LoopStmt, Cond, Context))
123+
return true;
124+
125+
for (const Stmt *Child : Cond->children()) {
126+
if (!Child)
127+
continue;
128+
129+
if (isAtLeastOneCondVarChanged(Func, LoopStmt, Child, Context))
130+
return true;
131+
}
132+
return false;
133+
}
134+
135+
/// Return the variable names in `Cond`.
136+
static std::string getCondVarNames(const Stmt *Cond) {
137+
if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
138+
if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl()))
139+
return Var->getName();
140+
}
141+
142+
std::string Result;
143+
for (const Stmt *Child : Cond->children()) {
144+
if (!Child)
145+
continue;
146+
147+
std::string NewNames = getCondVarNames(Child);
148+
if (!Result.empty() && !NewNames.empty())
149+
Result += ", ";
150+
Result += NewNames;
151+
}
152+
return Result;
153+
}
154+
155+
void InfiniteLoopCheck::registerMatchers(MatchFinder *Finder) {
156+
const auto LoopCondition = allOf(
157+
hasCondition(
158+
expr(forFunction(functionDecl().bind("func"))).bind("condition")),
159+
unless(hasBody(hasDescendant(
160+
loopEndingStmt(forFunction(equalsBoundNode("func")))))));
161+
162+
Finder->addMatcher(stmt(anyOf(whileStmt(LoopCondition), doStmt(LoopCondition),
163+
forStmt(LoopCondition)))
164+
.bind("loop-stmt"),
165+
this);
166+
}
167+
168+
void InfiniteLoopCheck::check(const MatchFinder::MatchResult &Result) {
169+
const auto *Cond = Result.Nodes.getNodeAs<Expr>("condition");
170+
const auto *LoopStmt = Result.Nodes.getNodeAs<Stmt>("loop-stmt");
171+
const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
172+
173+
if (isAtLeastOneCondVarChanged(Func, LoopStmt, Cond, Result.Context))
174+
return;
175+
176+
std::string CondVarNames = getCondVarNames(Cond);
177+
if (CondVarNames.empty())
178+
return;
179+
180+
diag(LoopStmt->getBeginLoc(),
181+
"this loop is infinite; none of its condition variables (%0)"
182+
" are updated in the loop body")
183+
<< CondVarNames;
184+
}
185+
186+
} // namespace bugprone
187+
} // namespace tidy
188+
} // namespace clang

0 commit comments

Comments
 (0)