Bug Summary

File:clang/lib/CodeGen/CoverageMappingGen.cpp
Warning:line 271, column 26
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

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