Bug Summary

File:build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/clang/lib/CodeGen/CoverageMappingGen.cpp
Warning:line 271, column 26
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CoverageMappingGen.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm -resource-dir /usr/lib/llvm-15/lib/clang/15.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/lib/CodeGen -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/clang/lib/CodeGen -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/clang/include -I tools/clang/include -I include -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-15/lib/clang/15.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm=build-llvm -fmacro-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm=build-llvm -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm=build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-04-20-140412-16051-1 -x c++ /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/clang/lib/CodeGen/CoverageMappingGen.cpp
1//===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===//
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// Instrumentation-based code coverage mapping generator
10//
11//===----------------------------------------------------------------------===//
12
13#include "CoverageMappingGen.h"
14#include "CodeGenFunction.h"
15#include "clang/AST/StmtVisitor.h"
16#include "clang/Basic/Diagnostic.h"
17#include "clang/Basic/FileManager.h"
18#include "clang/Frontend/FrontendDiagnostic.h"
19#include "clang/Lex/Lexer.h"
20#include "llvm/ADT/Optional.h"
21#include "llvm/ADT/SmallSet.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/ProfileData/Coverage/CoverageMapping.h"
24#include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
25#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
26#include "llvm/ProfileData/InstrProfReader.h"
27#include "llvm/Support/FileSystem.h"
28#include "llvm/Support/Path.h"
29
30// This selects the coverage mapping format defined when `InstrProfData.inc`
31// is textually included.
32#define COVMAP_V3
33
34static llvm::cl::opt<bool> EmptyLineCommentCoverage(
35 "emptyline-comment-coverage",
36 llvm::cl::desc("Emit emptylines and comment lines as skipped regions (only "
37 "disable it on test)"),
38 llvm::cl::init(true), llvm::cl::Hidden);
39
40using namespace clang;
41using namespace CodeGen;
42using namespace llvm::coverage;
43
44CoverageSourceInfo *
45CoverageMappingModuleGen::setUpCoverageCallbacks(Preprocessor &PP) {
46 CoverageSourceInfo *CoverageInfo =
47 new CoverageSourceInfo(PP.getSourceManager());
48 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(CoverageInfo));
49 if (EmptyLineCommentCoverage) {
50 PP.addCommentHandler(CoverageInfo);
51 PP.setEmptylineHandler(CoverageInfo);
52 PP.setPreprocessToken(true);
53 PP.setTokenWatcher([CoverageInfo](clang::Token Tok) {
54 // Update previous token location.
55 CoverageInfo->PrevTokLoc = Tok.getLocation();
56 if (Tok.getKind() != clang::tok::eod)
57 CoverageInfo->updateNextTokLoc(Tok.getLocation());
58 });
59 }
60 return CoverageInfo;
61}
62
63void CoverageSourceInfo::AddSkippedRange(SourceRange Range) {
64 if (EmptyLineCommentCoverage && !SkippedRanges.empty() &&
65 PrevTokLoc == SkippedRanges.back().PrevTokLoc &&
66 SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(),
67 Range.getBegin()))
68 SkippedRanges.back().Range.setEnd(Range.getEnd());
69 else
70 SkippedRanges.push_back({Range, PrevTokLoc});
71}
72
73void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) {
74 AddSkippedRange(Range);
75}
76
77void CoverageSourceInfo::HandleEmptyline(SourceRange Range) {
78 AddSkippedRange(Range);
79}
80
81bool CoverageSourceInfo::HandleComment(Preprocessor &PP, SourceRange Range) {
82 AddSkippedRange(Range);
83 return false;
84}
85
86void CoverageSourceInfo::updateNextTokLoc(SourceLocation Loc) {
87 if (!SkippedRanges.empty() && SkippedRanges.back().NextTokLoc.isInvalid())
88 SkippedRanges.back().NextTokLoc = Loc;
89}
90
91namespace {
92
93/// A region of source code that can be mapped to a counter.
94class SourceMappingRegion {
95 /// Primary Counter that is also used for Branch Regions for "True" branches.
96 Counter Count;
97
98 /// Secondary Counter used for Branch Regions for "False" branches.
99 Optional<Counter> FalseCount;
100
101 /// The region's starting location.
102 Optional<SourceLocation> LocStart;
103
104 /// The region's ending location.
105 Optional<SourceLocation> LocEnd;
106
107 /// Whether this region is a gap region. The count from a gap region is set
108 /// as the line execution count if there are no other regions on the line.
109 bool GapRegion;
110
111public:
112 SourceMappingRegion(Counter Count, Optional<SourceLocation> LocStart,
113 Optional<SourceLocation> LocEnd, bool GapRegion = false)
114 : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {
115 }
116
117 SourceMappingRegion(Counter Count, Optional<Counter> FalseCount,
118 Optional<SourceLocation> LocStart,
119 Optional<SourceLocation> LocEnd, bool GapRegion = false)
120 : Count(Count), FalseCount(FalseCount), LocStart(LocStart),
121 LocEnd(LocEnd), GapRegion(GapRegion) {}
122
123 const Counter &getCounter() const { return Count; }
124
125 const Counter &getFalseCounter() const {
126 assert(FalseCount && "Region has no alternate counter")(static_cast <bool> (FalseCount && "Region has no alternate counter"
) ? void (0) : __assert_fail ("FalseCount && \"Region has no alternate counter\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 126, __extension__
__PRETTY_FUNCTION__))
;
127 return *FalseCount;
128 }
129
130 void setCounter(Counter C) { Count = C; }
131
132 bool hasStartLoc() const { return LocStart.hasValue(); }
133
134 void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
135
136 SourceLocation getBeginLoc() const {
137 assert(LocStart && "Region has no start location")(static_cast <bool> (LocStart && "Region has no start location"
) ? void (0) : __assert_fail ("LocStart && \"Region has no start location\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 137, __extension__
__PRETTY_FUNCTION__))
;
138 return *LocStart;
139 }
140
141 bool hasEndLoc() const { return LocEnd.hasValue(); }
142
143 void setEndLoc(SourceLocation Loc) {
144 assert(Loc.isValid() && "Setting an invalid end location")(static_cast <bool> (Loc.isValid() && "Setting an invalid end location"
) ? void (0) : __assert_fail ("Loc.isValid() && \"Setting an invalid end location\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 144, __extension__
__PRETTY_FUNCTION__))
;
145 LocEnd = Loc;
146 }
147
148 SourceLocation getEndLoc() const {
149 assert(LocEnd && "Region has no end location")(static_cast <bool> (LocEnd && "Region has no end location"
) ? void (0) : __assert_fail ("LocEnd && \"Region has no end location\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 149, __extension__
__PRETTY_FUNCTION__))
;
150 return *LocEnd;
151 }
152
153 bool isGap() const { return GapRegion; }
154
155 void setGap(bool Gap) { GapRegion = Gap; }
156
157 bool isBranch() const { return FalseCount.hasValue(); }
158};
159
160/// Spelling locations for the start and end of a source region.
161struct SpellingRegion {
162 /// The line where the region starts.
163 unsigned LineStart;
164
165 /// The column where the region starts.
166 unsigned ColumnStart;
167
168 /// The line where the region ends.
169 unsigned LineEnd;
170
171 /// The column where the region ends.
172 unsigned ColumnEnd;
173
174 SpellingRegion(SourceManager &SM, SourceLocation LocStart,
175 SourceLocation LocEnd) {
176 LineStart = SM.getSpellingLineNumber(LocStart);
177 ColumnStart = SM.getSpellingColumnNumber(LocStart);
178 LineEnd = SM.getSpellingLineNumber(LocEnd);
179 ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
180 }
181
182 SpellingRegion(SourceManager &SM, SourceMappingRegion &R)
183 : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {}
184
185 /// Check if the start and end locations appear in source order, i.e
186 /// top->bottom, left->right.
187 bool isInSourceOrder() const {
188 return (LineStart < LineEnd) ||
189 (LineStart == LineEnd && ColumnStart <= ColumnEnd);
190 }
191};
192
193/// Provides the common functionality for the different
194/// coverage mapping region builders.
195class CoverageMappingBuilder {
196public:
197 CoverageMappingModuleGen &CVM;
198 SourceManager &SM;
199 const LangOptions &LangOpts;
200
201private:
202 /// Map of clang's FileIDs to IDs used for coverage mapping.
203 llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
204 FileIDMapping;
205
206public:
207 /// The coverage mapping regions for this function
208 llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
209 /// The source mapping regions for this function.
210 std::vector<SourceMappingRegion> SourceRegions;
211
212 /// A set of regions which can be used as a filter.
213 ///
214 /// It is produced by emitExpansionRegions() and is used in
215 /// emitSourceRegions() to suppress producing code regions if
216 /// the same area is covered by expansion regions.
217 typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
218 SourceRegionFilter;
219
220 CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
221 const LangOptions &LangOpts)
222 : CVM(CVM), SM(SM), LangOpts(LangOpts) {}
223
224 /// Return the precise end location for the given token.
225 SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
226 // We avoid getLocForEndOfToken here, because it doesn't do what we want for
227 // macro locations, which we just treat as expanded files.
228 unsigned TokLen =
229 Lexer::MeasureTokenLength(SM.getSpellingLoc(Loc), SM, LangOpts);
230 return Loc.getLocWithOffset(TokLen);
231 }
232
233 /// Return the start location of an included file or expanded macro.
234 SourceLocation getStartOfFileOrMacro(SourceLocation Loc) {
235 if (Loc.isMacroID())
236 return Loc.getLocWithOffset(-SM.getFileOffset(Loc));
237 return SM.getLocForStartOfFile(SM.getFileID(Loc));
238 }
239
240 /// Return the end location of an included file or expanded macro.
241 SourceLocation getEndOfFileOrMacro(SourceLocation Loc) {
242 if (Loc.isMacroID())
243 return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) -
244 SM.getFileOffset(Loc));
245 return SM.getLocForEndOfFile(SM.getFileID(Loc));
246 }
247
248 /// Find out where the current file is included or macro is expanded.
249 SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) {
250 return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin()
251 : SM.getIncludeLoc(SM.getFileID(Loc));
252 }
253
254 /// Return true if \c Loc is a location in a built-in macro.
255 bool isInBuiltin(SourceLocation Loc) {
256 return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>";
257 }
258
259 /// Check whether \c Loc is included or expanded from \c Parent.
260 bool isNestedIn(SourceLocation Loc, FileID Parent) {
261 do {
262 Loc = getIncludeOrExpansionLoc(Loc);
263 if (Loc.isInvalid())
264 return false;
265 } while (!SM.isInFileID(Loc, Parent));
266 return true;
267 }
268
269 /// Get the start of \c S ignoring macro arguments and builtin macros.
270 SourceLocation getStart(const Stmt *S) {
271 SourceLocation Loc = S->getBeginLoc();
13
Called C++ object pointer is null
272 while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
273 Loc = SM.getImmediateExpansionRange(Loc).getBegin();
274 return Loc;
275 }
276
277 /// Get the end of \c S ignoring macro arguments and builtin macros.
278 SourceLocation getEnd(const Stmt *S) {
279 SourceLocation Loc = S->getEndLoc();
280 while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
281 Loc = SM.getImmediateExpansionRange(Loc).getBegin();
282 return getPreciseTokenLocEnd(Loc);
283 }
284
285 /// Find the set of files we have regions for and assign IDs
286 ///
287 /// Fills \c Mapping with the virtual file mapping needed to write out
288 /// coverage and collects the necessary file information to emit source and
289 /// expansion regions.
290 void gatherFileIDs(SmallVectorImpl<unsigned> &Mapping) {
291 FileIDMapping.clear();
292
293 llvm::SmallSet<FileID, 8> Visited;
294 SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs;
295 for (const auto &Region : SourceRegions) {
296 SourceLocation Loc = Region.getBeginLoc();
297 FileID File = SM.getFileID(Loc);
298 if (!Visited.insert(File).second)
299 continue;
300
301 // Do not map FileID's associated with system headers.
302 if (SM.isInSystemHeader(SM.getSpellingLoc(Loc)))
303 continue;
304
305 unsigned Depth = 0;
306 for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
307 Parent.isValid(); Parent = getIncludeOrExpansionLoc(Parent))
308 ++Depth;
309 FileLocs.push_back(std::make_pair(Loc, Depth));
310 }
311 llvm::stable_sort(FileLocs, llvm::less_second());
312
313 for (const auto &FL : FileLocs) {
314 SourceLocation Loc = FL.first;
315 FileID SpellingFile = SM.getDecomposedSpellingLoc(Loc).first;
316 auto Entry = SM.getFileEntryForID(SpellingFile);
317 if (!Entry)
318 continue;
319
320 FileIDMapping[SM.getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
321 Mapping.push_back(CVM.getFileID(Entry));
322 }
323 }
324
325 /// Get the coverage mapping file ID for \c Loc.
326 ///
327 /// If such file id doesn't exist, return None.
328 Optional<unsigned> getCoverageFileID(SourceLocation Loc) {
329 auto Mapping = FileIDMapping.find(SM.getFileID(Loc));
330 if (Mapping != FileIDMapping.end())
331 return Mapping->second.first;
332 return None;
333 }
334
335 /// This shrinks the skipped range if it spans a line that contains a
336 /// non-comment token. If shrinking the skipped range would make it empty,
337 /// this returns None.
338 Optional<SpellingRegion> adjustSkippedRange(SourceManager &SM,
339 SourceLocation LocStart,
340 SourceLocation LocEnd,
341 SourceLocation PrevTokLoc,
342 SourceLocation NextTokLoc) {
343 SpellingRegion SR{SM, LocStart, LocEnd};
344 SR.ColumnStart = 1;
345 if (PrevTokLoc.isValid() && SM.isWrittenInSameFile(LocStart, PrevTokLoc) &&
346 SR.LineStart == SM.getSpellingLineNumber(PrevTokLoc))
347 SR.LineStart++;
348 if (NextTokLoc.isValid() && SM.isWrittenInSameFile(LocEnd, NextTokLoc) &&
349 SR.LineEnd == SM.getSpellingLineNumber(NextTokLoc)) {
350 SR.LineEnd--;
351 SR.ColumnEnd++;
352 }
353 if (SR.isInSourceOrder())
354 return SR;
355 return None;
356 }
357
358 /// Gather all the regions that were skipped by the preprocessor
359 /// using the constructs like #if or comments.
360 void gatherSkippedRegions() {
361 /// An array of the minimum lineStarts and the maximum lineEnds
362 /// for mapping regions from the appropriate source files.
363 llvm::SmallVector<std::pair<unsigned, unsigned>, 8> FileLineRanges;
364 FileLineRanges.resize(
365 FileIDMapping.size(),
366 std::make_pair(std::numeric_limits<unsigned>::max(), 0));
367 for (const auto &R : MappingRegions) {
368 FileLineRanges[R.FileID].first =
369 std::min(FileLineRanges[R.FileID].first, R.LineStart);
370 FileLineRanges[R.FileID].second =
371 std::max(FileLineRanges[R.FileID].second, R.LineEnd);
372 }
373
374 auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
375 for (auto &I : SkippedRanges) {
376 SourceRange Range = I.Range;
377 auto LocStart = Range.getBegin();
378 auto LocEnd = Range.getEnd();
379 assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&(static_cast <bool> (SM.isWrittenInSameFile(LocStart, LocEnd
) && "region spans multiple files") ? void (0) : __assert_fail
("SM.isWrittenInSameFile(LocStart, LocEnd) && \"region spans multiple files\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 380, __extension__
__PRETTY_FUNCTION__))
380 "region spans multiple files")(static_cast <bool> (SM.isWrittenInSameFile(LocStart, LocEnd
) && "region spans multiple files") ? void (0) : __assert_fail
("SM.isWrittenInSameFile(LocStart, LocEnd) && \"region spans multiple files\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 380, __extension__
__PRETTY_FUNCTION__))
;
381
382 auto CovFileID = getCoverageFileID(LocStart);
383 if (!CovFileID)
384 continue;
385 Optional<SpellingRegion> SR =
386 adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc, I.NextTokLoc);
387 if (!SR.hasValue())
388 continue;
389 auto Region = CounterMappingRegion::makeSkipped(
390 *CovFileID, SR->LineStart, SR->ColumnStart, SR->LineEnd,
391 SR->ColumnEnd);
392 // Make sure that we only collect the regions that are inside
393 // the source code of this function.
394 if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
395 Region.LineEnd <= FileLineRanges[*CovFileID].second)
396 MappingRegions.push_back(Region);
397 }
398 }
399
400 /// Generate the coverage counter mapping regions from collected
401 /// source regions.
402 void emitSourceRegions(const SourceRegionFilter &Filter) {
403 for (const auto &Region : SourceRegions) {
404 assert(Region.hasEndLoc() && "incomplete region")(static_cast <bool> (Region.hasEndLoc() && "incomplete region"
) ? void (0) : __assert_fail ("Region.hasEndLoc() && \"incomplete region\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 404, __extension__
__PRETTY_FUNCTION__))
;
405
406 SourceLocation LocStart = Region.getBeginLoc();
407 assert(SM.getFileID(LocStart).isValid() && "region in invalid file")(static_cast <bool> (SM.getFileID(LocStart).isValid() &&
"region in invalid file") ? void (0) : __assert_fail ("SM.getFileID(LocStart).isValid() && \"region in invalid file\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 407, __extension__
__PRETTY_FUNCTION__))
;
408
409 // Ignore regions from system headers.
410 if (SM.isInSystemHeader(SM.getSpellingLoc(LocStart)))
411 continue;
412
413 auto CovFileID = getCoverageFileID(LocStart);
414 // Ignore regions that don't have a file, such as builtin macros.
415 if (!CovFileID)
416 continue;
417
418 SourceLocation LocEnd = Region.getEndLoc();
419 assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&(static_cast <bool> (SM.isWrittenInSameFile(LocStart, LocEnd
) && "region spans multiple files") ? void (0) : __assert_fail
("SM.isWrittenInSameFile(LocStart, LocEnd) && \"region spans multiple files\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 420, __extension__
__PRETTY_FUNCTION__))
420 "region spans multiple files")(static_cast <bool> (SM.isWrittenInSameFile(LocStart, LocEnd
) && "region spans multiple files") ? void (0) : __assert_fail
("SM.isWrittenInSameFile(LocStart, LocEnd) && \"region spans multiple files\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 420, __extension__
__PRETTY_FUNCTION__))
;
421
422 // Don't add code regions for the area covered by expansion regions.
423 // This not only suppresses redundant regions, but sometimes prevents
424 // creating regions with wrong counters if, for example, a statement's
425 // body ends at the end of a nested macro.
426 if (Filter.count(std::make_pair(LocStart, LocEnd)))
427 continue;
428
429 // Find the spelling locations for the mapping region.
430 SpellingRegion SR{SM, LocStart, LocEnd};
431 assert(SR.isInSourceOrder() && "region start and end out of order")(static_cast <bool> (SR.isInSourceOrder() && "region start and end out of order"
) ? void (0) : __assert_fail ("SR.isInSourceOrder() && \"region start and end out of order\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 431, __extension__
__PRETTY_FUNCTION__))
;
432
433 if (Region.isGap()) {
434 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
435 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
436 SR.LineEnd, SR.ColumnEnd));
437 } else if (Region.isBranch()) {
438 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
439 Region.getCounter(), Region.getFalseCounter(), *CovFileID,
440 SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd));
441 } else {
442 MappingRegions.push_back(CounterMappingRegion::makeRegion(
443 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
444 SR.LineEnd, SR.ColumnEnd));
445 }
446 }
447 }
448
449 /// Generate expansion regions for each virtual file we've seen.
450 SourceRegionFilter emitExpansionRegions() {
451 SourceRegionFilter Filter;
452 for (const auto &FM : FileIDMapping) {
453 SourceLocation ExpandedLoc = FM.second.second;
454 SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc);
455 if (ParentLoc.isInvalid())
456 continue;
457
458 auto ParentFileID = getCoverageFileID(ParentLoc);
459 if (!ParentFileID)
460 continue;
461 auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
462 assert(ExpandedFileID && "expansion in uncovered file")(static_cast <bool> (ExpandedFileID && "expansion in uncovered file"
) ? void (0) : __assert_fail ("ExpandedFileID && \"expansion in uncovered file\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 462, __extension__
__PRETTY_FUNCTION__))
;
463
464 SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc);
465 assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) &&(static_cast <bool> (SM.isWrittenInSameFile(ParentLoc, LocEnd
) && "region spans multiple files") ? void (0) : __assert_fail
("SM.isWrittenInSameFile(ParentLoc, LocEnd) && \"region spans multiple files\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 466, __extension__
__PRETTY_FUNCTION__))
466 "region spans multiple files")(static_cast <bool> (SM.isWrittenInSameFile(ParentLoc, LocEnd
) && "region spans multiple files") ? void (0) : __assert_fail
("SM.isWrittenInSameFile(ParentLoc, LocEnd) && \"region spans multiple files\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 466, __extension__
__PRETTY_FUNCTION__))
;
467 Filter.insert(std::make_pair(ParentLoc, LocEnd));
468
469 SpellingRegion SR{SM, ParentLoc, LocEnd};
470 assert(SR.isInSourceOrder() && "region start and end out of order")(static_cast <bool> (SR.isInSourceOrder() && "region start and end out of order"
) ? void (0) : __assert_fail ("SR.isInSourceOrder() && \"region start and end out of order\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 470, __extension__
__PRETTY_FUNCTION__))
;
471 MappingRegions.push_back(CounterMappingRegion::makeExpansion(
472 *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
473 SR.LineEnd, SR.ColumnEnd));
474 }
475 return Filter;
476 }
477};
478
479/// Creates unreachable coverage regions for the functions that
480/// are not emitted.
481struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
482 EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
483 const LangOptions &LangOpts)
484 : CoverageMappingBuilder(CVM, SM, LangOpts) {}
485
486 void VisitDecl(const Decl *D) {
487 if (!D->hasBody())
488 return;
489 auto Body = D->getBody();
490 SourceLocation Start = getStart(Body);
491 SourceLocation End = getEnd(Body);
492 if (!SM.isWrittenInSameFile(Start, End)) {
493 // Walk up to find the common ancestor.
494 // Correct the locations accordingly.
495 FileID StartFileID = SM.getFileID(Start);
496 FileID EndFileID = SM.getFileID(End);
497 while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
498 Start = getIncludeOrExpansionLoc(Start);
499 assert(Start.isValid() &&(static_cast <bool> (Start.isValid() && "Declaration start location not nested within a known region"
) ? void (0) : __assert_fail ("Start.isValid() && \"Declaration start location not nested within a known region\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 500, __extension__
__PRETTY_FUNCTION__))
500 "Declaration start location not nested within a known region")(static_cast <bool> (Start.isValid() && "Declaration start location not nested within a known region"
) ? void (0) : __assert_fail ("Start.isValid() && \"Declaration start location not nested within a known region\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 500, __extension__
__PRETTY_FUNCTION__))
;
501 StartFileID = SM.getFileID(Start);
502 }
503 while (StartFileID != EndFileID) {
504 End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
505 assert(End.isValid() &&(static_cast <bool> (End.isValid() && "Declaration end location not nested within a known region"
) ? void (0) : __assert_fail ("End.isValid() && \"Declaration end location not nested within a known region\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 506, __extension__
__PRETTY_FUNCTION__))
506 "Declaration end location not nested within a known region")(static_cast <bool> (End.isValid() && "Declaration end location not nested within a known region"
) ? void (0) : __assert_fail ("End.isValid() && \"Declaration end location not nested within a known region\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 506, __extension__
__PRETTY_FUNCTION__))
;
507 EndFileID = SM.getFileID(End);
508 }
509 }
510 SourceRegions.emplace_back(Counter(), Start, End);
511 }
512
513 /// Write the mapping data to the output stream
514 void write(llvm::raw_ostream &OS) {
515 SmallVector<unsigned, 16> FileIDMapping;
516 gatherFileIDs(FileIDMapping);
517 emitSourceRegions(SourceRegionFilter());
518
519 if (MappingRegions.empty())
520 return;
521
522 CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions);
523 Writer.write(OS);
524 }
525};
526
527/// A StmtVisitor that creates coverage mapping regions which map
528/// from the source code locations to the PGO counters.
529struct CounterCoverageMappingBuilder
530 : public CoverageMappingBuilder,
531 public ConstStmtVisitor<CounterCoverageMappingBuilder> {
532 /// The map of statements to count values.
533 llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
534
535 /// A stack of currently live regions.
536 std::vector<SourceMappingRegion> RegionStack;
537
538 CounterExpressionBuilder Builder;
539
540 /// A location in the most recently visited file or macro.
541 ///
542 /// This is used to adjust the active source regions appropriately when
543 /// expressions cross file or macro boundaries.
544 SourceLocation MostRecentLocation;
545
546 /// Whether the visitor at a terminate statement.
547 bool HasTerminateStmt = false;
548
549 /// Gap region counter after terminate statement.
550 Counter GapRegionCounter;
551
552 /// Return a counter for the subtraction of \c RHS from \c LHS
553 Counter subtractCounters(Counter LHS, Counter RHS) {
554 return Builder.subtract(LHS, RHS);
555 }
556
557 /// Return a counter for the sum of \c LHS and \c RHS.
558 Counter addCounters(Counter LHS, Counter RHS) {
559 return Builder.add(LHS, RHS);
560 }
561
562 Counter addCounters(Counter C1, Counter C2, Counter C3) {
563 return addCounters(addCounters(C1, C2), C3);
564 }
565
566 /// Return the region counter for the given statement.
567 ///
568 /// This should only be called on statements that have a dedicated counter.
569 Counter getRegionCounter(const Stmt *S) {
570 return Counter::getCounter(CounterMap[S]);
571 }
572
573 /// Push a region onto the stack.
574 ///
575 /// Returns the index on the stack where the region was pushed. This can be
576 /// used with popRegions to exit a "scope", ending the region that was pushed.
577 size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None,
578 Optional<SourceLocation> EndLoc = None,
579 Optional<Counter> FalseCount = None) {
580
581 if (StartLoc && !FalseCount.hasValue()) {
582 MostRecentLocation = *StartLoc;
583 }
584
585 RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc);
586
587 return RegionStack.size() - 1;
588 }
589
590 size_t locationDepth(SourceLocation Loc) {
591 size_t Depth = 0;
592 while (Loc.isValid()) {
593 Loc = getIncludeOrExpansionLoc(Loc);
594 Depth++;
595 }
596 return Depth;
597 }
598
599 /// Pop regions from the stack into the function's list of regions.
600 ///
601 /// Adds all regions from \c ParentIndex to the top of the stack to the
602 /// function's \c SourceRegions.
603 void popRegions(size_t ParentIndex) {
604 assert(RegionStack.size() >= ParentIndex && "parent not in stack")(static_cast <bool> (RegionStack.size() >= ParentIndex
&& "parent not in stack") ? void (0) : __assert_fail
("RegionStack.size() >= ParentIndex && \"parent not in stack\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 604, __extension__
__PRETTY_FUNCTION__))
;
605 while (RegionStack.size() > ParentIndex) {
606 SourceMappingRegion &Region = RegionStack.back();
607 if (Region.hasStartLoc()) {
608 SourceLocation StartLoc = Region.getBeginLoc();
609 SourceLocation EndLoc = Region.hasEndLoc()
610 ? Region.getEndLoc()
611 : RegionStack[ParentIndex].getEndLoc();
612 bool isBranch = Region.isBranch();
613 size_t StartDepth = locationDepth(StartLoc);
614 size_t EndDepth = locationDepth(EndLoc);
615 while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
616 bool UnnestStart = StartDepth >= EndDepth;
617 bool UnnestEnd = EndDepth >= StartDepth;
618 if (UnnestEnd) {
619 // The region ends in a nested file or macro expansion. If the
620 // region is not a branch region, create a separate region for each
621 // expansion, and for all regions, update the EndLoc. Branch
622 // regions should not be split in order to keep a straightforward
623 // correspondance between the region and its associated branch
624 // condition, even if the condition spans multiple depths.
625 SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
626 assert(SM.isWrittenInSameFile(NestedLoc, EndLoc))(static_cast <bool> (SM.isWrittenInSameFile(NestedLoc, EndLoc
)) ? void (0) : __assert_fail ("SM.isWrittenInSameFile(NestedLoc, EndLoc)"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 626, __extension__
__PRETTY_FUNCTION__))
;
627
628 if (!isBranch && !isRegionAlreadyAdded(NestedLoc, EndLoc))
629 SourceRegions.emplace_back(Region.getCounter(), NestedLoc,
630 EndLoc);
631
632 EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
633 if (EndLoc.isInvalid())
634 llvm::report_fatal_error(
635 "File exit not handled before popRegions");
636 EndDepth--;
637 }
638 if (UnnestStart) {
639 // The region ends in a nested file or macro expansion. If the
640 // region is not a branch region, create a separate region for each
641 // expansion, and for all regions, update the StartLoc. Branch
642 // regions should not be split in order to keep a straightforward
643 // correspondance between the region and its associated branch
644 // condition, even if the condition spans multiple depths.
645 SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
646 assert(SM.isWrittenInSameFile(StartLoc, NestedLoc))(static_cast <bool> (SM.isWrittenInSameFile(StartLoc, NestedLoc
)) ? void (0) : __assert_fail ("SM.isWrittenInSameFile(StartLoc, NestedLoc)"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 646, __extension__
__PRETTY_FUNCTION__))
;
647
648 if (!isBranch && !isRegionAlreadyAdded(StartLoc, NestedLoc))
649 SourceRegions.emplace_back(Region.getCounter(), StartLoc,
650 NestedLoc);
651
652 StartLoc = getIncludeOrExpansionLoc(StartLoc);
653 if (StartLoc.isInvalid())
654 llvm::report_fatal_error(
655 "File exit not handled before popRegions");
656 StartDepth--;
657 }
658 }
659 Region.setStartLoc(StartLoc);
660 Region.setEndLoc(EndLoc);
661
662 if (!isBranch) {
663 MostRecentLocation = EndLoc;
664 // If this region happens to span an entire expansion, we need to
665 // make sure we don't overlap the parent region with it.
666 if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
667 EndLoc == getEndOfFileOrMacro(EndLoc))
668 MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
669 }
670
671 assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc))(static_cast <bool> (SM.isWrittenInSameFile(Region.getBeginLoc
(), EndLoc)) ? void (0) : __assert_fail ("SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc)"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 671, __extension__
__PRETTY_FUNCTION__))
;
672 assert(SpellingRegion(SM, Region).isInSourceOrder())(static_cast <bool> (SpellingRegion(SM, Region).isInSourceOrder
()) ? void (0) : __assert_fail ("SpellingRegion(SM, Region).isInSourceOrder()"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 672, __extension__
__PRETTY_FUNCTION__))
;
673 SourceRegions.push_back(Region);
674 }
675 RegionStack.pop_back();
676 }
677 }
678
679 /// Return the currently active region.
680 SourceMappingRegion &getRegion() {
681 assert(!RegionStack.empty() && "statement has no region")(static_cast <bool> (!RegionStack.empty() && "statement has no region"
) ? void (0) : __assert_fail ("!RegionStack.empty() && \"statement has no region\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 681, __extension__
__PRETTY_FUNCTION__))
;
682 return RegionStack.back();
683 }
684
685 /// Propagate counts through the children of \p S if \p VisitChildren is true.
686 /// Otherwise, only emit a count for \p S itself.
687 Counter propagateCounts(Counter TopCount, const Stmt *S,
688 bool VisitChildren = true) {
689 SourceLocation StartLoc = getStart(S);
11
Passing null pointer value via 1st parameter 'S'
12
Calling 'CoverageMappingBuilder::getStart'
690 SourceLocation EndLoc = getEnd(S);
691 size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
692 if (VisitChildren)
693 Visit(S);
694 Counter ExitCount = getRegion().getCounter();
695 popRegions(Index);
696
697 // The statement may be spanned by an expansion. Make sure we handle a file
698 // exit out of this expansion before moving to the next statement.
699 if (SM.isBeforeInTranslationUnit(StartLoc, S->getBeginLoc()))
700 MostRecentLocation = EndLoc;
701
702 return ExitCount;
703 }
704
705 /// Determine whether the given condition can be constant folded.
706 bool ConditionFoldsToBool(const Expr *Cond) {
707 Expr::EvalResult Result;
708 return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext()));
709 }
710
711 /// Create a Branch Region around an instrumentable condition for coverage
712 /// and add it to the function's SourceRegions. A branch region tracks a
713 /// "True" counter and a "False" counter for boolean expressions that
714 /// result in the generation of a branch.
715 void createBranchRegion(const Expr *C, Counter TrueCnt, Counter FalseCnt) {
716 // Check for NULL conditions.
717 if (!C)
718 return;
719
720 // Ensure we are an instrumentable condition (i.e. no "&&" or "||"). Push
721 // region onto RegionStack but immediately pop it (which adds it to the
722 // function's SourceRegions) because it doesn't apply to any other source
723 // code other than the Condition.
724 if (CodeGenFunction::isInstrumentedCondition(C)) {
725 // If a condition can fold to true or false, the corresponding branch
726 // will be removed. Create a region with both counters hard-coded to
727 // zero. This allows us to visualize them in a special way.
728 // Alternatively, we can prevent any optimization done via
729 // constant-folding by ensuring that ConstantFoldsToSimpleInteger() in
730 // CodeGenFunction.c always returns false, but that is very heavy-handed.
731 if (ConditionFoldsToBool(C))
732 popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C),
733 Counter::getZero()));
734 else
735 // Otherwise, create a region with the True counter and False counter.
736 popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt));
737 }
738 }
739
740 /// Create a Branch Region around a SwitchCase for code coverage
741 /// and add it to the function's SourceRegions.
742 void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt,
743 Counter FalseCnt) {
744 // Push region onto RegionStack but immediately pop it (which adds it to
745 // the function's SourceRegions) because it doesn't apply to any other
746 // source other than the SwitchCase.
747 popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt));
748 }
749
750 /// Check whether a region with bounds \c StartLoc and \c EndLoc
751 /// is already added to \c SourceRegions.
752 bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc,
753 bool isBranch = false) {
754 return llvm::any_of(
755 llvm::reverse(SourceRegions), [&](const SourceMappingRegion &Region) {
756 return Region.getBeginLoc() == StartLoc &&
757 Region.getEndLoc() == EndLoc && Region.isBranch() == isBranch;
758 });
759 }
760
761 /// Adjust the most recently visited location to \c EndLoc.
762 ///
763 /// This should be used after visiting any statements in non-source order.
764 void adjustForOutOfOrderTraversal(SourceLocation EndLoc) {
765 MostRecentLocation = EndLoc;
766 // The code region for a whole macro is created in handleFileExit() when
767 // it detects exiting of the virtual file of that macro. If we visited
768 // statements in non-source order, we might already have such a region
769 // added, for example, if a body of a loop is divided among multiple
770 // macros. Avoid adding duplicate regions in such case.
771 if (getRegion().hasEndLoc() &&
772 MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
773 isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
774 MostRecentLocation, getRegion().isBranch()))
775 MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
776 }
777
778 /// Adjust regions and state when \c NewLoc exits a file.
779 ///
780 /// If moving from our most recently tracked location to \c NewLoc exits any
781 /// files, this adjusts our current region stack and creates the file regions
782 /// for the exited file.
783 void handleFileExit(SourceLocation NewLoc) {
784 if (NewLoc.isInvalid() ||
785 SM.isWrittenInSameFile(MostRecentLocation, NewLoc))
786 return;
787
788 // If NewLoc is not in a file that contains MostRecentLocation, walk up to
789 // find the common ancestor.
790 SourceLocation LCA = NewLoc;
791 FileID ParentFile = SM.getFileID(LCA);
792 while (!isNestedIn(MostRecentLocation, ParentFile)) {
793 LCA = getIncludeOrExpansionLoc(LCA);
794 if (LCA.isInvalid() || SM.isWrittenInSameFile(LCA, MostRecentLocation)) {
795 // Since there isn't a common ancestor, no file was exited. We just need
796 // to adjust our location to the new file.
797 MostRecentLocation = NewLoc;
798 return;
799 }
800 ParentFile = SM.getFileID(LCA);
801 }
802
803 llvm::SmallSet<SourceLocation, 8> StartLocs;
804 Optional<Counter> ParentCounter;
805 for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
806 if (!I.hasStartLoc())
807 continue;
808 SourceLocation Loc = I.getBeginLoc();
809 if (!isNestedIn(Loc, ParentFile)) {
810 ParentCounter = I.getCounter();
811 break;
812 }
813
814 while (!SM.isInFileID(Loc, ParentFile)) {
815 // The most nested region for each start location is the one with the
816 // correct count. We avoid creating redundant regions by stopping once
817 // we've seen this region.
818 if (StartLocs.insert(Loc).second) {
819 if (I.isBranch())
820 SourceRegions.emplace_back(I.getCounter(), I.getFalseCounter(), Loc,
821 getEndOfFileOrMacro(Loc), I.isBranch());
822 else
823 SourceRegions.emplace_back(I.getCounter(), Loc,
824 getEndOfFileOrMacro(Loc));
825 }
826 Loc = getIncludeOrExpansionLoc(Loc);
827 }
828 I.setStartLoc(getPreciseTokenLocEnd(Loc));
829 }
830
831 if (ParentCounter) {
832 // If the file is contained completely by another region and doesn't
833 // immediately start its own region, the whole file gets a region
834 // corresponding to the parent.
835 SourceLocation Loc = MostRecentLocation;
836 while (isNestedIn(Loc, ParentFile)) {
837 SourceLocation FileStart = getStartOfFileOrMacro(Loc);
838 if (StartLocs.insert(FileStart).second) {
839 SourceRegions.emplace_back(*ParentCounter, FileStart,
840 getEndOfFileOrMacro(Loc));
841 assert(SpellingRegion(SM, SourceRegions.back()).isInSourceOrder())(static_cast <bool> (SpellingRegion(SM, SourceRegions.back
()).isInSourceOrder()) ? void (0) : __assert_fail ("SpellingRegion(SM, SourceRegions.back()).isInSourceOrder()"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 841, __extension__
__PRETTY_FUNCTION__))
;
842 }
843 Loc = getIncludeOrExpansionLoc(Loc);
844 }
845 }
846
847 MostRecentLocation = NewLoc;
848 }
849
850 /// Ensure that \c S is included in the current region.
851 void extendRegion(const Stmt *S) {
852 SourceMappingRegion &Region = getRegion();
853 SourceLocation StartLoc = getStart(S);
854
855 handleFileExit(StartLoc);
856 if (!Region.hasStartLoc())
857 Region.setStartLoc(StartLoc);
858 }
859
860 /// Mark \c S as a terminator, starting a zero region.
861 void terminateRegion(const Stmt *S) {
862 extendRegion(S);
863 SourceMappingRegion &Region = getRegion();
864 SourceLocation EndLoc = getEnd(S);
865 if (!Region.hasEndLoc())
866 Region.setEndLoc(EndLoc);
867 pushRegion(Counter::getZero());
868 HasTerminateStmt = true;
869 }
870
871 /// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
872 Optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
873 SourceLocation BeforeLoc) {
874 // If AfterLoc is in function-like macro, use the right parenthesis
875 // location.
876 if (AfterLoc.isMacroID()) {
877 FileID FID = SM.getFileID(AfterLoc);
878 const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
879 if (EI->isFunctionMacroExpansion())
880 AfterLoc = EI->getExpansionLocEnd();
881 }
882
883 size_t StartDepth = locationDepth(AfterLoc);
884 size_t EndDepth = locationDepth(BeforeLoc);
885 while (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc)) {
886 bool UnnestStart = StartDepth >= EndDepth;
887 bool UnnestEnd = EndDepth >= StartDepth;
888 if (UnnestEnd) {
889 assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),(static_cast <bool> (SM.isWrittenInSameFile(getStartOfFileOrMacro
(BeforeLoc), BeforeLoc)) ? void (0) : __assert_fail ("SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc), BeforeLoc)"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 890, __extension__
__PRETTY_FUNCTION__))
890 BeforeLoc))(static_cast <bool> (SM.isWrittenInSameFile(getStartOfFileOrMacro
(BeforeLoc), BeforeLoc)) ? void (0) : __assert_fail ("SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc), BeforeLoc)"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 890, __extension__
__PRETTY_FUNCTION__))
;
891
892 BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
893 assert(BeforeLoc.isValid())(static_cast <bool> (BeforeLoc.isValid()) ? void (0) : __assert_fail
("BeforeLoc.isValid()", "clang/lib/CodeGen/CoverageMappingGen.cpp"
, 893, __extension__ __PRETTY_FUNCTION__))
;
894 EndDepth--;
895 }
896 if (UnnestStart) {
897 assert(SM.isWrittenInSameFile(AfterLoc,(static_cast <bool> (SM.isWrittenInSameFile(AfterLoc, getEndOfFileOrMacro
(AfterLoc))) ? void (0) : __assert_fail ("SM.isWrittenInSameFile(AfterLoc, getEndOfFileOrMacro(AfterLoc))"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 898, __extension__
__PRETTY_FUNCTION__))
898 getEndOfFileOrMacro(AfterLoc)))(static_cast <bool> (SM.isWrittenInSameFile(AfterLoc, getEndOfFileOrMacro
(AfterLoc))) ? void (0) : __assert_fail ("SM.isWrittenInSameFile(AfterLoc, getEndOfFileOrMacro(AfterLoc))"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 898, __extension__
__PRETTY_FUNCTION__))
;
899
900 AfterLoc = getIncludeOrExpansionLoc(AfterLoc);
901 assert(AfterLoc.isValid())(static_cast <bool> (AfterLoc.isValid()) ? void (0) : __assert_fail
("AfterLoc.isValid()", "clang/lib/CodeGen/CoverageMappingGen.cpp"
, 901, __extension__ __PRETTY_FUNCTION__))
;
902 AfterLoc = getPreciseTokenLocEnd(AfterLoc);
903 assert(AfterLoc.isValid())(static_cast <bool> (AfterLoc.isValid()) ? void (0) : __assert_fail
("AfterLoc.isValid()", "clang/lib/CodeGen/CoverageMappingGen.cpp"
, 903, __extension__ __PRETTY_FUNCTION__))
;
904 StartDepth--;
905 }
906 }
907 AfterLoc = getPreciseTokenLocEnd(AfterLoc);
908 // If the start and end locations of the gap are both within the same macro
909 // file, the range may not be in source order.
910 if (AfterLoc.isMacroID() || BeforeLoc.isMacroID())
911 return None;
912 if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc) ||
913 !SpellingRegion(SM, AfterLoc, BeforeLoc).isInSourceOrder())
914 return None;
915 return {{AfterLoc, BeforeLoc}};
916 }
917
918 /// Emit a gap region between \p StartLoc and \p EndLoc with the given count.
919 void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc,
920 Counter Count) {
921 if (StartLoc == EndLoc)
922 return;
923 assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder())(static_cast <bool> (SpellingRegion(SM, StartLoc, EndLoc
).isInSourceOrder()) ? void (0) : __assert_fail ("SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder()"
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 923, __extension__
__PRETTY_FUNCTION__))
;
924 handleFileExit(StartLoc);
925 size_t Index = pushRegion(Count, StartLoc, EndLoc);
926 getRegion().setGap(true);
927 handleFileExit(EndLoc);
928 popRegions(Index);
929 }
930
931 /// Keep counts of breaks and continues inside loops.
932 struct BreakContinue {
933 Counter BreakCount;
934 Counter ContinueCount;
935 };
936 SmallVector<BreakContinue, 8> BreakContinueStack;
937
938 CounterCoverageMappingBuilder(
939 CoverageMappingModuleGen &CVM,
940 llvm::DenseMap<const Stmt *, unsigned> &CounterMap, SourceManager &SM,
941 const LangOptions &LangOpts)
942 : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap) {}
943
944 /// Write the mapping data to the output stream
945 void write(llvm::raw_ostream &OS) {
946 llvm::SmallVector<unsigned, 8> VirtualFileMapping;
947 gatherFileIDs(VirtualFileMapping);
948 SourceRegionFilter Filter = emitExpansionRegions();
949 emitSourceRegions(Filter);
950 gatherSkippedRegions();
951
952 if (MappingRegions.empty())
953 return;
954
955 CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
956 MappingRegions);
957 Writer.write(OS);
958 }
959
960 void VisitStmt(const Stmt *S) {
961 if (S->getBeginLoc().isValid())
962 extendRegion(S);
963 const Stmt *LastStmt = nullptr;
964 bool SaveTerminateStmt = HasTerminateStmt;
965 HasTerminateStmt = false;
966 GapRegionCounter = Counter::getZero();
967 for (const Stmt *Child : S->children())
968 if (Child) {
969 // If last statement contains terminate statements, add a gap area
970 // between the two statements. Skipping attributed statements, because
971 // they don't have valid start location.
972 if (LastStmt && HasTerminateStmt && !isa<AttributedStmt>(Child)) {
973 auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
974 if (Gap)
975 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
976 GapRegionCounter);
977 SaveTerminateStmt = true;
978 HasTerminateStmt = false;
979 }
980 this->Visit(Child);
981 LastStmt = Child;
982 }
983 if (SaveTerminateStmt)
984 HasTerminateStmt = true;
985 handleFileExit(getEnd(S));
986 }
987
988 void VisitDecl(const Decl *D) {
989 Stmt *Body = D->getBody();
4
'Body' initialized here
990
991 // Do not propagate region counts into system headers.
992 if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
5
Assuming 'Body' is null
6
Taking false branch
993 return;
994
995 // Do not visit the artificial children nodes of defaulted methods. The
996 // lexer may not be able to report back precise token end locations for
997 // these children nodes (llvm.org/PR39822), and moreover users will not be
998 // able to see coverage for them.
999 bool Defaulted = false;
1000 if (auto *Method
7.1
'Method' is null
= dyn_cast<CXXMethodDecl>(D))
7
Assuming 'D' is not a 'CXXMethodDecl'
8
Taking false branch
1001 Defaulted = Method->isDefaulted();
1002
1003 propagateCounts(getRegionCounter(Body), Body,
9
Passing null pointer value via 2nd parameter 'S'
10
Calling 'CounterCoverageMappingBuilder::propagateCounts'
1004 /*VisitChildren=*/!Defaulted);
1005 assert(RegionStack.empty() && "Regions entered but never exited")(static_cast <bool> (RegionStack.empty() && "Regions entered but never exited"
) ? void (0) : __assert_fail ("RegionStack.empty() && \"Regions entered but never exited\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 1005, __extension__
__PRETTY_FUNCTION__))
;
1006 }
1007
1008 void VisitReturnStmt(const ReturnStmt *S) {
1009 extendRegion(S);
1010 if (S->getRetValue())
1011 Visit(S->getRetValue());
1012 terminateRegion(S);
1013 }
1014
1015 void VisitCoroutineBodyStmt(const CoroutineBodyStmt *S) {
1016 extendRegion(S);
1017 Visit(S->getBody());
1018 }
1019
1020 void VisitCoreturnStmt(const CoreturnStmt *S) {
1021 extendRegion(S);
1022 if (S->getOperand())
1023 Visit(S->getOperand());
1024 terminateRegion(S);
1025 }
1026
1027 void VisitCXXThrowExpr(const CXXThrowExpr *E) {
1028 extendRegion(E);
1029 if (E->getSubExpr())
1030 Visit(E->getSubExpr());
1031 terminateRegion(E);
1032 }
1033
1034 void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); }
1035
1036 void VisitLabelStmt(const LabelStmt *S) {
1037 Counter LabelCount = getRegionCounter(S);
1038 SourceLocation Start = getStart(S);
1039 // We can't extendRegion here or we risk overlapping with our new region.
1040 handleFileExit(Start);
1041 pushRegion(LabelCount, Start);
1042 Visit(S->getSubStmt());
1043 }
1044
1045 void VisitBreakStmt(const BreakStmt *S) {
1046 assert(!BreakContinueStack.empty() && "break not in a loop or switch!")(static_cast <bool> (!BreakContinueStack.empty() &&
"break not in a loop or switch!") ? void (0) : __assert_fail
("!BreakContinueStack.empty() && \"break not in a loop or switch!\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 1046, __extension__
__PRETTY_FUNCTION__))
;
1047 BreakContinueStack.back().BreakCount = addCounters(
1048 BreakContinueStack.back().BreakCount, getRegion().getCounter());
1049 // FIXME: a break in a switch should terminate regions for all preceding
1050 // case statements, not just the most recent one.
1051 terminateRegion(S);
1052 }
1053
1054 void VisitContinueStmt(const ContinueStmt *S) {
1055 assert(!BreakContinueStack.empty() && "continue stmt not in a loop!")(static_cast <bool> (!BreakContinueStack.empty() &&
"continue stmt not in a loop!") ? void (0) : __assert_fail (
"!BreakContinueStack.empty() && \"continue stmt not in a loop!\""
, "clang/lib/CodeGen/CoverageMappingGen.cpp", 1055, __extension__
__PRETTY_FUNCTION__))
;
1056 BreakContinueStack.back().ContinueCount = addCounters(
1057 BreakContinueStack.back().ContinueCount, getRegion().getCounter());
1058 terminateRegion(S);
1059 }
1060
1061 void VisitCallExpr(const CallExpr *E) {
1062 VisitStmt(E);
1063
1064 // Terminate the region when we hit a noreturn function.
1065 // (This is helpful dealing with switch statements.)
1066 QualType CalleeType = E->getCallee()->getType();
1067 if (getFunctionExtInfo(*CalleeType).getNoReturn())
1068 terminateRegion(E);
1069 }
1070
1071 void VisitWhileStmt(const WhileStmt *S) {
1072 extendRegion(S);
1073
1074 Counter ParentCount = getRegion().getCounter();
1075 Counter BodyCount = getRegionCounter(S);
1076
1077 // Handle the body first so that we can get the backedge count.
1078 BreakContinueStack.push_back(BreakContinue());
1079 extendRegion(S->getBody());
1080 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1081 BreakContinue BC = BreakContinueStack.pop_back_val();
1082
1083 bool BodyHasTerminateStmt = HasTerminateStmt;
1084 HasTerminateStmt = false;
1085
1086 // Go back to handle the condition.
1087 Counter CondCount =
1088 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1089 propagateCounts(CondCount, S->getCond());
1090 adjustForOutOfOrderTraversal(getEnd(S));
1091
1092 // The body count applies to the area immediately after the increment.
1093 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1094 if (Gap)
1095 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1096
1097 Counter OutCount =
1098 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
1099 if (OutCount != ParentCount) {
1100 pushRegion(OutCount);
1101 GapRegionCounter = OutCount;
1102 if (BodyHasTerminateStmt)
1103 HasTerminateStmt = true;
1104 }
1105
1106 // Create Branch Region around condition.
1107 createBranchRegion(S->getCond(), BodyCount,
1108 subtractCounters(CondCount, BodyCount));
1109 }
1110
1111 void VisitDoStmt(const DoStmt *S) {
1112 extendRegion(S);
1113
1114 Counter ParentCount = getRegion().getCounter();
1115 Counter BodyCount = getRegionCounter(S);
1116
1117 BreakContinueStack.push_back(BreakContinue());
1118 extendRegion(S->getBody());
1119 Counter BackedgeCount =
1120 propagateCounts(addCounters(ParentCount, BodyCount), S->getBody());
1121 BreakContinue BC = BreakContinueStack.pop_back_val();
1122
1123 bool BodyHasTerminateStmt = HasTerminateStmt;
1124 HasTerminateStmt = false;
1125
1126 Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
1127 propagateCounts(CondCount, S->getCond());
1128
1129 Counter OutCount =
1130 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
1131 if (OutCount != ParentCount) {
1132 pushRegion(OutCount);
1133 GapRegionCounter = OutCount;
1134 }
1135
1136 // Create Branch Region around condition.
1137 createBranchRegion(S->getCond(), BodyCount,
1138 subtractCounters(CondCount, BodyCount));
1139
1140 if (BodyHasTerminateStmt)
1141 HasTerminateStmt = true;
1142 }
1143
1144 void VisitForStmt(const ForStmt *S) {
1145 extendRegion(S);
1146 if (S->getInit())
1147 Visit(S->getInit());
1148
1149 Counter ParentCount = getRegion().getCounter();
1150 Counter BodyCount = getRegionCounter(S);
1151
1152 // The loop increment may contain a break or continue.
1153 if (S->getInc())
1154 BreakContinueStack.emplace_back();
1155
1156 // Handle the body first so that we can get the backedge count.
1157 BreakContinueStack.emplace_back();
1158 extendRegion(S->getBody());
1159 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1160 BreakContinue BodyBC = BreakContinueStack.pop_back_val();
1161
1162 bool BodyHasTerminateStmt = HasTerminateStmt;
1163 HasTerminateStmt = false;
1164
1165 // The increment is essentially part of the body but it needs to include
1166 // the count for all the continue statements.
1167 BreakContinue IncrementBC;
1168 if (const Stmt *Inc = S->getInc()) {
1169 propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc);
1170 IncrementBC = BreakContinueStack.pop_back_val();
1171 }
1172
1173 // Go back to handle the condition.
1174 Counter CondCount = addCounters(
1175 addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
1176 IncrementBC.ContinueCount);
1177 if (const Expr *Cond = S->getCond()) {
1178 propagateCounts(CondCount, Cond);
1179 adjustForOutOfOrderTraversal(getEnd(S));
1180 }
1181
1182 // The body count applies to the area immediately after the increment.
1183 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1184 if (Gap)
1185 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1186
1187 Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
1188 subtractCounters(CondCount, BodyCount));
1189 if (OutCount != ParentCount) {
1190 pushRegion(OutCount);
1191 GapRegionCounter = OutCount;
1192 if (BodyHasTerminateStmt)
1193 HasTerminateStmt = true;
1194 }
1195
1196 // Create Branch Region around condition.
1197 createBranchRegion(S->getCond(), BodyCount,
1198 subtractCounters(CondCount, BodyCount));
1199 }
1200
1201 void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
1202 extendRegion(S);
1203 if (S->getInit())
1204 Visit(S->getInit());
1205 Visit(S->getLoopVarStmt());
1206 Visit(S->getRangeStmt());
1207
1208 Counter ParentCount = getRegion().getCounter();
1209 Counter BodyCount = getRegionCounter(S);
1210
1211 BreakContinueStack.push_back(BreakContinue());
1212 extendRegion(S->getBody());
1213 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1214 BreakContinue BC = BreakContinueStack.pop_back_val();
1215
1216 bool BodyHasTerminateStmt = HasTerminateStmt;
1217 HasTerminateStmt = false;
1218
1219 // The body count applies to the area immediately after the range.
1220 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1221 if (Gap)
1222 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1223
1224 Counter LoopCount =
1225 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1226 Counter OutCount =
1227 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1228 if (OutCount != ParentCount) {
1229 pushRegion(OutCount);
1230 GapRegionCounter = OutCount;
1231 if (BodyHasTerminateStmt)
1232 HasTerminateStmt = true;
1233 }
1234
1235 // Create Branch Region around condition.
1236 createBranchRegion(S->getCond(), BodyCount,
1237 subtractCounters(LoopCount, BodyCount));
1238 }
1239
1240 void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
1241 extendRegion(S);
1242 Visit(S->getElement());
1243
1244 Counter ParentCount = getRegion().getCounter();
1245 Counter BodyCount = getRegionCounter(S);
1246
1247 BreakContinueStack.push_back(BreakContinue());
1248 extendRegion(S->getBody());
1249 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1250 BreakContinue BC = BreakContinueStack.pop_back_val();
1251
1252 // The body count applies to the area immediately after the collection.
1253 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1254 if (Gap)
1255 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1256
1257 Counter LoopCount =
1258 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1259 Counter OutCount =
1260 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1261 if (OutCount != ParentCount) {
1262 pushRegion(OutCount);
1263 GapRegionCounter = OutCount;
1264 }
1265 }
1266
1267 void VisitSwitchStmt(const SwitchStmt *S) {
1268 extendRegion(S);
1269 if (S->getInit())
1270 Visit(S->getInit());
1271 Visit(S->getCond());
1272
1273 BreakContinueStack.push_back(BreakContinue());
1274
1275 const Stmt *Body = S->getBody();
1276 extendRegion(Body);
1277 if (const auto *CS = dyn_cast<CompoundStmt>(Body)) {
1278 if (!CS->body_empty()) {
1279 // Make a region for the body of the switch. If the body starts with
1280 // a case, that case will reuse this region; otherwise, this covers
1281 // the unreachable code at the beginning of the switch body.
1282 size_t Index = pushRegion(Counter::getZero(), getStart(CS));
1283 getRegion().setGap(true);
1284 Visit(Body);
1285
1286 // Set the end for the body of the switch, if it isn't already set.
1287 for (size_t i = RegionStack.size(); i != Index; --i) {
1288 if (!RegionStack[i - 1].hasEndLoc())
1289 RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
1290 }
1291
1292 popRegions(Index);
1293 }
1294 } else
1295 propagateCounts(Counter::getZero(), Body);
1296 BreakContinue BC = BreakContinueStack.pop_back_val();
1297
1298 if (!BreakContinueStack.empty())
1299 BreakContinueStack.back().ContinueCount = addCounters(
1300 BreakContinueStack.back().ContinueCount, BC.ContinueCount);
1301
1302 Counter ParentCount = getRegion().getCounter();
1303 Counter ExitCount = getRegionCounter(S);
1304 SourceLocation ExitLoc = getEnd(S);
1305 pushRegion(ExitCount);
1306 GapRegionCounter = ExitCount;
1307
1308 // Ensure that handleFileExit recognizes when the end location is located
1309 // in a different file.
1310 MostRecentLocation = getStart(S);
1311 handleFileExit(ExitLoc);
1312
1313 // Create a Branch Region around each Case. Subtract the case's
1314 // counter from the Parent counter to track the "False" branch count.
1315 Counter CaseCountSum;
1316 bool HasDefaultCase = false;
1317 const SwitchCase *Case = S->getSwitchCaseList();
1318 for (; Case; Case = Case->getNextSwitchCase()) {
1319 HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
1320 CaseCountSum = addCounters(CaseCountSum, getRegionCounter(Case));
1321 createSwitchCaseRegion(
1322 Case, getRegionCounter(Case),
1323 subtractCounters(ParentCount, getRegionCounter(Case)));
1324 }
1325
1326 // If no explicit default case exists, create a branch region to represent
1327 // the hidden branch, which will be added later by the CodeGen. This region
1328 // will be associated with the switch statement's condition.
1329 if (!HasDefaultCase) {
1330 Counter DefaultTrue = subtractCounters(ParentCount, CaseCountSum);
1331 Counter DefaultFalse = subtractCounters(ParentCount, DefaultTrue);
1332 createBranchRegion(S->getCond(), DefaultTrue, DefaultFalse);
1333 }
1334 }
1335
1336 void VisitSwitchCase(const SwitchCase *S) {
1337 extendRegion(S);
1338
1339 SourceMappingRegion &Parent = getRegion();
1340
1341 Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
1342 // Reuse the existing region if it starts at our label. This is typical of
1343 // the first case in a switch.
1344 if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S))
1345 Parent.setCounter(Count);
1346 else
1347 pushRegion(Count, getStart(S));
1348
1349 GapRegionCounter = Count;
1350
1351 if (const auto *CS = dyn_cast<CaseStmt>(S)) {
1352 Visit(CS->getLHS());
1353 if (const Expr *RHS = CS->getRHS())
1354 Visit(RHS);
1355 }
1356 Visit(S->getSubStmt());
1357 }
1358
1359 void VisitIfStmt(const IfStmt *S) {
1360 extendRegion(S);
1361 if (S->getInit())
1362 Visit(S->getInit());
1363
1364 // Extend into the condition before we propagate through it below - this is
1365 // needed to handle macros that generate the "if" but not the condition.
1366 extendRegion(S->getCond());
1367
1368 Counter ParentCount = getRegion().getCounter();
1369 Counter ThenCount = getRegionCounter(S);
1370
1371 // Emitting a counter for the condition makes it easier to interpret the
1372 // counter for the body when looking at the coverage.
1373 propagateCounts(ParentCount, S->getCond());
1374
1375 // The 'then' count applies to the area immediately after the condition.
1376 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
1377 if (Gap)
1378 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
1379
1380 extendRegion(S->getThen());
1381 Counter OutCount = propagateCounts(ThenCount, S->getThen());
1382
1383 Counter ElseCount = subtractCounters(ParentCount, ThenCount);
1384 if (const Stmt *Else = S->getElse()) {
1385 bool ThenHasTerminateStmt = HasTerminateStmt;
1386 HasTerminateStmt = false;
1387
1388 // The 'else' count applies to the area immediately after the 'then'.
1389 Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
1390 if (Gap)
1391 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
1392 extendRegion(Else);
1393 OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
1394
1395 if (ThenHasTerminateStmt)
1396 HasTerminateStmt = true;
1397 } else
1398 OutCount = addCounters(OutCount, ElseCount);
1399
1400 if (OutCount != ParentCount) {
1401 pushRegion(OutCount);
1402 GapRegionCounter = OutCount;
1403 }
1404
1405 // Create Branch Region around condition.
1406 createBranchRegion(S->getCond(), ThenCount,
1407 subtractCounters(ParentCount, ThenCount));
1408 }
1409
1410 void VisitCXXTryStmt(const CXXTryStmt *S) {
1411 extendRegion(S);
1412 // Handle macros that generate the "try" but not the rest.
1413 extendRegion(S->getTryBlock());
1414
1415 Counter ParentCount = getRegion().getCounter();
1416 propagateCounts(ParentCount, S->getTryBlock());
1417
1418 for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
1419 Visit(S->getHandler(I));
1420
1421 Counter ExitCount = getRegionCounter(S);
1422 pushRegion(ExitCount);
1423 }
1424
1425 void VisitCXXCatchStmt(const CXXCatchStmt *S) {
1426 propagateCounts(getRegionCounter(S), S->getHandlerBlock());
1427 }
1428
1429 void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
1430 extendRegion(E);
1431
1432 Counter ParentCount = getRegion().getCounter();
1433 Counter TrueCount = getRegionCounter(E);
1434
1435 propagateCounts(ParentCount, E->getCond());
1436
1437 if (!isa<BinaryConditionalOperator>(E)) {
1438 // The 'then' count applies to the area immediately after the condition.
1439 auto Gap =
1440 findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr()));
1441 if (Gap)
1442 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
1443
1444 extendRegion(E->getTrueExpr());
1445 propagateCounts(TrueCount, E->getTrueExpr());
1446 }
1447
1448 extendRegion(E->getFalseExpr());
1449 propagateCounts(subtractCounters(ParentCount, TrueCount),
1450 E->getFalseExpr());
1451
1452 // Create Branch Region around condition.
1453 createBranchRegion(E->getCond(), TrueCount,
1454 subtractCounters(ParentCount, TrueCount));
1455 }
1456
1457 void VisitBinLAnd(const BinaryOperator *E) {
1458 extendRegion(E->getLHS());
1459 propagateCounts(getRegion().getCounter(), E->getLHS());
1460 handleFileExit(getEnd(E->getLHS()));
1461
1462 // Counter tracks the right hand side of a logical and operator.
1463 extendRegion(E->getRHS());
1464 propagateCounts(getRegionCounter(E), E->getRHS());
1465
1466 // Extract the RHS's Execution Counter.
1467 Counter RHSExecCnt = getRegionCounter(E);
1468
1469 // Extract the RHS's "True" Instance Counter.
1470 Counter RHSTrueCnt = getRegionCounter(E->getRHS());
1471
1472 // Extract the Parent Region Counter.
1473 Counter ParentCnt = getRegion().getCounter();
1474
1475 // Create Branch Region around LHS condition.
1476 createBranchRegion(E->getLHS(), RHSExecCnt,
1477 subtractCounters(ParentCnt, RHSExecCnt));
1478
1479 // Create Branch Region around RHS condition.
1480 createBranchRegion(E->getRHS(), RHSTrueCnt,
1481 subtractCounters(RHSExecCnt, RHSTrueCnt));
1482 }
1483
1484 void VisitBinLOr(const BinaryOperator *E) {
1485 extendRegion(E->getLHS());
1486 propagateCounts(getRegion().getCounter(), E->getLHS());
1487 handleFileExit(getEnd(E->getLHS()));
1488
1489 // Counter tracks the right hand side of a logical or operator.
1490 extendRegion(E->getRHS());
1491 propagateCounts(getRegionCounter(E), E->getRHS());
1492
1493 // Extract the RHS's Execution Counter.
1494 Counter RHSExecCnt = getRegionCounter(E);
1495
1496 // Extract the RHS's "False" Instance Counter.
1497 Counter RHSFalseCnt = getRegionCounter(E->getRHS());
1498
1499 // Extract the Parent Region Counter.
1500 Counter ParentCnt = getRegion().getCounter();
1501
1502 // Create Branch Region around LHS condition.
1503 createBranchRegion(E->getLHS(), subtractCounters(ParentCnt, RHSExecCnt),
1504 RHSExecCnt);
1505
1506 // Create Branch Region around RHS condition.
1507 createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
1508 RHSFalseCnt);
1509 }
1510
1511 void VisitLambdaExpr(const LambdaExpr *LE) {
1512 // Lambdas are treated as their own functions for now, so we shouldn't
1513 // propagate counts into them.
1514 }
1515};
1516
1517} // end anonymous namespace
1518
1519static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
1520 ArrayRef<CounterExpression> Expressions,
1521 ArrayRef<CounterMappingRegion> Regions) {
1522 OS << FunctionName << ":\n";
1523 CounterMappingContext Ctx(Expressions);
1524 for (const auto &R : Regions) {
1525 OS.indent(2);
1526 switch (R.Kind) {
1527 case CounterMappingRegion::CodeRegion:
1528 break;
1529 case CounterMappingRegion::ExpansionRegion:
1530 OS << "Expansion,";
1531 break;
1532 case CounterMappingRegion::SkippedRegion:
1533 OS << "Skipped,";
1534 break;
1535 case CounterMappingRegion::GapRegion:
1536 OS << "Gap,";
1537 break;
1538 case CounterMappingRegion::BranchRegion:
1539 OS << "Branch,";
1540 break;
1541 }
1542
1543 OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart
1544 << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = ";
1545 Ctx.dump(R.Count, OS);
1546
1547 if (R.Kind == CounterMappingRegion::BranchRegion) {
1548 OS << ", ";
1549 Ctx.dump(R.FalseCount, OS);
1550 }
1551
1552 if (R.Kind == CounterMappingRegion::ExpansionRegion)
1553 OS << " (Expanded file = " << R.ExpandedFileID << ")";
1554 OS << "\n";
1555 }
1556}
1557
1558CoverageMappingModuleGen::CoverageMappingModuleGen(
1559 CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
1560 : CGM(CGM), SourceInfo(SourceInfo) {
1561 CoveragePrefixMap = CGM.getCodeGenOpts().CoveragePrefixMap;
1562}
1563
1564std::string CoverageMappingModuleGen::getCurrentDirname() {
1565 if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty())
1566 return CGM.getCodeGenOpts().CoverageCompilationDir;
1567
1568 SmallString<256> CWD;
1569 llvm::sys::fs::current_path(CWD);
1570 return CWD.str().str();
1571}
1572
1573std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) {
1574 llvm::SmallString<256> Path(Filename);
1575 llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
1576 for (const auto &Entry : CoveragePrefixMap) {
1577 if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
1578 break;
1579 }
1580 return Path.str().str();
1581}
1582
1583static std::string getInstrProfSection(const CodeGenModule &CGM,
1584 llvm::InstrProfSectKind SK) {
1585 return llvm::getInstrProfSectionName(
1586 SK, CGM.getContext().getTargetInfo().getTriple().getObjectFormat());
1587}
1588
1589void CoverageMappingModuleGen::emitFunctionMappingRecord(
1590 const FunctionInfo &Info, uint64_t FilenamesRef) {
1591 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1592
1593 // Assign a name to the function record. This is used to merge duplicates.
1594 std::string FuncRecordName = "__covrec_" + llvm::utohexstr(Info.NameHash);
1595
1596 // A dummy description for a function included-but-not-used in a TU can be
1597 // replaced by full description provided by a different TU. The two kinds of
1598 // descriptions play distinct roles: therefore, assign them different names
1599 // to prevent `linkonce_odr` merging.
1600 if (Info.IsUsed)
1601 FuncRecordName += "u";
1602
1603 // Create the function record type.
1604 const uint64_t NameHash = Info.NameHash;
1605 const uint64_t FuncHash = Info.FuncHash;
1606 const std::string &CoverageMapping = Info.CoverageMapping;
1607#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
1608 llvm::Type *FunctionRecordTypes[] = {
1609#include "llvm/ProfileData/InstrProfData.inc"
1610 };
1611 auto *FunctionRecordTy =
1612 llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes),
1613 /*isPacked=*/true);
1614
1615 // Create the function record constant.
1616#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init,
1617 llvm::Constant *FunctionRecordVals[] = {
1618 #include "llvm/ProfileData/InstrProfData.inc"
1619 };
1620 auto *FuncRecordConstant = llvm::ConstantStruct::get(
1621 FunctionRecordTy, makeArrayRef(FunctionRecordVals));
1622
1623 // Create the function record global.
1624 auto *FuncRecord = new llvm::GlobalVariable(
1625 CGM.getModule(), FunctionRecordTy, /*isConstant=*/true,
1626 llvm::GlobalValue::LinkOnceODRLinkage, FuncRecordConstant,
1627 FuncRecordName);
1628 FuncRecord->setVisibility(llvm::GlobalValue::HiddenVisibility);
1629 FuncRecord->setSection(getInstrProfSection(CGM, llvm::IPSK_covfun));
1630 FuncRecord->setAlignment(llvm::Align(8));
1631 if (CGM.supportsCOMDAT())
1632 FuncRecord->setComdat(CGM.getModule().getOrInsertComdat(FuncRecordName));
1633
1634 // Make sure the data doesn't get deleted.
1635 CGM.addUsedGlobal(FuncRecord);
1636}
1637
1638void CoverageMappingModuleGen::addFunctionMappingRecord(
1639 llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
1640 const std::string &CoverageMapping, bool IsUsed) {
1641 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1642 const uint64_t NameHash = llvm::IndexedInstrProf::ComputeHash(NameValue);
1643 FunctionRecords.push_back({NameHash, FuncHash, CoverageMapping, IsUsed});
1644
1645 if (!IsUsed)
1646 FunctionNames.push_back(
1647 llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
1648
1649 if (CGM.getCodeGenOpts().DumpCoverageMapping) {
1650 // Dump the coverage mapping data for this function by decoding the
1651 // encoded data. This allows us to dump the mapping regions which were
1652 // also processed by the CoverageMappingWriter which performs
1653 // additional minimization operations such as reducing the number of
1654 // expressions.
1655 llvm::SmallVector<std::string, 16> FilenameStrs;
1656 std::vector<StringRef> Filenames;
1657 std::vector<CounterExpression> Expressions;
1658 std::vector<CounterMappingRegion> Regions;
1659 FilenameStrs.resize(FileEntries.size() + 1);
1660 FilenameStrs[0] = normalizeFilename(getCurrentDirname());
1661 for (const auto &Entry : FileEntries) {
1662 auto I = Entry.second;
1663 FilenameStrs[I] = normalizeFilename(Entry.first->getName());
1664 }
1665 ArrayRef<std::string> FilenameRefs = llvm::makeArrayRef(FilenameStrs);
1666 RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
1667 Expressions, Regions);
1668 if (Reader.read())
1669 return;
1670 dump(llvm::outs(), NameValue, Expressions, Regions);
1671 }
1672}
1673
1674void CoverageMappingModuleGen::emit() {
1675 if (FunctionRecords.empty())
1676 return;
1677 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1678 auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
1679
1680 // Create the filenames and merge them with coverage mappings
1681 llvm::SmallVector<std::string, 16> FilenameStrs;
1682 FilenameStrs.resize(FileEntries.size() + 1);
1683 // The first filename is the current working directory.
1684 FilenameStrs[0] = normalizeFilename(getCurrentDirname());
1685 for (const auto &Entry : FileEntries) {
1686 auto I = Entry.second;
1687 FilenameStrs[I] = normalizeFilename(Entry.first->getName());
1688 }
1689
1690 std::string Filenames;
1691 {
1692 llvm::raw_string_ostream OS(Filenames);
1693 CoverageFilenamesSectionWriter(FilenameStrs).write(OS);
1694 }
1695 auto *FilenamesVal =
1696 llvm::ConstantDataArray::getString(Ctx, Filenames, false);
1697 const int64_t FilenamesRef = llvm::IndexedInstrProf::ComputeHash(Filenames);
1698
1699 // Emit the function records.
1700 for (const FunctionInfo &Info : FunctionRecords)
1701 emitFunctionMappingRecord(Info, FilenamesRef);
1702
1703 const unsigned NRecords = 0;
1704 const size_t FilenamesSize = Filenames.size();
1705 const unsigned CoverageMappingSize = 0;
1706 llvm::Type *CovDataHeaderTypes[] = {
1707#define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType,
1708#include "llvm/ProfileData/InstrProfData.inc"
1709 };
1710 auto CovDataHeaderTy =
1711 llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
1712 llvm::Constant *CovDataHeaderVals[] = {
1713#define COVMAP_HEADER(Type, LLVMType, Name, Init) Init,
1714#include "llvm/ProfileData/InstrProfData.inc"
1715 };
1716 auto CovDataHeaderVal = llvm::ConstantStruct::get(
1717 CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));
1718
1719 // Create the coverage data record
1720 llvm::Type *CovDataTypes[] = {CovDataHeaderTy, FilenamesVal->getType()};
1721 auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
1722 llvm::Constant *TUDataVals[] = {CovDataHeaderVal, FilenamesVal};
1723 auto CovDataVal =
1724 llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
1725 auto CovData = new llvm::GlobalVariable(
1726 CGM.getModule(), CovDataTy, true, llvm::GlobalValue::PrivateLinkage,
1727 CovDataVal, llvm::getCoverageMappingVarName());
1728
1729 CovData->setSection(getInstrProfSection(CGM, llvm::IPSK_covmap));
1730 CovData->setAlignment(llvm::Align(8));
1731
1732 // Make sure the data doesn't get deleted.
1733 CGM.addUsedGlobal(CovData);
1734 // Create the deferred function records array
1735 if (!FunctionNames.empty()) {
1736 auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx),
1737 FunctionNames.size());
1738 auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
1739 // This variable will *NOT* be emitted to the object file. It is used
1740 // to pass the list of names referenced to codegen.
1741 new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true,
1742 llvm::GlobalValue::InternalLinkage, NamesArrVal,
1743 llvm::getCoverageUnusedNamesVarName());
1744 }
1745}
1746
1747unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {
1748 auto It = FileEntries.find(File);
1749 if (It != FileEntries.end())
1750 return It->second;
1751 unsigned FileID = FileEntries.size() + 1;
1752 FileEntries.insert(std::make_pair(File, FileID));
1753 return FileID;
1754}
1755
1756void CoverageMappingGen::emitCounterMapping(const Decl *D,
1757 llvm::raw_ostream &OS) {
1758 assert(CounterMap)(static_cast <bool> (CounterMap) ? void (0) : __assert_fail
("CounterMap", "clang/lib/CodeGen/CoverageMappingGen.cpp", 1758
, __extension__ __PRETTY_FUNCTION__))
;
1
Assuming field 'CounterMap' is non-null
2
'?' condition is true
1759 CounterCoverageMappingBuilder Walker(CVM, *CounterMap, SM, LangOpts);
1760 Walker.VisitDecl(D);
3
Calling 'CounterCoverageMappingBuilder::VisitDecl'
1761 Walker.write(OS);
1762}
1763
1764void CoverageMappingGen::emitEmptyMapping(const Decl *D,
1765 llvm::raw_ostream &OS) {
1766 EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
1767 Walker.VisitDecl(D);
1768 Walker.write(OS);
1769}