Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 41ac4c4

Browse files
committed
Merge remote-tracking branch 'origin/swift-5.0-branch' into stable
2 parents ad7fb41 + e54a125 commit 41ac4c4

File tree

18 files changed

+383
-29
lines changed

18 files changed

+383
-29
lines changed

docs/analyzer/DebugChecks.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ using a 'dot' format viewer (such as Graphviz on OS X) instead.
3030
- debug.DumpLiveVars: Show the results of live variable analysis for each
3131
top-level function being analyzed.
3232

33+
- debug.DumpLiveStmts: Show the results of live statement analysis for each
34+
top-level function being analyzed.
35+
3336
- debug.ViewExplodedGraph: Show the Exploded Graphs generated for the
3437
analysis of different functions in the input translation unit. When there
35-
are several functions analyzed, display one graph per function. Beware
38+
are several functions analyzed, display one graph per function. Beware
3639
that these graphs may grow very large, even for small functions.
3740

3841
Path Tracking

include/clang/Analysis/Analyses/LiveVariables.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,13 @@ class LiveVariables : public ManagedAnalysis {
8888
/// before the given block-level expression (see runOnAllBlocks).
8989
bool isLive(const Stmt *Loc, const Stmt *StmtVal);
9090

91-
/// Print to stderr the liveness information associated with
91+
/// Print to stderr the variable liveness information associated with
9292
/// each basic block.
93-
void dumpBlockLiveness(const SourceManager& M);
93+
void dumpBlockLiveness(const SourceManager &M);
94+
95+
/// Print to stderr the statement liveness information associated with
96+
/// each basic block.
97+
void dumpStmtLiveness(const SourceManager &M);
9498

9599
void runOnAllBlocks(Observer &obs);
96100

include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,9 @@ def DominatorsTreeDumper : Checker<"DumpDominators">,
707707
def LiveVariablesDumper : Checker<"DumpLiveVars">,
708708
HelpText<"Print results of live variable analysis">;
709709

710+
def LiveStatementsDumper : Checker<"DumpLiveStmts">,
711+
HelpText<"Print results of live statement analysis">;
712+
710713
def CFGViewer : Checker<"ViewCFG">,
711714
HelpText<"View Control-Flow Graphs using GraphViz">;
712715

include/clang/module.modulemap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ module Clang_StaticAnalyzer_Core {
122122
umbrella "StaticAnalyzer/Core"
123123

124124
textual header "StaticAnalyzer/Core/Analyses.def"
125+
textual header "StaticAnalyzer/Core/AnalyzerOptions.def"
125126
textual header "StaticAnalyzer/Core/PathSensitive/SVals.def"
126127
textual header "StaticAnalyzer/Core/PathSensitive/Symbols.def"
127128
textual header "StaticAnalyzer/Core/PathSensitive/Regions.def"

lib/Analysis/LiveVariables.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class LiveVariablesImpl {
9393
LiveVariables::Observer *obs = nullptr);
9494

9595
void dumpBlockLiveness(const SourceManager& M);
96+
void dumpStmtLiveness(const SourceManager& M);
9697

9798
LiveVariablesImpl(AnalysisDeclContext &ac, bool KillAtAssign)
9899
: analysisContext(ac),
@@ -327,6 +328,35 @@ void TransferFunctions::Visit(Stmt *S) {
327328
// No need to unconditionally visit subexpressions.
328329
return;
329330
}
331+
case Stmt::IfStmtClass: {
332+
// If one of the branches is an expression rather than a compound
333+
// statement, it will be bad if we mark it as live at the terminator
334+
// of the if-statement (i.e., immediately after the condition expression).
335+
AddLiveStmt(val.liveStmts, LV.SSetFact, cast<IfStmt>(S)->getCond());
336+
return;
337+
}
338+
case Stmt::WhileStmtClass: {
339+
// If the loop body is an expression rather than a compound statement,
340+
// it will be bad if we mark it as live at the terminator of the loop
341+
// (i.e., immediately after the condition expression).
342+
AddLiveStmt(val.liveStmts, LV.SSetFact, cast<WhileStmt>(S)->getCond());
343+
return;
344+
}
345+
case Stmt::DoStmtClass: {
346+
// If the loop body is an expression rather than a compound statement,
347+
// it will be bad if we mark it as live at the terminator of the loop
348+
// (i.e., immediately after the condition expression).
349+
AddLiveStmt(val.liveStmts, LV.SSetFact, cast<DoStmt>(S)->getCond());
350+
return;
351+
}
352+
case Stmt::ForStmtClass: {
353+
// If the loop body is an expression rather than a compound statement,
354+
// it will be bad if we mark it as live at the terminator of the loop
355+
// (i.e., immediately after the condition expression).
356+
AddLiveStmt(val.liveStmts, LV.SSetFact, cast<ForStmt>(S)->getCond());
357+
return;
358+
}
359+
330360
}
331361

332362
for (Stmt *Child : S->children()) {
@@ -633,5 +663,23 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
633663
llvm::errs() << "\n";
634664
}
635665

666+
void LiveVariables::dumpStmtLiveness(const SourceManager &M) {
667+
getImpl(impl).dumpStmtLiveness(M);
668+
}
669+
670+
void LiveVariablesImpl::dumpStmtLiveness(const SourceManager &M) {
671+
// Don't iterate over blockEndsToLiveness directly because it's not sorted.
672+
for (auto I : *analysisContext.getCFG()) {
673+
674+
llvm::errs() << "\n[ B" << I->getBlockID()
675+
<< " (live statements at block exit) ]\n";
676+
for (auto S : blocksEndToLiveness[I].liveStmts) {
677+
llvm::errs() << "\n";
678+
S->dump();
679+
}
680+
llvm::errs() << "\n";
681+
}
682+
}
683+
636684
const void *LiveVariables::getTag() { static int x; return &x; }
637685
const void *RelaxedLiveVariables::getTag() { static int x; return &x; }

lib/Driver/ToolChains/Arch/AArch64.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,17 @@ using namespace clang::driver::tools;
1919
using namespace clang;
2020
using namespace llvm::opt;
2121

22+
/// \returns true if the given triple can determine the default CPU type even
23+
/// if -arch is not specified.
24+
static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) {
25+
return Triple.isOSDarwin();
26+
}
27+
2228
/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
2329
/// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is
2430
/// provided, or to nullptr otherwise.
25-
std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
31+
std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
32+
const llvm::Triple &Triple, Arg *&A) {
2633
std::string CPU;
2734
// If we have -mcpu, use that.
2835
if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
@@ -36,9 +43,9 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
3643
else if (CPU.size())
3744
return CPU;
3845

39-
// Make sure we pick "cyclone" if -arch is used.
40-
// FIXME: Should this be picked by checking the target triple instead?
41-
if (Args.getLastArg(options::OPT_arch))
46+
// Make sure we pick "cyclone" if -arch is used or when targetting a Darwin
47+
// OS.
48+
if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
4249
return "cyclone";
4350

4451
return "generic";
@@ -152,7 +159,9 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
152159
return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
153160
}
154161

