Bug Summary

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