Bug Summary

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