155-
void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
162+
void aarch64::getAArch64TargetFeatures(const Driver &D,
163+
const llvm::Triple &Triple,
164+
const ArgList &Args,
156165
std::vector<StringRef> &Features) {
157166
Arg *A;
158167
bool success = true;
@@ -162,19 +171,20 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
162171
success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
163172
else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
164173
success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
165-
else if (Args.hasArg(options::OPT_arch))
166-
success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A),
167-
Args, Features);
174+
else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))
175+
success = getAArch64ArchFeaturesFromMcpu(
176+
D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
168177

169178
if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
170179
success =
171180
getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
172181
else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
173182
success =
174183
getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
175-
else if (success && Args.hasArg(options::OPT_arch))
184+
else if (success &&
185+
(Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple)))
176186
success = getAArch64MicroArchFeaturesFromMcpu(
177-
D, getAArch64TargetCPU(Args, A), Args, Features);
187+
D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
178188

179189
if (!success)
180190
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);

lib/Driver/ToolChains/Arch/AArch64.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ namespace driver {
2121
namespace tools {
2222
namespace aarch64 {
2323

24-
void getAArch64TargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
24+
void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
25+
const llvm::opt::ArgList &Args,
2526
std::vector<llvm::StringRef> &Features);
2627

2728
std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
28-
llvm::opt::Arg *&A);
29+
const llvm::Triple &Triple, llvm::opt::Arg *&A);
2930

3031
} // end namespace aarch64
3132
} // end namespace target

lib/Driver/ToolChains/Clang.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
341341
break;
342342
case llvm::Triple::aarch64:
343343
case llvm::Triple::aarch64_be:
344-
aarch64::getAArch64TargetFeatures(D, Args, Features);
344+
aarch64::getAArch64TargetFeatures(D, Triple, Args, Features);
345345
break;
346346
case llvm::Triple::x86:
347347
case llvm::Triple::x86_64:

lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
270270

271271
case llvm::Triple::aarch64:
272272
case llvm::Triple::aarch64_be:
273-
return aarch64::getAArch64TargetCPU(Args, A);
273+
return aarch64::getAArch64TargetCPU(Args, T, A);
274274

275275
case llvm::Triple::arm:
276276
case llvm::Triple::armeb:

lib/Parse/ParseDecl.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6256,7 +6256,16 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
62566256
SmallVector<NamedDecl *, 0> DeclsInPrototype;
62576257
if (getCurScope()->getFlags() & Scope::FunctionDeclarationScope &&
62586258
!getLangOpts().CPlusPlus) {
6259-
for (Decl *D : getCurScope()->decls()) {
6259+
// The decls in the scope are in arbitrary order. Add them in sorted order
6260+
// now and allow for the declarator chunk to always contain the decls in
6261+
// deterministic order. This is necessary because ActOnFunctionDeclarator
6262+
// copies the declarator chunk as is when populating the decl context,
6263+
// which could be later serialized for modules or PCHs.
6264+
SmallVector<Decl *, 8> SortedDecls(getCurScope()->decls());
6265+
llvm::sort(SortedDecls, [](const Decl *L, const Decl *R) {
6266+
return L->getID() < R->getID();
6267+
});
6268+
for (Decl *D : SortedDecls) {
62606269
NamedDecl *ND = dyn_cast<NamedDecl>(D);
62616270
if (!ND || isa<ParmVarDecl>(ND))
62626271
continue;

lib/StaticAnalyzer/Checkers/DebugCheckers.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,25 @@ void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
6868
mgr.registerChecker<LiveVariablesDumper>();
6969
}
7070

71+
//===----------------------------------------------------------------------===//
72+
// LiveStatementsDumper
73+
//===----------------------------------------------------------------------===//
74+
75+
namespace {
76+
class LiveStatementsDumper : public Checker<check::ASTCodeBody> {
77+
public:
78+
void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
79+
BugReporter &BR) const {
80+
if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))
81+
L->dumpStmtLiveness(Mgr.getSourceManager());
82+
}
83+
};
84+
}
85+
86+
void ento::registerLiveStatementsDumper(CheckerManager &mgr) {
87+
mgr.registerChecker<LiveStatementsDumper>();
88+
}
89+
7190
//===----------------------------------------------------------------------===//
7291
// CFGViewer
7392
//===----------------------------------------------------------------------===//

lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ class ObjCContainersChecker : public Checker< check::PreStmt<CallExpr>,
5757
const InvalidatedSymbols &Escaped,
5858
const CallEvent *Call,
5959
PointerEscapeKind Kind) const;
60+
61+
void printState(raw_ostream &OS, ProgramStateRef State,
62+
const char *NL, const char *Sep) const;
6063
};
6164
} // end anonymous namespace
6265

@@ -144,6 +147,8 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
144147
initBugType();
145148
auto R = llvm::make_unique<BugReport>(*BT, "Index is out of bounds", N);
146149
R->addRange(IdxExpr->getSourceRange());
150+
bugreporter::trackExpressionValue(N, IdxExpr, *R,
151+
/*EnableNullFPSuppression=*/false);
147152
C.emitReport(std::move(R));
148153
return;
149154
}
@@ -166,6 +171,18 @@ ObjCContainersChecker::checkPointerEscape(ProgramStateRef State,
166171
return State;
167172
}
168173

174+
void ObjCContainersChecker::printState(raw_ostream &OS, ProgramStateRef State,
175+
const char *NL, const char *Sep) const {
176+
ArraySizeMapTy Map = State->get<ArraySizeMap>();
177+
if (Map.isEmpty())
178+
return;
179+
180+
OS << Sep << "ObjC container sizes :" << NL;
181+
for (auto I : Map) {
182+
OS << I.first << " : " << I.second << NL;
183+
}
184+
}
185+
169186
/// Register checker.
170187
void ento::registerObjCContainersChecker(CheckerManager &mgr) {
171188
mgr.registerChecker<ObjCContainersChecker>();

lib/StaticAnalyzer/Core/CallEvent.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ const BlockDataRegion *BlockCall::getBlockRegion() const {
837837
ArrayRef<ParmVarDecl*> BlockCall::parameters() const {
838838
const BlockDecl *D = getDecl();
839839
if (!D)
840-
return nullptr;
840+
return None;
841841
return D->parameters();
842842
}
843843

0 commit comments

Comments
 (0)