Bug Summary

File:clang/lib/Basic/Diagnostic.cpp
Warning:line 824, column 9
Array access (from variable 'DiagStr') results in a null pointer dereference

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 Diagnostic.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~++20210903100615+fd66b44ec19e/build-llvm/tools/clang/lib/Basic -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/tools/clang/lib/Basic -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/clang/lib/Basic -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/clang/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include -D 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~++20210903100615+fd66b44ec19e/build-llvm/tools/clang/lib/Basic -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e=. -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-09-04-040900-46481-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/clang/lib/Basic/Diagnostic.cpp

/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/clang/lib/Basic/Diagnostic.cpp

1//===- Diagnostic.cpp - C Language Family Diagnostic Handling -------------===//
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// This file implements the Diagnostic-related interfaces.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Basic/Diagnostic.h"
14#include "clang/Basic/CharInfo.h"
15#include "clang/Basic/DiagnosticError.h"
16#include "clang/Basic/DiagnosticIDs.h"
17#include "clang/Basic/DiagnosticOptions.h"
18#include "clang/Basic/IdentifierTable.h"
19#include "clang/Basic/PartialDiagnostic.h"
20#include "clang/Basic/SourceLocation.h"
21#include "clang/Basic/SourceManager.h"
22#include "clang/Basic/Specifiers.h"
23#include "clang/Basic/TokenKinds.h"
24#include "llvm/ADT/SmallString.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/ADT/StringExtras.h"
27#include "llvm/ADT/StringRef.h"
28#include "llvm/Support/CrashRecoveryContext.h"
29#include "llvm/Support/Locale.h"
30#include "llvm/Support/raw_ostream.h"
31#include <algorithm>
32#include <cassert>
33#include <cstddef>
34#include <cstdint>
35#include <cstring>
36#include <limits>
37#include <string>
38#include <utility>
39#include <vector>
40
41using namespace clang;
42
43const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
44 DiagNullabilityKind nullability) {
45 StringRef string;
46 switch (nullability.first) {
47 case NullabilityKind::NonNull:
48 string = nullability.second ? "'nonnull'" : "'_Nonnull'";
49 break;
50
51 case NullabilityKind::Nullable:
52 string = nullability.second ? "'nullable'" : "'_Nullable'";
53 break;
54
55 case NullabilityKind::Unspecified:
56 string = nullability.second ? "'null_unspecified'" : "'_Null_unspecified'";
57 break;
58
59 case NullabilityKind::NullableResult:
60 assert(!nullability.second &&(static_cast<void> (0))
61 "_Nullable_result isn't supported as context-sensitive keyword")(static_cast<void> (0));
62 string = "_Nullable_result";
63 break;
64 }
65
66 DB.AddString(string);
67 return DB;
68}
69
70const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
71 llvm::Error &&E) {
72 DB.AddString(toString(std::move(E)));
73 return DB;
74}
75
76static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
77 StringRef Modifier, StringRef Argument,
78 ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
79 SmallVectorImpl<char> &Output,
80 void *Cookie,
81 ArrayRef<intptr_t> QualTypeVals) {
82 StringRef Str = "<can't format argument>";
83 Output.append(Str.begin(), Str.end());
84}
85
86DiagnosticsEngine::DiagnosticsEngine(
87 IntrusiveRefCntPtr<DiagnosticIDs> diags,
88 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, DiagnosticConsumer *client,
89 bool ShouldOwnClient)
90 : Diags(std::move(diags)), DiagOpts(std::move(DiagOpts)) {
91 setClient(client, ShouldOwnClient);
92 ArgToStringFn = DummyArgToStringFn;
93
94 Reset();
95}
96
97DiagnosticsEngine::~DiagnosticsEngine() {
98 // If we own the diagnostic client, destroy it first so that it can access the
99 // engine from its destructor.
100 setClient(nullptr);
101}
102
103void DiagnosticsEngine::dump() const {
104 DiagStatesByLoc.dump(*SourceMgr);
105}
106
107void DiagnosticsEngine::dump(StringRef DiagName) const {
108 DiagStatesByLoc.dump(*SourceMgr, DiagName);
109}
110
111void DiagnosticsEngine::setClient(DiagnosticConsumer *client,
112 bool ShouldOwnClient) {
113 Owner.reset(ShouldOwnClient ? client : nullptr);
114 Client = client;
115}
116
117void DiagnosticsEngine::pushMappings(SourceLocation Loc) {
118 DiagStateOnPushStack.push_back(GetCurDiagState());
119}
120
121bool DiagnosticsEngine::popMappings(SourceLocation Loc) {
122 if (DiagStateOnPushStack.empty())
123 return false;
124
125 if (DiagStateOnPushStack.back() != GetCurDiagState()) {
126 // State changed at some point between push/pop.
127 PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
128 }
129 DiagStateOnPushStack.pop_back();
130 return true;
131}
132
133void DiagnosticsEngine::Reset() {
134 ErrorOccurred = false;
135 UncompilableErrorOccurred = false;
136 FatalErrorOccurred = false;
137 UnrecoverableErrorOccurred = false;
138
139 NumWarnings = 0;
140 NumErrors = 0;
141 TrapNumErrorsOccurred = 0;
142 TrapNumUnrecoverableErrorsOccurred = 0;
143
144 CurDiagID = std::numeric_limits<unsigned>::max();
145 LastDiagLevel = DiagnosticIDs::Ignored;
146 DelayedDiagID = 0;
147
148 // Clear state related to #pragma diagnostic.
149 DiagStates.clear();
150 DiagStatesByLoc.clear();
151 DiagStateOnPushStack.clear();
152
153 // Create a DiagState and DiagStatePoint representing diagnostic changes
154 // through command-line.
155 DiagStates.emplace_back();
156 DiagStatesByLoc.appendFirst(&DiagStates.back());
157}
158
159void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1,
160 StringRef Arg2, StringRef Arg3) {
161 if (DelayedDiagID)
162 return;
163
164 DelayedDiagID = DiagID;
165 DelayedDiagArg1 = Arg1.str();
166 DelayedDiagArg2 = Arg2.str();
167 DelayedDiagArg3 = Arg3.str();
168}
169
170void DiagnosticsEngine::ReportDelayed() {
171 unsigned ID = DelayedDiagID;
172 DelayedDiagID = 0;
173 Report(ID) << DelayedDiagArg1 << DelayedDiagArg2 << DelayedDiagArg3;
174}
175
176void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
177 assert(Files.empty() && "not first")(static_cast<void> (0));
178 FirstDiagState = CurDiagState = State;
179 CurDiagStateLoc = SourceLocation();
180}
181
182void DiagnosticsEngine::DiagStateMap::append(SourceManager &SrcMgr,
183 SourceLocation Loc,
184 DiagState *State) {
185 CurDiagState = State;
186 CurDiagStateLoc = Loc;
187
188 std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedLoc(Loc);
189 unsigned Offset = Decomp.second;
190 for (File *F = getFile(SrcMgr, Decomp.first); F;
191 Offset = F->ParentOffset, F = F->Parent) {
192 F->HasLocalTransitions = true;
193 auto &Last = F->StateTransitions.back();
194 assert(Last.Offset <= Offset && "state transitions added out of order")(static_cast<void> (0));
195
196 if (Last.Offset == Offset) {
197 if (Last.State == State)
198 break;
199 Last.State = State;
200 continue;
201 }
202
203 F->StateTransitions.push_back({State, Offset});
204 }
205}
206
207DiagnosticsEngine::DiagState *
208DiagnosticsEngine::DiagStateMap::lookup(SourceManager &SrcMgr,
209 SourceLocation Loc) const {
210 // Common case: we have not seen any diagnostic pragmas.
211 if (Files.empty())
212 return FirstDiagState;
213
214 std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedLoc(Loc);
215 const File *F = getFile(SrcMgr, Decomp.first);
216 return F->lookup(Decomp.second);
217}
218
219DiagnosticsEngine::DiagState *
220DiagnosticsEngine::DiagStateMap::File::lookup(unsigned Offset) const {
221 auto OnePastIt =
222 llvm::partition_point(StateTransitions, [=](const DiagStatePoint &P) {
223 return P.Offset <= Offset;
224 });
225 assert(OnePastIt != StateTransitions.begin() && "missing initial state")(static_cast<void> (0));
226 return OnePastIt[-1].State;
227}
228
229DiagnosticsEngine::DiagStateMap::File *
230DiagnosticsEngine::DiagStateMap::getFile(SourceManager &SrcMgr,
231 FileID ID) const {
232 // Get or insert the File for this ID.
233 auto Range = Files.equal_range(ID);
234 if (Range.first != Range.second)
235 return &Range.first->second;
236 auto &F = Files.insert(Range.first, std::make_pair(ID, File()))->second;
237
238 // We created a new File; look up the diagnostic state at the start of it and
239 // initialize it.
240 if (ID.isValid()) {
241 std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedIncludedLoc(ID);
242 F.Parent = getFile(SrcMgr, Decomp.first);
243 F.ParentOffset = Decomp.second;
244 F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0});
245 } else {
246 // This is the (imaginary) root file into which we pretend all top-level
247 // files are included; it descends from the initial state.
248 //
249 // FIXME: This doesn't guarantee that we use the same ordering as
250 // isBeforeInTranslationUnit in the cases where someone invented another
251 // top-level file and added diagnostic pragmas to it. See the code at the
252 // end of isBeforeInTranslationUnit for the quirks it deals with.
253 F.StateTransitions.push_back({FirstDiagState, 0});
254 }
255 return &F;
256}
257
258void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
259 StringRef DiagName) const {
260 llvm::errs() << "diagnostic state at ";
261 CurDiagStateLoc.print(llvm::errs(), SrcMgr);
262 llvm::errs() << ": " << CurDiagState << "\n";
263
264 for (auto &F : Files) {
265 FileID ID = F.first;
266 File &File = F.second;
267
268 bool PrintedOuterHeading = false;
269 auto PrintOuterHeading = [&] {
270 if (PrintedOuterHeading) return;
271 PrintedOuterHeading = true;
272
273 llvm::errs() << "File " << &File << " <FileID " << ID.getHashValue()
274 << ">: " << SrcMgr.getBufferOrFake(ID).getBufferIdentifier();
275
276 if (F.second.Parent) {
277 std::pair<FileID, unsigned> Decomp =
278 SrcMgr.getDecomposedIncludedLoc(ID);
279 assert(File.ParentOffset == Decomp.second)(static_cast<void> (0));
280 llvm::errs() << " parent " << File.Parent << " <FileID "
281 << Decomp.first.getHashValue() << "> ";
282 SrcMgr.getLocForStartOfFile(Decomp.first)
283 .getLocWithOffset(Decomp.second)
284 .print(llvm::errs(), SrcMgr);
285 }
286 if (File.HasLocalTransitions)
287 llvm::errs() << " has_local_transitions";
288 llvm::errs() << "\n";
289 };
290
291 if (DiagName.empty())
292 PrintOuterHeading();
293
294 for (DiagStatePoint &Transition : File.StateTransitions) {
295 bool PrintedInnerHeading = false;
296 auto PrintInnerHeading = [&] {
297 if (PrintedInnerHeading) return;
298 PrintedInnerHeading = true;
299
300 PrintOuterHeading();
301 llvm::errs() << " ";
302 SrcMgr.getLocForStartOfFile(ID)
303 .getLocWithOffset(Transition.Offset)
304 .print(llvm::errs(), SrcMgr);
305 llvm::errs() << ": state " << Transition.State << ":\n";
306 };
307
308 if (DiagName.empty())
309 PrintInnerHeading();
310
311 for (auto &Mapping : *Transition.State) {
312 StringRef Option =
313 DiagnosticIDs::getWarningOptionForDiag(Mapping.first);
314 if (!DiagName.empty() && DiagName != Option)
315 continue;
316
317 PrintInnerHeading();
318 llvm::errs() << " ";
319 if (Option.empty())
320 llvm::errs() << "<unknown " << Mapping.first << ">";
321 else
322 llvm::errs() << Option;
323 llvm::errs() << ": ";
324
325 switch (Mapping.second.getSeverity()) {
326 case diag::Severity::Ignored: llvm::errs() << "ignored"; break;
327 case diag::Severity::Remark: llvm::errs() << "remark"; break;
328 case diag::Severity::Warning: llvm::errs() << "warning"; break;
329 case diag::Severity::Error: llvm::errs() << "error"; break;
330 case diag::Severity::Fatal: llvm::errs() << "fatal"; break;
331 }
332
333 if (!Mapping.second.isUser())
334 llvm::errs() << " default";
335 if (Mapping.second.isPragma())
336 llvm::errs() << " pragma";
337 if (Mapping.second.hasNoWarningAsError())
338 llvm::errs() << " no-error";
339 if (Mapping.second.hasNoErrorAsFatal())
340 llvm::errs() << " no-fatal";
341 if (Mapping.second.wasUpgradedFromWarning())
342 llvm::errs() << " overruled";
343 llvm::errs() << "\n";
344 }
345 }
346 }
347}
348
349void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
350 SourceLocation Loc) {
351 assert(Loc.isValid() && "Adding invalid loc point")(static_cast<void> (0));
352 DiagStatesByLoc.append(*SourceMgr, Loc, State);
353}
354
355void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
356 SourceLocation L) {
357 assert(Diag < diag::DIAG_UPPER_LIMIT &&(static_cast<void> (0))
358 "Can only map builtin diagnostics")(static_cast<void> (0));
359 assert((Diags->isBuiltinWarningOrExtension(Diag) ||(static_cast<void> (0))
360 (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) &&(static_cast<void> (0))
361 "Cannot map errors into warnings!")(static_cast<void> (0));
362 assert((L.isInvalid() || SourceMgr) && "No SourceMgr for valid location")(static_cast<void> (0));
363
364 // Don't allow a mapping to a warning override an error/fatal mapping.
365 bool WasUpgradedFromWarning = false;
366 if (Map == diag::Severity::Warning) {
367 DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
368 if (Info.getSeverity() == diag::Severity::Error ||
369 Info.getSeverity() == diag::Severity::Fatal) {
370 Map = Info.getSeverity();
371 WasUpgradedFromWarning = true;
372 }
373 }
374 DiagnosticMapping Mapping = makeUserMapping(Map, L);
375 Mapping.setUpgradedFromWarning(WasUpgradedFromWarning);
376
377 // Common case; setting all the diagnostics of a group in one place.
378 if ((L.isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
379 DiagStatesByLoc.getCurDiagState()) {
380 // FIXME: This is theoretically wrong: if the current state is shared with
381 // some other location (via push/pop) we will change the state for that
382 // other location as well. This cannot currently happen, as we can't update
383 // the diagnostic state at the same location at which we pop.
384 DiagStatesByLoc.getCurDiagState()->setMapping(Diag, Mapping);
385 return;
386 }
387
388 // A diagnostic pragma occurred, create a new DiagState initialized with
389 // the current one and a new DiagStatePoint to record at which location
390 // the new state became active.
391 DiagStates.push_back(*GetCurDiagState());
392 DiagStates.back().setMapping(Diag, Mapping);
393 PushDiagStatePoint(&DiagStates.back(), L);
394}
395
396bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
397 StringRef Group, diag::Severity Map,
398 SourceLocation Loc) {
399 // Get the diagnostics in this group.
400 SmallVector<diag::kind, 256> GroupDiags;
401 if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
402 return true;
403
404 // Set the mapping.
405 for (diag::kind Diag : GroupDiags)
406 setSeverity(Diag, Map, Loc);
407
408 return false;
409}
410
411bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
412 bool Enabled) {
413 // If we are enabling this feature, just set the diagnostic mappings to map to
414 // errors.
415 if (Enabled)
416 return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
417 diag::Severity::Error);
418
419 // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
420 // potentially downgrade anything already mapped to be a warning.
421
422 // Get the diagnostics in this group.
423 SmallVector<diag::kind, 8> GroupDiags;
424 if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
425 GroupDiags))
426 return true;
427
428 // Perform the mapping change.
429 for (diag::kind Diag : GroupDiags) {
430 DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
431
432 if (Info.getSeverity() == diag::Severity::Error ||
433 Info.getSeverity() == diag::Severity::Fatal)
434 Info.setSeverity(diag::Severity::Warning);
435
436 Info.setNoWarningAsError(true);
437 }
438
439 return false;
440}
441
442bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
443 bool Enabled) {
444 // If we are enabling this feature, just set the diagnostic mappings to map to
445 // fatal errors.
446 if (Enabled)
447 return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
448 diag::Severity::Fatal);
449
450 // Otherwise, we want to set the diagnostic mapping's "no Wfatal-errors" bit,
451 // and potentially downgrade anything already mapped to be a fatal error.
452
453 // Get the diagnostics in this group.
454 SmallVector<diag::kind, 8> GroupDiags;
455 if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
456 GroupDiags))
457 return true;
458
459 // Perform the mapping change.
460 for (diag::kind Diag : GroupDiags) {
461 DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
462
463 if (Info.getSeverity() == diag::Severity::Fatal)
464 Info.setSeverity(diag::Severity::Error);
465
466 Info.setNoErrorAsFatal(true);
467 }
468
469 return false;
470}
471
472void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
473 diag::Severity Map,
474 SourceLocation Loc) {
475 // Get all the diagnostics.
476 std::vector<diag::kind> AllDiags;
477 DiagnosticIDs::getAllDiagnostics(Flavor, AllDiags);
478
479 // Set the mapping.
480 for (diag::kind Diag : AllDiags)
481 if (Diags->isBuiltinWarningOrExtension(Diag))
482 setSeverity(Diag, Map, Loc);
483}
484
485void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
486 assert(CurDiagID == std::numeric_limits<unsigned>::max() &&(static_cast<void> (0))
487 "Multiple diagnostics in flight at once!")(static_cast<void> (0));
488
489 CurDiagLoc = storedDiag.getLocation();
490 CurDiagID = storedDiag.getID();
491 DiagStorage.NumDiagArgs = 0;
492
493 DiagStorage.DiagRanges.clear();
494 DiagStorage.DiagRanges.append(storedDiag.range_begin(),
495 storedDiag.range_end());
496
497 DiagStorage.FixItHints.clear();
498 DiagStorage.FixItHints.append(storedDiag.fixit_begin(),
499 storedDiag.fixit_end());
500
501 assert(Client && "DiagnosticConsumer not set!")(static_cast<void> (0));
502 Level DiagLevel = storedDiag.getLevel();
503 Diagnostic Info(this, storedDiag.getMessage());
504 Client->HandleDiagnostic(DiagLevel, Info);
505 if (Client->IncludeInDiagnosticCounts()) {
506 if (DiagLevel == DiagnosticsEngine::Warning)
507 ++NumWarnings;
508 }
509
510 CurDiagID = std::numeric_limits<unsigned>::max();
511}
512
513bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) {
514 assert(getClient() && "DiagnosticClient not set!")(static_cast<void> (0));
515
516 bool Emitted;
517 if (Force) {
518 Diagnostic Info(this);
519
520 // Figure out the diagnostic level of this message.
521 DiagnosticIDs::Level DiagLevel
522 = Diags->getDiagnosticLevel(Info.getID(), Info.getLocation(), *this);
523
524 Emitted = (DiagLevel != DiagnosticIDs::Ignored);
525 if (Emitted) {
526 // Emit the diagnostic regardless of suppression level.
527 Diags->EmitDiag(*this, DiagLevel);
528 }
529 } else {
530 // Process the diagnostic, sending the accumulated information to the
531 // DiagnosticConsumer.
532 Emitted = ProcessDiag();
533 }
534
535 // Clear out the current diagnostic object.
536 Clear();
537
538 // If there was a delayed diagnostic, emit it now.
539 if (!Force && DelayedDiagID)
540 ReportDelayed();
541
542 return Emitted;
543}
544
545DiagnosticConsumer::~DiagnosticConsumer() = default;
546
547void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
548 const Diagnostic &Info) {
549 if (!IncludeInDiagnosticCounts())
550 return;
551
552 if (DiagLevel == DiagnosticsEngine::Warning)
553 ++NumWarnings;
554 else if (DiagLevel >= DiagnosticsEngine::Error)
555 ++NumErrors;
556}
557
558/// ModifierIs - Return true if the specified modifier matches specified string.
559template <std::size_t StrLen>
560static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
561 const char (&Str)[StrLen]) {
562 return StrLen-1 == ModifierLen && memcmp(Modifier, Str, StrLen-1) == 0;
43
Returning zero, which participates in a condition later
563}
564
565/// ScanForward - Scans forward, looking for the given character, skipping
566/// nested clauses and escaped characters.
567static const char *ScanFormat(const char *I, const char *E, char Target) {
568 unsigned Depth = 0;
569
570 for ( ; I != E; ++I) {
571 if (Depth == 0 && *I == Target) return I;
572 if (Depth != 0 && *I == '}') Depth--;
573
574 if (*I == '%') {
575 I++;
576 if (I == E) break;
577
578 // Escaped characters get implicitly skipped here.
579
580 // Format specifier.
581 if (!isDigit(*I) && !isPunctuation(*I)) {
582 for (I++; I != E && !isDigit(*I) && *I != '{'; I++) ;
583 if (I == E) break;
584 if (*I == '{')
585 Depth++;
586 }
587 }
588 }
589 return E;
590}
591
592/// HandleSelectModifier - Handle the integer 'select' modifier. This is used
593/// like this: %select{foo|bar|baz}2. This means that the integer argument
594/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'.
595/// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'.
596/// This is very useful for certain classes of variant diagnostics.
597static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo,
598 const char *Argument, unsigned ArgumentLen,
599 SmallVectorImpl<char> &OutStr) {
600 const char *ArgumentEnd = Argument+ArgumentLen;
601
602 // Skip over 'ValNo' |'s.
603 while (ValNo) {
604 const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
605 assert(NextVal != ArgumentEnd && "Value for integer select modifier was"(static_cast<void> (0))
606 " larger than the number of options in the diagnostic string!")(static_cast<void> (0));
607 Argument = NextVal+1; // Skip this string.
608 --ValNo;
609 }
610
611 // Get the end of the value. This is either the } or the |.
612 const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
613
614 // Recursively format the result of the select clause into the output string.
615 DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
616}
617
618/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the
619/// letter 's' to the string if the value is not 1. This is used in cases like
620/// this: "you idiot, you have %4 parameter%s4!".
621static void HandleIntegerSModifier(unsigned ValNo,
622 SmallVectorImpl<char> &OutStr) {
623 if (ValNo != 1)
624 OutStr.push_back('s');
625}
626
627/// HandleOrdinalModifier - Handle the integer 'ord' modifier. This
628/// prints the ordinal form of the given integer, with 1 corresponding
629/// to the first ordinal. Currently this is hard-coded to use the
630/// English form.
631static void HandleOrdinalModifier(unsigned ValNo,
632 SmallVectorImpl<char> &OutStr) {
633 assert(ValNo != 0 && "ValNo must be strictly positive!")(static_cast<void> (0));
634
635 llvm::raw_svector_ostream Out(OutStr);
636
637 // We could use text forms for the first N ordinals, but the numeric
638 // forms are actually nicer in diagnostics because they stand out.
639 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
640}
641
642/// PluralNumber - Parse an unsigned integer and advance Start.
643static unsigned PluralNumber(const char *&Start, const char *End) {
644 // Programming 101: Parse a decimal number :-)
645 unsigned Val = 0;
646 while (Start != End && *Start >= '0' && *Start <= '9') {
647 Val *= 10;
648 Val += *Start - '0';
649 ++Start;
650 }
651 return Val;
652}
653
654/// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
655static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
656 if (*Start != '[') {
657 unsigned Ref = PluralNumber(Start, End);
658 return Ref == Val;
659 }
660
661 ++Start;
662 unsigned Low = PluralNumber(Start, End);
663 assert(*Start == ',' && "Bad plural expression syntax: expected ,")(static_cast<void> (0));
664 ++Start;
665 unsigned High = PluralNumber(Start, End);
666 assert(*Start == ']' && "Bad plural expression syntax: expected )")(static_cast<void> (0));
667 ++Start;
668 return Low <= Val && Val <= High;
669}
670
671/// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
672static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
673 // Empty condition?
674 if (*Start == ':')
675 return true;
676
677 while (true) {
678 char C = *Start;
679 if (C == '%') {
680 // Modulo expression
681 ++Start;
682 unsigned Arg = PluralNumber(Start, End);
683 assert(*Start == '=' && "Bad plural expression syntax: expected =")(static_cast<void> (0));
684 ++Start;
685 unsigned ValMod = ValNo % Arg;
686 if (TestPluralRange(ValMod, Start, End))
687 return true;
688 } else {
689 assert((C == '[' || (C >= '0' && C <= '9')) &&(static_cast<void> (0))
690 "Bad plural expression syntax: unexpected character")(static_cast<void> (0));
691 // Range expression
692 if (TestPluralRange(ValNo, Start, End))
693 return true;
694 }
695
696 // Scan for next or-expr part.
697 Start = std::find(Start, End, ',');
698 if (Start == End)
699 break;
700 ++Start;
701 }
702 return false;
703}
704
705/// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
706/// for complex plural forms, or in languages where all plurals are complex.
707/// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
708/// conditions that are tested in order, the form corresponding to the first
709/// that applies being emitted. The empty condition is always true, making the
710/// last form a default case.
711/// Conditions are simple boolean expressions, where n is the number argument.
712/// Here are the rules.
713/// condition := expression | empty
714/// empty := -> always true
715/// expression := numeric [',' expression] -> logical or
716/// numeric := range -> true if n in range
717/// | '%' number '=' range -> true if n % number in range
718/// range := number
719/// | '[' number ',' number ']' -> ranges are inclusive both ends
720///
721/// Here are some examples from the GNU gettext manual written in this form:
722/// English:
723/// {1:form0|:form1}
724/// Latvian:
725/// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
726/// Gaeilge:
727/// {1:form0|2:form1|:form2}
728/// Romanian:
729/// {1:form0|0,%100=[1,19]:form1|:form2}
730/// Lithuanian:
731/// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
732/// Russian (requires repeated form):
733/// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
734/// Slovak
735/// {1:form0|[2,4]:form1|:form2}
736/// Polish (requires repeated form):
737/// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
738static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
739 const char *Argument, unsigned ArgumentLen,
740 SmallVectorImpl<char> &OutStr) {
741 const char *ArgumentEnd = Argument + ArgumentLen;
742 while (true) {
743 assert(Argument < ArgumentEnd && "Plural expression didn't match.")(static_cast<void> (0));
744 const char *ExprEnd = Argument;
745 while (*ExprEnd != ':') {
746 assert(ExprEnd != ArgumentEnd && "Plural missing expression end")(static_cast<void> (0));
747 ++ExprEnd;
748 }
749 if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
750 Argument = ExprEnd + 1;
751 ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
752
753 // Recursively format the result of the plural clause into the
754 // output string.
755 DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr);
756 return;
757 }
758 Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
759 }
760}
761
762/// Returns the friendly description for a token kind that will appear
763/// without quotes in diagnostic messages. These strings may be translatable in
764/// future.
765static const char *getTokenDescForDiagnostic(tok::TokenKind Kind) {
766 switch (Kind) {
767 case tok::identifier:
768 return "identifier";
769 default:
770 return nullptr;
771 }
772}
773
774/// FormatDiagnostic - Format this diagnostic into a string, substituting the
775/// formal arguments into the %0 slots. The result is appended onto the Str
776/// array.
777void Diagnostic::
778FormatDiagnostic(SmallVectorImpl<char> &OutStr) const {
779 if (!StoredDiagMessage.empty()) {
3
Assuming the condition is false
4
Taking false branch
780 OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end());
781 return;
782 }
783
784 StringRef Diag =
785 getDiags()->getDiagnosticIDs()->getDescription(getID());
786
787 FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
5
Calling 'Diagnostic::FormatDiagnostic'
788}
789
790void Diagnostic::
791FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
792 SmallVectorImpl<char> &OutStr) const {
793 // When the diagnostic string is only "%0", the entire string is being given
794 // by an outside source. Remove unprintable characters from this string
795 // and skip all the other string processing.
796 if (DiagEnd - DiagStr == 2 &&
6
Assuming the condition is false
7
Taking false branch
30
Assuming the condition is false
31
Taking false branch
54
Assuming the condition is false
55
Taking false branch
797 StringRef(DiagStr, DiagEnd - DiagStr).equals("%0") &&
798 getArgKind(0) == DiagnosticsEngine::ak_std_string) {
799 const std::string &S = getArgStdStr(0);
800 for (char c : S) {
801 if (llvm::sys::locale::isPrint(c) || c == '\t') {
802 OutStr.push_back(c);
803 }
804 }
805 return;
806 }
807
808 /// FormattedArgs - Keep track of all of the arguments formatted by
809 /// ConvertArgToString and pass them into subsequent calls to
810 /// ConvertArgToString, allowing the implementation to avoid redundancies in
811 /// obvious cases.
812 SmallVector<DiagnosticsEngine::ArgumentValue, 8> FormattedArgs;
813
814 /// QualTypeVals - Pass a vector of arrays so that QualType names can be
815 /// compared to see if more information is needed to be printed.
816 SmallVector<intptr_t, 2> QualTypeVals;
817 SmallString<64> Tree;
818
819 for (unsigned i = 0, e = getNumArgs(); i < e; ++i)
8
Assuming 'i' is >= 'e'
9
Loop condition is false. Execution continues on line 823
32
Loop condition is false. Execution continues on line 823
56
Loop condition is false. Execution continues on line 823
820 if (getArgKind(i) == DiagnosticsEngine::ak_qualtype)
821 QualTypeVals.push_back(getRawArg(i));
822
823 while (DiagStr != DiagEnd) {
10
Assuming 'DiagStr' is not equal to 'DiagEnd'
11
Loop condition is true. Entering loop body
33
Assuming 'DiagStr' is not equal to 'DiagEnd'
34
Loop condition is true. Entering loop body
57
Assuming 'DiagStr' is not equal to 'DiagEnd'
58
Loop condition is true. Entering loop body
824 if (DiagStr[0] != '%') {
12
Assuming the condition is false
13
Taking false branch
35
Assuming the condition is false
36
Taking false branch
59
Array access (from variable 'DiagStr') results in a null pointer dereference
825 // Append non-%0 substrings to Str if we have one.
826 const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
827 OutStr.append(DiagStr, StrEnd);
828 DiagStr = StrEnd;
829 continue;
830 } else if (isPunctuation(DiagStr[1])) {
14
Assuming the condition is false
15
Taking false branch
37
Assuming the condition is false
38
Taking false branch
831 OutStr.push_back(DiagStr[1]); // %% -> %.
832 DiagStr += 2;
833 continue;
834 }
835
836 // Skip the %.
837 ++DiagStr;
838
839 // This must be a placeholder for a diagnostic argument. The format for a
840 // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
841 // The digit is a number from 0-9 indicating which argument this comes from.
842 // The modifier is a string of digits from the set [-a-z]+, arguments is a
843 // brace enclosed string.
844 const char *Modifier = nullptr, *Argument = nullptr;
39
'Argument' initialized to a null pointer value
845 unsigned ModifierLen = 0, ArgumentLen = 0;
846
847 // Check to see if we have a modifier. If so eat it.
848 if (!isDigit(DiagStr[0])) {
16
Assuming the condition is true
17
Taking true branch
40
Assuming the condition is false
41
Taking false branch
849 Modifier = DiagStr;
850 while (DiagStr[0] == '-' ||
18
Assuming the condition is false
21
Loop condition is false. Execution continues on line 853
851 (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
19
Assuming the condition is true
20
Assuming the condition is false
852 ++DiagStr;
853 ModifierLen = DiagStr-Modifier;
854
855 // If we have an argument, get it next.
856 if (DiagStr[0] == '{') {
22
Assuming the condition is true
23
Taking true branch
857 ++DiagStr; // Skip {.
858 Argument = DiagStr;
859
860 DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
861 assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!")(static_cast<void> (0));
862 ArgumentLen = DiagStr-Argument;
863 ++DiagStr; // Skip }.
864 }
865 }
866
867 assert(isDigit(*DiagStr) && "Invalid format for argument in diagnostic")(static_cast<void> (0));
868 unsigned ArgNo = *DiagStr++ - '0';
869
870 // Only used for type diffing.
871 unsigned ArgNo2 = ArgNo;
872
873 DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo);
874 if (ModifierIs(Modifier, ModifierLen, "diff")) {
24
Taking false branch
42
Calling 'ModifierIs<5UL>'
44
Returning from 'ModifierIs<5UL>'
45
Taking false branch
875 assert(*DiagStr == ',' && isDigit(*(DiagStr + 1)) &&(static_cast<void> (0))
876 "Invalid format for diff modifier")(static_cast<void> (0));
877 ++DiagStr; // Comma.
878 ArgNo2 = *DiagStr++ - '0';
879 DiagnosticsEngine::ArgumentKind Kind2 = getArgKind(ArgNo2);
880 if (Kind == DiagnosticsEngine::ak_qualtype &&
881 Kind2 == DiagnosticsEngine::ak_qualtype)
882 Kind = DiagnosticsEngine::ak_qualtype_pair;
883 else {
884 // %diff only supports QualTypes. For other kinds of arguments,
885 // use the default printing. For example, if the modifier is:
886 // "%diff{compare $ to $|other text}1,2"
887 // treat it as:
888 // "compare %1 to %2"
889 const char *ArgumentEnd = Argument + ArgumentLen;
890 const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
891 assert(ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd &&(static_cast<void> (0))
892 "Found too many '|'s in a %diff modifier!")(static_cast<void> (0));
893 const char *FirstDollar = ScanFormat(Argument, Pipe, '$');
894 const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$');
895 const char ArgStr1[] = { '%', static_cast<char>('0' + ArgNo) };
896 const char ArgStr2[] = { '%', static_cast<char>('0' + ArgNo2) };
897 FormatDiagnostic(Argument, FirstDollar, OutStr);
898 FormatDiagnostic(ArgStr1, ArgStr1 + 2, OutStr);
899 FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
900 FormatDiagnostic(ArgStr2, ArgStr2 + 2, OutStr);
901 FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
902 continue;
903 }
904 }
905
906 switch (Kind) {
25
Control jumps to 'case ak_qualtype_pair:' at line 1014
46
Control jumps to 'case ak_qualtype_pair:' at line 1014
907 // ---- STRINGS ----
908 case DiagnosticsEngine::ak_std_string: {
909 const std::string &S = getArgStdStr(ArgNo);
910 assert(ModifierLen == 0 && "No modifiers for strings yet")(static_cast<void> (0));
911 OutStr.append(S.begin(), S.end());
912 break;
913 }
914 case DiagnosticsEngine::ak_c_string: {
915 const char *S = getArgCStr(ArgNo);
916 assert(ModifierLen == 0 && "No modifiers for strings yet")(static_cast<void> (0));
917
918 // Don't crash if get passed a null pointer by accident.
919 if (!S)
920 S = "(null)";
921
922 OutStr.append(S, S + strlen(S));
923 break;
924 }
925 // ---- INTEGERS ----
926 case DiagnosticsEngine::ak_sint: {
927 int Val = getArgSInt(ArgNo);
928
929 if (ModifierIs(Modifier, ModifierLen, "select")) {
930 HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen,
931 OutStr);
932 } else if (ModifierIs(Modifier, ModifierLen, "s")) {
933 HandleIntegerSModifier(Val, OutStr);
934 } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
935 HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
936 OutStr);
937 } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
938 HandleOrdinalModifier((unsigned)Val, OutStr);
939 } else {
940 assert(ModifierLen == 0 && "Unknown integer modifier")(static_cast<void> (0));
941 llvm::raw_svector_ostream(OutStr) << Val;
942 }
943 break;
944 }
945 case DiagnosticsEngine::ak_uint: {
946 unsigned Val = getArgUInt(ArgNo);
947
948 if (ModifierIs(Modifier, ModifierLen, "select")) {
949 HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
950 } else if (ModifierIs(Modifier, ModifierLen, "s")) {
951 HandleIntegerSModifier(Val, OutStr);
952 } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
953 HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
954 OutStr);
955 } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
956 HandleOrdinalModifier(Val, OutStr);
957 } else {
958 assert(ModifierLen == 0 && "Unknown integer modifier")(static_cast<void> (0));
959 llvm::raw_svector_ostream(OutStr) << Val;
960 }
961 break;
962 }
963 // ---- TOKEN SPELLINGS ----
964 case DiagnosticsEngine::ak_tokenkind: {
965 tok::TokenKind Kind = static_cast<tok::TokenKind>(getRawArg(ArgNo));
966 assert(ModifierLen == 0 && "No modifiers for token kinds yet")(static_cast<void> (0));
967
968 llvm::raw_svector_ostream Out(OutStr);
969 if (const char *S = tok::getPunctuatorSpelling(Kind))
970 // Quoted token spelling for punctuators.
971 Out << '\'' << S << '\'';
972 else if (const char *S = tok::getKeywordSpelling(Kind))
973 // Unquoted token spelling for keywords.
974 Out << S;
975 else if (const char *S = getTokenDescForDiagnostic(Kind))
976 // Unquoted translatable token name.
977 Out << S;
978 else if (const char *S = tok::getTokenName(Kind))
979 // Debug name, shouldn't appear in user-facing diagnostics.
980 Out << '<' << S << '>';
981 else
982 Out << "(null)";
983 break;
984 }
985 // ---- NAMES and TYPES ----
986 case DiagnosticsEngine::ak_identifierinfo: {
987 const IdentifierInfo *II = getArgIdentifier(ArgNo);
988 assert(ModifierLen == 0 && "No modifiers for strings yet")(static_cast<void> (0));
989
990 // Don't crash if get passed a null pointer by accident.
991 if (!II) {
992 const char *S = "(null)";
993 OutStr.append(S, S + strlen(S));
994 continue;
995 }
996
997 llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
998 break;
999 }
1000 case DiagnosticsEngine::ak_addrspace:
1001 case DiagnosticsEngine::ak_qual:
1002 case DiagnosticsEngine::ak_qualtype:
1003 case DiagnosticsEngine::ak_declarationname:
1004 case DiagnosticsEngine::ak_nameddecl:
1005 case DiagnosticsEngine::ak_nestednamespec:
1006 case DiagnosticsEngine::ak_declcontext:
1007 case DiagnosticsEngine::ak_attr:
1008 getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
1009 StringRef(Modifier, ModifierLen),
1010 StringRef(Argument, ArgumentLen),
1011 FormattedArgs,
1012 OutStr, QualTypeVals);
1013 break;
1014 case DiagnosticsEngine::ak_qualtype_pair: {
1015 // Create a struct with all the info needed for printing.
1016 TemplateDiffTypes TDT;
1017 TDT.FromType = getRawArg(ArgNo);
1018 TDT.ToType = getRawArg(ArgNo2);
1019 TDT.ElideType = getDiags()->ElideType;
1020 TDT.ShowColors = getDiags()->ShowColors;
1021 TDT.TemplateDiffUsed = false;
1022 intptr_t val = reinterpret_cast<intptr_t>(&TDT);
1023
1024 const char *ArgumentEnd = Argument + ArgumentLen;
1025 const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
1026
1027 // Print the tree. If this diagnostic already has a tree, skip the
1028 // second tree.
1029 if (getDiags()->PrintTemplateTree
46.1
Field 'PrintTemplateTree' is true
46.1
Field 'PrintTemplateTree' is true
&& Tree.empty()) {
26
Assuming field 'PrintTemplateTree' is true
27
Taking true branch
47
Calling 'SmallVectorBase::empty'
50
Returning from 'SmallVectorBase::empty'
51
Taking false branch
1030 TDT.PrintFromType = true;
1031 TDT.PrintTree = true;
1032 getDiags()->ConvertArgToString(Kind, val,
1033 StringRef(Modifier, ModifierLen),
1034 StringRef(Argument, ArgumentLen),
1035 FormattedArgs,
1036 Tree, QualTypeVals);
1037 // If there is no tree information, fall back to regular printing.
1038 if (!Tree.empty()) {
28
Taking true branch
1039 FormatDiagnostic(Pipe + 1, ArgumentEnd, OutStr);
29
Calling 'Diagnostic::FormatDiagnostic'
1040 break;
1041 }
1042 }
1043
1044 // Non-tree printing, also the fall-back when tree printing fails.
1045 // The fall-back is triggered when the types compared are not templates.
1046 const char *FirstDollar = ScanFormat(Argument, ArgumentEnd, '$');
1047 const char *SecondDollar = ScanFormat(FirstDollar + 1, ArgumentEnd, '$');
1048
1049 // Append before text
1050 FormatDiagnostic(Argument, FirstDollar, OutStr);
52
Passing null pointer value via 1st parameter 'DiagStr'
53
Calling 'Diagnostic::FormatDiagnostic'
1051
1052 // Append first type
1053 TDT.PrintTree = false;
1054 TDT.PrintFromType = true;
1055 getDiags()->ConvertArgToString(Kind, val,
1056 StringRef(Modifier, ModifierLen),
1057 StringRef(Argument, ArgumentLen),
1058 FormattedArgs,
1059 OutStr, QualTypeVals);
1060 if (!TDT.TemplateDiffUsed)
1061 FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
1062 TDT.FromType));
1063
1064 // Append middle text
1065 FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
1066
1067 // Append second type
1068 TDT.PrintFromType = false;
1069 getDiags()->ConvertArgToString(Kind, val,
1070 StringRef(Modifier, ModifierLen),
1071 StringRef(Argument, ArgumentLen),
1072 FormattedArgs,
1073 OutStr, QualTypeVals);
1074 if (!TDT.TemplateDiffUsed)
1075 FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
1076 TDT.ToType));
1077
1078 // Append end text
1079 FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
1080 break;
1081 }
1082 }
1083
1084 // Remember this argument info for subsequent formatting operations. Turn
1085 // std::strings into a null terminated string to make it be the same case as
1086 // all the other ones.
1087 if (Kind == DiagnosticsEngine::ak_qualtype_pair)
1088 continue;
1089 else if (Kind != DiagnosticsEngine::ak_std_string)
1090 FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
1091 else
1092 FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_c_string,
1093 (intptr_t)getArgStdStr(ArgNo).c_str()));
1094 }
1095
1096 // Append the type tree to the end of the diagnostics.
1097 OutStr.append(Tree.begin(), Tree.end());
1098}
1099
1100StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1101 StringRef Message)
1102 : ID(ID), Level(Level), Message(Message) {}
1103
1104StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
1105 const Diagnostic &Info)
1106 : ID(Info.getID()), Level(Level) {
1107 assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&(static_cast<void> (0))
1108 "Valid source location without setting a source manager for diagnostic")(static_cast<void> (0));
1109 if (Info.getLocation().isValid())
1
Taking false branch
1110 Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
1111 SmallString<64> Message;
1112 Info.FormatDiagnostic(Message);
2
Calling 'Diagnostic::FormatDiagnostic'
1113 this->Message.assign(Message.begin(), Message.end());
1114 this->Ranges.assign(Info.getRanges().begin(), Info.getRanges().end());
1115 this->FixIts.assign(Info.getFixItHints().begin(), Info.getFixItHints().end());
1116}
1117
1118StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1119 StringRef Message, FullSourceLoc Loc,
1120 ArrayRef<CharSourceRange> Ranges,
1121 ArrayRef<FixItHint> FixIts)
1122 : ID(ID), Level(Level), Loc(Loc), Message(Message),
1123 Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
1124{
1125}
1126
1127/// IncludeInDiagnosticCounts - This method (whose default implementation
1128/// returns true) indicates whether the diagnostics handled by this
1129/// DiagnosticConsumer should be included in the number of diagnostics
1130/// reported by DiagnosticsEngine.
1131bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; }
1132
1133void IgnoringDiagConsumer::anchor() {}
1134
1135ForwardingDiagnosticConsumer::~ForwardingDiagnosticConsumer() = default;
1136
1137void ForwardingDiagnosticConsumer::HandleDiagnostic(
1138 DiagnosticsEngine::Level DiagLevel,
1139 const Diagnostic &Info) {
1140 Target.HandleDiagnostic(DiagLevel, Info);
1141}
1142
1143void ForwardingDiagnosticConsumer::clear() {
1144 DiagnosticConsumer::clear();
1145 Target.clear();
1146}
1147
1148bool ForwardingDiagnosticConsumer::IncludeInDiagnosticCounts() const {
1149 return Target.IncludeInDiagnosticCounts();
1150}
1151
1152PartialDiagnostic::DiagStorageAllocator::DiagStorageAllocator() {
1153 for (unsigned I = 0; I != NumCached; ++I)
1154 FreeList[I] = Cached + I;
1155 NumFreeListEntries = NumCached;
1156}
1157
1158PartialDiagnostic::DiagStorageAllocator::~DiagStorageAllocator() {
1159 // Don't assert if we are in a CrashRecovery context, as this invariant may
1160 // be invalidated during a crash.
1161 assert((NumFreeListEntries == NumCached ||(static_cast<void> (0))
1162 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&(static_cast<void> (0))
1163 "A partial is on the lam")(static_cast<void> (0));
1164}
1165
1166char DiagnosticError::ID;

/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include/llvm/ADT/SmallVector.h

1//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- 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// This file defines the SmallVector class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_ADT_SMALLVECTOR_H
14#define LLVM_ADT_SMALLVECTOR_H
15
16#include "llvm/ADT/iterator_range.h"
17#include "llvm/Support/Compiler.h"
18#include "llvm/Support/ErrorHandling.h"
19#include "llvm/Support/MemAlloc.h"
20#include "llvm/Support/type_traits.h"
21#include <algorithm>
22#include <cassert>
23#include <cstddef>
24#include <cstdlib>
25#include <cstring>
26#include <functional>
27#include <initializer_list>
28#include <iterator>
29#include <limits>
30#include <memory>
31#include <new>
32#include <type_traits>
33#include <utility>
34
35namespace llvm {
36
37/// This is all the stuff common to all SmallVectors.
38///
39/// The template parameter specifies the type which should be used to hold the
40/// Size and Capacity of the SmallVector, so it can be adjusted.
41/// Using 32 bit size is desirable to shrink the size of the SmallVector.
42/// Using 64 bit size is desirable for cases like SmallVector<char>, where a
43/// 32 bit size would limit the vector to ~4GB. SmallVectors are used for
44/// buffering bitcode output - which can exceed 4GB.
45template <class Size_T> class SmallVectorBase {
46protected:
47 void *BeginX;
48 Size_T Size = 0, Capacity;
49
50 /// The maximum value of the Size_T used.
51 static constexpr size_t SizeTypeMax() {
52 return std::numeric_limits<Size_T>::max();
53 }
54
55 SmallVectorBase() = delete;
56 SmallVectorBase(void *FirstEl, size_t TotalCapacity)
57 : BeginX(FirstEl), Capacity(TotalCapacity) {}
58
59 /// This is a helper for \a grow() that's out of line to reduce code
60 /// duplication. This function will report a fatal error if it can't grow at
61 /// least to \p MinSize.
62 void *mallocForGrow(size_t MinSize, size_t TSize, size_t &NewCapacity);
63
64 /// This is an implementation of the grow() method which only works
65 /// on POD-like data types and is out of line to reduce code duplication.
66 /// This function will report a fatal error if it cannot increase capacity.
67 void grow_pod(void *FirstEl, size_t MinSize, size_t TSize);
68
69public:
70 size_t size() const { return Size; }
71 size_t capacity() const { return Capacity; }
72
73 LLVM_NODISCARD[[clang::warn_unused_result]] bool empty() const { return !Size; }
48
Assuming field 'Size' is not equal to 0
49
Returning zero, which participates in a condition later
74
75 /// Set the array size to \p N, which the current array must have enough
76 /// capacity for.
77 ///
78 /// This does not construct or destroy any elements in the vector.
79 ///
80 /// Clients can use this in conjunction with capacity() to write past the end
81 /// of the buffer when they know that more elements are available, and only
82 /// update the size later. This avoids the cost of value initializing elements
83 /// which will only be overwritten.
84 void set_size(size_t N) {
85 assert(N <= capacity())(static_cast<void> (0));
86 Size = N;
87 }
88};
89
90template <class T>
91using SmallVectorSizeType =
92 typename std::conditional<sizeof(T) < 4 && sizeof(void *) >= 8, uint64_t,
93 uint32_t>::type;
94
95/// Figure out the offset of the first element.
96template <class T, typename = void> struct SmallVectorAlignmentAndSize {
97 alignas(SmallVectorBase<SmallVectorSizeType<T>>) char Base[sizeof(
98 SmallVectorBase<SmallVectorSizeType<T>>)];
99 alignas(T) char FirstEl[sizeof(T)];
100};
101
102/// This is the part of SmallVectorTemplateBase which does not depend on whether
103/// the type T is a POD. The extra dummy template argument is used by ArrayRef
104/// to avoid unnecessarily requiring T to be complete.
105template <typename T, typename = void>
106class SmallVectorTemplateCommon
107 : public SmallVectorBase<SmallVectorSizeType<T>> {
108 using Base = SmallVectorBase<SmallVectorSizeType<T>>;
109
110 /// Find the address of the first element. For this pointer math to be valid
111 /// with small-size of 0 for T with lots of alignment, it's important that
112 /// SmallVectorStorage is properly-aligned even for small-size of 0.
113 void *getFirstEl() const {
114 return const_cast<void *>(reinterpret_cast<const void *>(
115 reinterpret_cast<const char *>(this) +
116 offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)__builtin_offsetof(SmallVectorAlignmentAndSize<T>, FirstEl
)
));
117 }
118 // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
119
120protected:
121 SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {}
122
123 void grow_pod(size_t MinSize, size_t TSize) {
124 Base::grow_pod(getFirstEl(), MinSize, TSize);
125 }
126
127 /// Return true if this is a smallvector which has not had dynamic
128 /// memory allocated for it.
129 bool isSmall() const { return this->BeginX == getFirstEl(); }
130
131 /// Put this vector in a state of being small.
132 void resetToSmall() {
133 this->BeginX = getFirstEl();
134 this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect.
135 }
136
137 /// Return true if V is an internal reference to the given range.
138 bool isReferenceToRange(const void *V, const void *First, const void *Last) const {
139 // Use std::less to avoid UB.
140 std::less<> LessThan;
141 return !LessThan(V, First) && LessThan(V, Last);
142 }
143
144 /// Return true if V is an internal reference to this vector.
145 bool isReferenceToStorage(const void *V) const {
146 return isReferenceToRange(V, this->begin(), this->end());
147 }
148
149 /// Return true if First and Last form a valid (possibly empty) range in this
150 /// vector's storage.
151 bool isRangeInStorage(const void *First, const void *Last) const {
152 // Use std::less to avoid UB.
153 std::less<> LessThan;
154 return !LessThan(First, this->begin()) && !LessThan(Last, First) &&
155 !LessThan(this->end(), Last);
156 }
157
158 /// Return true unless Elt will be invalidated by resizing the vector to
159 /// NewSize.
160 bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize) {
161 // Past the end.
162 if (LLVM_LIKELY(!isReferenceToStorage(Elt))__builtin_expect((bool)(!isReferenceToStorage(Elt)), true))
163 return true;
164
165 // Return false if Elt will be destroyed by shrinking.
166 if (NewSize <= this->size())
167 return Elt < this->begin() + NewSize;
168
169 // Return false if we need to grow.
170 return NewSize <= this->capacity();
171 }
172
173 /// Check whether Elt will be invalidated by resizing the vector to NewSize.
174 void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize) {
175 assert(isSafeToReferenceAfterResize(Elt, NewSize) &&(static_cast<void> (0))
176 "Attempting to reference an element of the vector in an operation "(static_cast<void> (0))
177 "that invalidates it")(static_cast<void> (0));
178 }
179
180 /// Check whether Elt will be invalidated by increasing the size of the
181 /// vector by N.
182 void assertSafeToAdd(const void *Elt, size_t N = 1) {
183 this->assertSafeToReferenceAfterResize(Elt, this->size() + N);
184 }
185
186 /// Check whether any part of the range will be invalidated by clearing.
187 void assertSafeToReferenceAfterClear(const T *From, const T *To) {
188 if (From == To)
189 return;
190 this->assertSafeToReferenceAfterResize(From, 0);
191 this->assertSafeToReferenceAfterResize(To - 1, 0);
192 }
193 template <
194 class ItTy,
195 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value,
196 bool> = false>
197 void assertSafeToReferenceAfterClear(ItTy, ItTy) {}
198
199 /// Check whether any part of the range will be invalidated by growing.
200 void assertSafeToAddRange(const T *From, const T *To) {
201 if (From == To)
202 return;
203 this->assertSafeToAdd(From, To - From);
204 this->assertSafeToAdd(To - 1, To - From);
205 }
206 template <
207 class ItTy,
208 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value,
209 bool> = false>
210 void assertSafeToAddRange(ItTy, ItTy) {}
211
212 /// Reserve enough space to add one element, and return the updated element
213 /// pointer in case it was a reference to the storage.
214 template <class U>
215 static const T *reserveForParamAndGetAddressImpl(U *This, const T &Elt,
216 size_t N) {
217 size_t NewSize = This->size() + N;
218 if (LLVM_LIKELY(NewSize <= This->capacity())__builtin_expect((bool)(NewSize <= This->capacity()), true
)
)
219 return &Elt;
220
221 bool ReferencesStorage = false;
222 int64_t Index = -1;
223 if (!U::TakesParamByValue) {
224 if (LLVM_UNLIKELY(This->isReferenceToStorage(&Elt))__builtin_expect((bool)(This->isReferenceToStorage(&Elt
)), false)
) {
225 ReferencesStorage = true;
226 Index = &Elt - This->begin();
227 }
228 }
229 This->grow(NewSize);
230 return ReferencesStorage ? This->begin() + Index : &Elt;
231 }
232
233public:
234 using size_type = size_t;
235 using difference_type = ptrdiff_t;
236 using value_type = T;
237 using iterator = T *;
238 using const_iterator = const T *;
239
240 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
241 using reverse_iterator = std::reverse_iterator<iterator>;
242
243 using reference = T &;
244 using const_reference = const T &;
245 using pointer = T *;
246 using const_pointer = const T *;
247
248 using Base::capacity;
249 using Base::empty;
250 using Base::size;
251
252 // forward iterator creation methods.
253 iterator begin() { return (iterator)this->BeginX; }
254 const_iterator begin() const { return (const_iterator)this->BeginX; }
255 iterator end() { return begin() + size(); }
256 const_iterator end() const { return begin() + size(); }
257
258 // reverse iterator creation methods.
259 reverse_iterator rbegin() { return reverse_iterator(end()); }
260 const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
261 reverse_iterator rend() { return reverse_iterator(begin()); }
262 const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
263
264 size_type size_in_bytes() const { return size() * sizeof(T); }
265 size_type max_size() const {
266 return std::min(this->SizeTypeMax(), size_type(-1) / sizeof(T));
267 }
268
269 size_t capacity_in_bytes() const { return capacity() * sizeof(T); }
270
271 /// Return a pointer to the vector's buffer, even if empty().
272 pointer data() { return pointer(begin()); }
273 /// Return a pointer to the vector's buffer, even if empty().
274 const_pointer data() const { return const_pointer(begin()); }
275
276 reference operator[](size_type idx) {
277 assert(idx < size())(static_cast<void> (0));
278 return begin()[idx];
279 }
280 const_reference operator[](size_type idx) const {
281 assert(idx < size())(static_cast<void> (0));
282 return begin()[idx];
283 }
284
285 reference front() {
286 assert(!empty())(static_cast<void> (0));
287 return begin()[0];
288 }
289 const_reference front() const {
290 assert(!empty())(static_cast<void> (0));
291 return begin()[0];
292 }
293
294 reference back() {
295 assert(!empty())(static_cast<void> (0));
296 return end()[-1];
297 }
298 const_reference back() const {
299 assert(!empty())(static_cast<void> (0));
300 return end()[-1];
301 }
302};
303
304/// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put
305/// method implementations that are designed to work with non-trivial T's.
306///
307/// We approximate is_trivially_copyable with trivial move/copy construction and
308/// trivial destruction. While the standard doesn't specify that you're allowed
309/// copy these types with memcpy, there is no way for the type to observe this.
310/// This catches the important case of std::pair<POD, POD>, which is not
311/// trivially assignable.
312template <typename T, bool = (is_trivially_copy_constructible<T>::value) &&
313 (is_trivially_move_constructible<T>::value) &&
314 std::is_trivially_destructible<T>::value>
315class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
316 friend class SmallVectorTemplateCommon<T>;
317
318protected:
319 static constexpr bool TakesParamByValue = false;
320 using ValueParamT = const T &;
321
322 SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
323
324 static void destroy_range(T *S, T *E) {
325 while (S != E) {
326 --E;
327 E->~T();
328 }
329 }
330
331 /// Move the range [I, E) into the uninitialized memory starting with "Dest",
332 /// constructing elements as needed.
333 template<typename It1, typename It2>
334 static void uninitialized_move(It1 I, It1 E, It2 Dest) {
335 std::uninitialized_copy(std::make_move_iterator(I),
336 std::make_move_iterator(E), Dest);
337 }
338
339 /// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
340 /// constructing elements as needed.
341 template<typename It1, typename It2>
342 static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
343 std::uninitialized_copy(I, E, Dest);
344 }
345
346 /// Grow the allocated memory (without initializing new elements), doubling
347 /// the size of the allocated memory. Guarantees space for at least one more
348 /// element, or MinSize more elements if specified.
349 void grow(size_t MinSize = 0);
350
351 /// Create a new allocation big enough for \p MinSize and pass back its size
352 /// in \p NewCapacity. This is the first section of \a grow().
353 T *mallocForGrow(size_t MinSize, size_t &NewCapacity) {
354 return static_cast<T *>(
355 SmallVectorBase<SmallVectorSizeType<T>>::mallocForGrow(
356 MinSize, sizeof(T), NewCapacity));
357 }
358
359 /// Move existing elements over to the new allocation \p NewElts, the middle
360 /// section of \a grow().
361 void moveElementsForGrow(T *NewElts);
362
363 /// Transfer ownership of the allocation, finishing up \a grow().
364 void takeAllocationForGrow(T *NewElts, size_t NewCapacity);
365
366 /// Reserve enough space to add one element, and return the updated element
367 /// pointer in case it was a reference to the storage.
368 const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) {
369 return this->reserveForParamAndGetAddressImpl(this, Elt, N);
370 }
371
372 /// Reserve enough space to add one element, and return the updated element
373 /// pointer in case it was a reference to the storage.
374 T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) {
375 return const_cast<T *>(
376 this->reserveForParamAndGetAddressImpl(this, Elt, N));
377 }
378
379 static T &&forward_value_param(T &&V) { return std::move(V); }
380 static const T &forward_value_param(const T &V) { return V; }
381
382 void growAndAssign(size_t NumElts, const T &Elt) {
383 // Grow manually in case Elt is an internal reference.
384 size_t NewCapacity;
385 T *NewElts = mallocForGrow(NumElts, NewCapacity);
386 std::uninitialized_fill_n(NewElts, NumElts, Elt);
387 this->destroy_range(this->begin(), this->end());
388 takeAllocationForGrow(NewElts, NewCapacity);
389 this->set_size(NumElts);
390 }
391
392 template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) {
393 // Grow manually in case one of Args is an internal reference.
394 size_t NewCapacity;
395 T *NewElts = mallocForGrow(0, NewCapacity);
396 ::new ((void *)(NewElts + this->size())) T(std::forward<ArgTypes>(Args)...);
397 moveElementsForGrow(NewElts);
398 takeAllocationForGrow(NewElts, NewCapacity);
399 this->set_size(this->size() + 1);
400 return this->back();
401 }
402
403public:
404 void push_back(const T &Elt) {
405 const T *EltPtr = reserveForParamAndGetAddress(Elt);
406 ::new ((void *)this->end()) T(*EltPtr);
407 this->set_size(this->size() + 1);
408 }
409
410 void push_back(T &&Elt) {
411 T *EltPtr = reserveForParamAndGetAddress(Elt);
412 ::new ((void *)this->end()) T(::std::move(*EltPtr));
413 this->set_size(this->size() + 1);
414 }
415
416 void pop_back() {
417 this->set_size(this->size() - 1);
418 this->end()->~T();
419 }
420};
421
422// Define this out-of-line to dissuade the C++ compiler from inlining it.
423template <typename T, bool TriviallyCopyable>
424void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) {
425 size_t NewCapacity;
426 T *NewElts = mallocForGrow(MinSize, NewCapacity);
427 moveElementsForGrow(NewElts);
428 takeAllocationForGrow(NewElts, NewCapacity);
429}
430
431// Define this out-of-line to dissuade the C++ compiler from inlining it.
432template <typename T, bool TriviallyCopyable>
433void SmallVectorTemplateBase<T, TriviallyCopyable>::moveElementsForGrow(
434 T *NewElts) {
435 // Move the elements over.
436 this->uninitialized_move(this->begin(), this->end(), NewElts);
437
438 // Destroy the original elements.
439 destroy_range(this->begin(), this->end());
440}
441
442// Define this out-of-line to dissuade the C++ compiler from inlining it.
443template <typename T, bool TriviallyCopyable>
444void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow(
445 T *NewElts, size_t NewCapacity) {
446 // If this wasn't grown from the inline copy, deallocate the old space.
447 if (!this->isSmall())
448 free(this->begin());
449
450 this->BeginX = NewElts;
451 this->Capacity = NewCapacity;
452}
453
454/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
455/// method implementations that are designed to work with trivially copyable
456/// T's. This allows using memcpy in place of copy/move construction and
457/// skipping destruction.
458template <typename T>
459class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
460 friend class SmallVectorTemplateCommon<T>;
461
462protected:
463 /// True if it's cheap enough to take parameters by value. Doing so avoids
464 /// overhead related to mitigations for reference invalidation.
465 static constexpr bool TakesParamByValue = sizeof(T) <= 2 * sizeof(void *);
466
467 /// Either const T& or T, depending on whether it's cheap enough to take
468 /// parameters by value.
469 using ValueParamT =
470 typename std::conditional<TakesParamByValue, T, const T &>::type;
471
472 SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
473
474 // No need to do a destroy loop for POD's.
475 static void destroy_range(T *, T *) {}
476
477 /// Move the range [I, E) onto the uninitialized memory
478 /// starting with "Dest", constructing elements into it as needed.
479 template<typename It1, typename It2>
480 static void uninitialized_move(It1 I, It1 E, It2 Dest) {
481 // Just do a copy.
482 uninitialized_copy(I, E, Dest);
483 }
484
485 /// Copy the range [I, E) onto the uninitialized memory
486 /// starting with "Dest", constructing elements into it as needed.
487 template<typename It1, typename It2>
488 static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
489 // Arbitrary iterator types; just use the basic implementation.
490 std::uninitialized_copy(I, E, Dest);
491 }
492
493 /// Copy the range [I, E) onto the uninitialized memory
494 /// starting with "Dest", constructing elements into it as needed.
495 template <typename T1, typename T2>
496 static void uninitialized_copy(
497 T1 *I, T1 *E, T2 *Dest,
498 std::enable_if_t<std::is_same<typename std::remove_const<T1>::type,
499 T2>::value> * = nullptr) {
500 // Use memcpy for PODs iterated by pointers (which includes SmallVector
501 // iterators): std::uninitialized_copy optimizes to memmove, but we can
502 // use memcpy here. Note that I and E are iterators and thus might be
503 // invalid for memcpy if they are equal.
504 if (I != E)
505 memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T));
506 }
507
508 /// Double the size of the allocated memory, guaranteeing space for at
509 /// least one more element or MinSize if specified.
510 void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); }
511
512 /// Reserve enough space to add one element, and return the updated element
513 /// pointer in case it was a reference to the storage.
514 const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) {
515 return this->reserveForParamAndGetAddressImpl(this, Elt, N);
516 }
517
518 /// Reserve enough space to add one element, and return the updated element
519 /// pointer in case it was a reference to the storage.
520 T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) {
521 return const_cast<T *>(
522 this->reserveForParamAndGetAddressImpl(this, Elt, N));
523 }
524
525 /// Copy \p V or return a reference, depending on \a ValueParamT.
526 static ValueParamT forward_value_param(ValueParamT V) { return V; }
527
528 void growAndAssign(size_t NumElts, T Elt) {
529 // Elt has been copied in case it's an internal reference, side-stepping
530 // reference invalidation problems without losing the realloc optimization.
531 this->set_size(0);
532 this->grow(NumElts);
533 std::uninitialized_fill_n(this->begin(), NumElts, Elt);
534 this->set_size(NumElts);
535 }
536
537 template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) {
538 // Use push_back with a copy in case Args has an internal reference,
539 // side-stepping reference invalidation problems without losing the realloc
540 // optimization.
541 push_back(T(std::forward<ArgTypes>(Args)...));
542 return this->back();
543 }
544
545public:
546 void push_back(ValueParamT Elt) {
547 const T *EltPtr = reserveForParamAndGetAddress(Elt);
548 memcpy(reinterpret_cast<void *>(this->end()), EltPtr, sizeof(T));
549 this->set_size(this->size() + 1);
550 }
551
552 void pop_back() { this->set_size(this->size() - 1); }
553};
554
555/// This class consists of common code factored out of the SmallVector class to
556/// reduce code duplication based on the SmallVector 'N' template parameter.
557template <typename T>
558class SmallVectorImpl : public SmallVectorTemplateBase<T> {
559 using SuperClass = SmallVectorTemplateBase<T>;
560
561public:
562 using iterator = typename SuperClass::iterator;
563 using const_iterator = typename SuperClass::const_iterator;
564 using reference = typename SuperClass::reference;
565 using size_type = typename SuperClass::size_type;
566
567protected:
568 using SmallVectorTemplateBase<T>::TakesParamByValue;
569 using ValueParamT = typename SuperClass::ValueParamT;
570
571 // Default ctor - Initialize to empty.
572 explicit SmallVectorImpl(unsigned N)
573 : SmallVectorTemplateBase<T>(N) {}
574
575public:
576 SmallVectorImpl(const SmallVectorImpl &) = delete;
577
578 ~SmallVectorImpl() {
579 // Subclass has already destructed this vector's elements.
580 // If this wasn't grown from the inline copy, deallocate the old space.
581 if (!this->isSmall())
582 free(this->begin());
583 }
584
585 void clear() {
586 this->destroy_range(this->begin(), this->end());
587 this->Size = 0;
588 }
589
590private:
591 template <bool ForOverwrite> void resizeImpl(size_type N) {
592 if (N < this->size()) {
593 this->pop_back_n(this->size() - N);
594 } else if (N > this->size()) {
595 this->reserve(N);
596 for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
597 if (ForOverwrite)
598 new (&*I) T;
599 else
600 new (&*I) T();
601 this->set_size(N);
602 }
603 }
604
605public:
606 void resize(size_type N) { resizeImpl<false>(N); }
607
608 /// Like resize, but \ref T is POD, the new values won't be initialized.
609 void resize_for_overwrite(size_type N) { resizeImpl<true>(N); }
610
611 void resize(size_type N, ValueParamT NV) {
612 if (N == this->size())
613 return;
614
615 if (N < this->size()) {
616 this->pop_back_n(this->size() - N);
617 return;
618 }
619
620 // N > this->size(). Defer to append.
621 this->append(N - this->size(), NV);
622 }
623
624 void reserve(size_type N) {
625 if (this->capacity() < N)
626 this->grow(N);
627 }
628
629 void pop_back_n(size_type NumItems) {
630 assert(this->size() >= NumItems)(static_cast<void> (0));
631 this->destroy_range(this->end() - NumItems, this->end());
632 this->set_size(this->size() - NumItems);
633 }
634
635 LLVM_NODISCARD[[clang::warn_unused_result]] T pop_back_val() {
636 T Result = ::std::move(this->back());
637 this->pop_back();
638 return Result;
639 }
640
641 void swap(SmallVectorImpl &RHS);
642
643 /// Add the specified range to the end of the SmallVector.
644 template <typename in_iter,
645 typename = std::enable_if_t<std::is_convertible<
646 typename std::iterator_traits<in_iter>::iterator_category,
647 std::input_iterator_tag>::value>>
648 void append(in_iter in_start, in_iter in_end) {
649 this->assertSafeToAddRange(in_start, in_end);
650 size_type NumInputs = std::distance(in_start, in_end);
651 this->reserve(this->size() + NumInputs);
652 this->uninitialized_copy(in_start, in_end, this->end());
653 this->set_size(this->size() + NumInputs);
654 }
655
656 /// Append \p NumInputs copies of \p Elt to the end.
657 void append(size_type NumInputs, ValueParamT Elt) {
658 const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumInputs);
659 std::uninitialized_fill_n(this->end(), NumInputs, *EltPtr);
660 this->set_size(this->size() + NumInputs);
661 }
662
663 void append(std::initializer_list<T> IL) {
664 append(IL.begin(), IL.end());
665 }
666
667 void append(const SmallVectorImpl &RHS) { append(RHS.begin(), RHS.end()); }
668
669 void assign(size_type NumElts, ValueParamT Elt) {
670 // Note that Elt could be an internal reference.
671 if (NumElts > this->capacity()) {
672 this->growAndAssign(NumElts, Elt);
673 return;
674 }
675
676 // Assign over existing elements.
677 std::fill_n(this->begin(), std::min(NumElts, this->size()), Elt);
678 if (NumElts > this->size())
679 std::uninitialized_fill_n(this->end(), NumElts - this->size(), Elt);
680 else if (NumElts < this->size())
681 this->destroy_range(this->begin() + NumElts, this->end());
682 this->set_size(NumElts);
683 }
684
685 // FIXME: Consider assigning over existing elements, rather than clearing &
686 // re-initializing them - for all assign(...) variants.
687
688 template <typename in_iter,
689 typename = std::enable_if_t<std::is_convertible<
690 typename std::iterator_traits<in_iter>::iterator_category,
691 std::input_iterator_tag>::value>>
692 void assign(in_iter in_start, in_iter in_end) {
693 this->assertSafeToReferenceAfterClear(in_start, in_end);
694 clear();
695 append(in_start, in_end);
696 }
697
698 void assign(std::initializer_list<T> IL) {
699 clear();
700 append(IL);
701 }
702
703 void assign(const SmallVectorImpl &RHS) { assign(RHS.begin(), RHS.end()); }
704
705 iterator erase(const_iterator CI) {
706 // Just cast away constness because this is a non-const member function.
707 iterator I = const_cast<iterator>(CI);
708
709 assert(this->isReferenceToStorage(CI) && "Iterator to erase is out of bounds.")(static_cast<void> (0));
710
711 iterator N = I;
712 // Shift all elts down one.
713 std::move(I+1, this->end(), I);
714 // Drop the last elt.
715 this->pop_back();
716 return(N);
717 }
718
719 iterator erase(const_iterator CS, const_iterator CE) {
720 // Just cast away constness because this is a non-const member function.
721 iterator S = const_cast<iterator>(CS);
722 iterator E = const_cast<iterator>(CE);
723
724 assert(this->isRangeInStorage(S, E) && "Range to erase is out of bounds.")(static_cast<void> (0));
725
726 iterator N = S;
727 // Shift all elts down.
728 iterator I = std::move(E, this->end(), S);
729 // Drop the last elts.
730 this->destroy_range(I, this->end());
731 this->set_size(I - this->begin());
732 return(N);
733 }
734
735private:
736 template <class ArgType> iterator insert_one_impl(iterator I, ArgType &&Elt) {
737 // Callers ensure that ArgType is derived from T.
738 static_assert(
739 std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>,
740 T>::value,
741 "ArgType must be derived from T!");
742
743 if (I == this->end()) { // Important special case for empty vector.
744 this->push_back(::std::forward<ArgType>(Elt));
745 return this->end()-1;
746 }
747
748 assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.")(static_cast<void> (0));
749
750 // Grow if necessary.
751 size_t Index = I - this->begin();
752 std::remove_reference_t<ArgType> *EltPtr =
753 this->reserveForParamAndGetAddress(Elt);
754 I = this->begin() + Index;
755
756 ::new ((void*) this->end()) T(::std::move(this->back()));
757 // Push everything else over.
758 std::move_backward(I, this->end()-1, this->end());
759 this->set_size(this->size() + 1);
760
761 // If we just moved the element we're inserting, be sure to update
762 // the reference (never happens if TakesParamByValue).
763 static_assert(!TakesParamByValue || std::is_same<ArgType, T>::value,
764 "ArgType must be 'T' when taking by value!");
765 if (!TakesParamByValue && this->isReferenceToRange(EltPtr, I, this->end()))
766 ++EltPtr;
767
768 *I = ::std::forward<ArgType>(*EltPtr);
769 return I;
770 }
771
772public:
773 iterator insert(iterator I, T &&Elt) {
774 return insert_one_impl(I, this->forward_value_param(std::move(Elt)));
775 }
776
777 iterator insert(iterator I, const T &Elt) {
778 return insert_one_impl(I, this->forward_value_param(Elt));
779 }
780
781 iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt) {
782 // Convert iterator to elt# to avoid invalidating iterator when we reserve()
783 size_t InsertElt = I - this->begin();
784
785 if (I == this->end()) { // Important special case for empty vector.
786 append(NumToInsert, Elt);
787 return this->begin()+InsertElt;
788 }
789
790 assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.")(static_cast<void> (0));
791
792 // Ensure there is enough space, and get the (maybe updated) address of
793 // Elt.
794 const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumToInsert);
795
796 // Uninvalidate the iterator.
797 I = this->begin()+InsertElt;
798
799 // If there are more elements between the insertion point and the end of the
800 // range than there are being inserted, we can use a simple approach to
801 // insertion. Since we already reserved space, we know that this won't
802 // reallocate the vector.
803 if (size_t(this->end()-I) >= NumToInsert) {
804 T *OldEnd = this->end();
805 append(std::move_iterator<iterator>(this->end() - NumToInsert),
806 std::move_iterator<iterator>(this->end()));
807
808 // Copy the existing elements that get replaced.
809 std::move_backward(I, OldEnd-NumToInsert, OldEnd);
810
811 // If we just moved the element we're inserting, be sure to update
812 // the reference (never happens if TakesParamByValue).
813 if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
814 EltPtr += NumToInsert;
815
816 std::fill_n(I, NumToInsert, *EltPtr);
817 return I;
818 }
819
820 // Otherwise, we're inserting more elements than exist already, and we're
821 // not inserting at the end.
822
823 // Move over the elements that we're about to overwrite.
824 T *OldEnd = this->end();
825 this->set_size(this->size() + NumToInsert);
826 size_t NumOverwritten = OldEnd-I;
827 this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
828
829 // If we just moved the element we're inserting, be sure to update
830 // the reference (never happens if TakesParamByValue).
831 if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
832 EltPtr += NumToInsert;
833
834 // Replace the overwritten part.
835 std::fill_n(I, NumOverwritten, *EltPtr);
836
837 // Insert the non-overwritten middle part.
838 std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr);
839 return I;
840 }
841
842 template <typename ItTy,
843 typename = std::enable_if_t<std::is_convertible<
844 typename std::iterator_traits<ItTy>::iterator_category,
845 std::input_iterator_tag>::value>>
846 iterator insert(iterator I, ItTy From, ItTy To) {
847 // Convert iterator to elt# to avoid invalidating iterator when we reserve()
848 size_t InsertElt = I - this->begin();
849
850 if (I == this->end()) { // Important special case for empty vector.
851 append(From, To);
852 return this->begin()+InsertElt;
853 }
854
855 assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.")(static_cast<void> (0));
856
857 // Check that the reserve that follows doesn't invalidate the iterators.
858 this->assertSafeToAddRange(From, To);
859
860 size_t NumToInsert = std::distance(From, To);
861
862 // Ensure there is enough space.
863 reserve(this->size() + NumToInsert);
864
865 // Uninvalidate the iterator.
866 I = this->begin()+InsertElt;
867
868 // If there are more elements between the insertion point and the end of the
869 // range than there are being inserted, we can use a simple approach to
870 // insertion. Since we already reserved space, we know that this won't
871 // reallocate the vector.
872 if (size_t(this->end()-I) >= NumToInsert) {
873 T *OldEnd = this->end();
874 append(std::move_iterator<iterator>(this->end() - NumToInsert),
875 std::move_iterator<iterator>(this->end()));
876
877 // Copy the existing elements that get replaced.
878 std::move_backward(I, OldEnd-NumToInsert, OldEnd);
879
880 std::copy(From, To, I);
881 return I;
882 }
883
884 // Otherwise, we're inserting more elements than exist already, and we're
885 // not inserting at the end.
886
887 // Move over the elements that we're about to overwrite.
888 T *OldEnd = this->end();
889 this->set_size(this->size() + NumToInsert);
890 size_t NumOverwritten = OldEnd-I;
891 this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
892
893 // Replace the overwritten part.
894 for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
895 *J = *From;
896 ++J; ++From;
897 }
898
899 // Insert the non-overwritten middle part.
900 this->uninitialized_copy(From, To, OldEnd);
901 return I;
902 }
903
904 void insert(iterator I, std::initializer_list<T> IL) {
905 insert(I, IL.begin(), IL.end());
906 }
907
908 template <typename... ArgTypes> reference emplace_back(ArgTypes &&... Args) {
909 if (LLVM_UNLIKELY(this->size() >= this->capacity())__builtin_expect((bool)(this->size() >= this->capacity
()), false)
)
910 return this->growAndEmplaceBack(std::forward<ArgTypes>(Args)...);
911
912 ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
913 this->set_size(this->size() + 1);
914 return this->back();
915 }
916
917 SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
918
919 SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
920
921 bool operator==(const SmallVectorImpl &RHS) const {
922 if (this->size() != RHS.size()) return false;
923 return std::equal(this->begin(), this->end(), RHS.begin());
924 }
925 bool operator!=(const SmallVectorImpl &RHS) const {
926 return !(*this == RHS);
927 }
928
929 bool operator<(const SmallVectorImpl &RHS) const {
930 return std::lexicographical_compare(this->begin(), this->end(),
931 RHS.begin(), RHS.end());
932 }
933};
934
935template <typename T>
936void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
937 if (this == &RHS) return;
938
939 // We can only avoid copying elements if neither vector is small.
940 if (!this->isSmall() && !RHS.isSmall()) {
941 std::swap(this->BeginX, RHS.BeginX);
942 std::swap(this->Size, RHS.Size);
943 std::swap(this->Capacity, RHS.Capacity);
944 return;
945 }
946 this->reserve(RHS.size());
947 RHS.reserve(this->size());
948
949 // Swap the shared elements.
950 size_t NumShared = this->size();
951 if (NumShared > RHS.size()) NumShared = RHS.size();
952 for (size_type i = 0; i != NumShared; ++i)
953 std::swap((*this)[i], RHS[i]);
954
955 // Copy over the extra elts.
956 if (this->size() > RHS.size()) {
957 size_t EltDiff = this->size() - RHS.size();
958 this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
959 RHS.set_size(RHS.size() + EltDiff);
960 this->destroy_range(this->begin()+NumShared, this->end());
961 this->set_size(NumShared);
962 } else if (RHS.size() > this->size()) {
963 size_t EltDiff = RHS.size() - this->size();
964 this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
965 this->set_size(this->size() + EltDiff);
966 this->destroy_range(RHS.begin()+NumShared, RHS.end());
967 RHS.set_size(NumShared);
968 }
969}
970
971template <typename T>
972SmallVectorImpl<T> &SmallVectorImpl<T>::
973 operator=(const SmallVectorImpl<T> &RHS) {
974 // Avoid self-assignment.
975 if (this == &RHS) return *this;
976
977 // If we already have sufficient space, assign the common elements, then
978 // destroy any excess.
979 size_t RHSSize = RHS.size();
980 size_t CurSize = this->size();
981 if (CurSize >= RHSSize) {
982 // Assign common elements.
983 iterator NewEnd;
984 if (RHSSize)
985 NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
986 else
987 NewEnd = this->begin();
988
989 // Destroy excess elements.
990 this->destroy_range(NewEnd, this->end());
991
992 // Trim.
993 this->set_size(RHSSize);
994 return *this;
995 }
996
997 // If we have to grow to have enough elements, destroy the current elements.
998 // This allows us to avoid copying them during the grow.
999 // FIXME: don't do this if they're efficiently moveable.
1000 if (this->capacity() < RHSSize) {
1001 // Destroy current elements.
1002 this->clear();
1003 CurSize = 0;
1004 this->grow(RHSSize);
1005 } else if (CurSize) {
1006 // Otherwise, use assignment for the already-constructed elements.
1007 std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
1008 }
1009
1010 // Copy construct the new elements in place.
1011 this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
1012 this->begin()+CurSize);
1013
1014 // Set end.
1015 this->set_size(RHSSize);
1016 return *this;
1017}
1018
1019template <typename T>
1020SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
1021 // Avoid self-assignment.
1022 if (this == &RHS) return *this;
1023
1024 // If the RHS isn't small, clear this vector and then steal its buffer.
1025 if (!RHS.isSmall()) {
1026 this->destroy_range(this->begin(), this->end());
1027 if (!this->isSmall()) free(this->begin());
1028 this->BeginX = RHS.BeginX;
1029 this->Size = RHS.Size;
1030 this->Capacity = RHS.Capacity;
1031 RHS.resetToSmall();
1032 return *this;
1033 }
1034
1035 // If we already have sufficient space, assign the common elements, then
1036 // destroy any excess.
1037 size_t RHSSize = RHS.size();
1038 size_t CurSize = this->size();
1039 if (CurSize >= RHSSize) {
1040 // Assign common elements.
1041 iterator NewEnd = this->begin();
1042 if (RHSSize)
1043 NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
1044
1045 // Destroy excess elements and trim the bounds.
1046 this->destroy_range(NewEnd, this->end());
1047 this->set_size(RHSSize);
1048
1049 // Clear the RHS.
1050 RHS.clear();
1051
1052 return *this;
1053 }
1054
1055 // If we have to grow to have enough elements, destroy the current elements.
1056 // This allows us to avoid copying them during the grow.
1057 // FIXME: this may not actually make any sense if we can efficiently move
1058 // elements.
1059 if (this->capacity() < RHSSize) {
1060 // Destroy current elements.
1061 this->clear();
1062 CurSize = 0;
1063 this->grow(RHSSize);
1064 } else if (CurSize) {
1065 // Otherwise, use assignment for the already-constructed elements.
1066 std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
1067 }
1068
1069 // Move-construct the new elements in place.
1070 this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
1071 this->begin()+CurSize);
1072
1073 // Set end.
1074 this->set_size(RHSSize);
1075
1076 RHS.clear();
1077 return *this;
1078}
1079
1080/// Storage for the SmallVector elements. This is specialized for the N=0 case
1081/// to avoid allocating unnecessary storage.
1082template <typename T, unsigned N>
1083struct SmallVectorStorage {
1084 alignas(T) char InlineElts[N * sizeof(T)];
1085};
1086
1087/// We need the storage to be properly aligned even for small-size of 0 so that
1088/// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is
1089/// well-defined.
1090template <typename T> struct alignas(T) SmallVectorStorage<T, 0> {};
1091
1092/// Forward declaration of SmallVector so that
1093/// calculateSmallVectorDefaultInlinedElements can reference
1094/// `sizeof(SmallVector<T, 0>)`.
1095template <typename T, unsigned N> class LLVM_GSL_OWNER[[gsl::Owner]] SmallVector;
1096
1097/// Helper class for calculating the default number of inline elements for
1098/// `SmallVector<T>`.
1099///
1100/// This should be migrated to a constexpr function when our minimum
1101/// compiler support is enough for multi-statement constexpr functions.
1102template <typename T> struct CalculateSmallVectorDefaultInlinedElements {
1103 // Parameter controlling the default number of inlined elements
1104 // for `SmallVector<T>`.
1105 //
1106 // The default number of inlined elements ensures that
1107 // 1. There is at least one inlined element.
1108 // 2. `sizeof(SmallVector<T>) <= kPreferredSmallVectorSizeof` unless
1109 // it contradicts 1.
1110 static constexpr size_t kPreferredSmallVectorSizeof = 64;
1111
1112 // static_assert that sizeof(T) is not "too big".
1113 //
1114 // Because our policy guarantees at least one inlined element, it is possible
1115 // for an arbitrarily large inlined element to allocate an arbitrarily large
1116 // amount of inline storage. We generally consider it an antipattern for a
1117 // SmallVector to allocate an excessive amount of inline storage, so we want
1118 // to call attention to these cases and make sure that users are making an
1119 // intentional decision if they request a lot of inline storage.
1120 //
1121 // We want this assertion to trigger in pathological cases, but otherwise
1122 // not be too easy to hit. To accomplish that, the cutoff is actually somewhat
1123 // larger than kPreferredSmallVectorSizeof (otherwise,
1124 // `SmallVector<SmallVector<T>>` would be one easy way to trip it, and that
1125 // pattern seems useful in practice).
1126 //
1127 // One wrinkle is that this assertion is in theory non-portable, since
1128 // sizeof(T) is in general platform-dependent. However, we don't expect this
1129 // to be much of an issue, because most LLVM development happens on 64-bit
1130 // hosts, and therefore sizeof(T) is expected to *decrease* when compiled for
1131 // 32-bit hosts, dodging the issue. The reverse situation, where development
1132 // happens on a 32-bit host and then fails due to sizeof(T) *increasing* on a
1133 // 64-bit host, is expected to be very rare.
1134 static_assert(
1135 sizeof(T) <= 256,
1136 "You are trying to use a default number of inlined elements for "
1137 "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
1138 "explicit number of inlined elements with `SmallVector<T, N>` to make "
1139 "sure you really want that much inline storage.");
1140
1141 // Discount the size of the header itself when calculating the maximum inline
1142 // bytes.
1143 static constexpr size_t PreferredInlineBytes =
1144 kPreferredSmallVectorSizeof - sizeof(SmallVector<T, 0>);
1145 static constexpr size_t NumElementsThatFit = PreferredInlineBytes / sizeof(T);
1146 static constexpr size_t value =
1147 NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
1148};
1149
1150/// This is a 'vector' (really, a variable-sized array), optimized
1151/// for the case when the array is small. It contains some number of elements
1152/// in-place, which allows it to avoid heap allocation when the actual number of
1153/// elements is below that threshold. This allows normal "small" cases to be
1154/// fast without losing generality for large inputs.
1155///
1156/// \note
1157/// In the absence of a well-motivated choice for the number of inlined
1158/// elements \p N, it is recommended to use \c SmallVector<T> (that is,
1159/// omitting the \p N). This will choose a default number of inlined elements
1160/// reasonable for allocation on the stack (for example, trying to keep \c
1161/// sizeof(SmallVector<T>) around 64 bytes).
1162///
1163/// \warning This does not attempt to be exception safe.
1164///
1165/// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h
1166template <typename T,
1167 unsigned N = CalculateSmallVectorDefaultInlinedElements<T>::value>
1168class LLVM_GSL_OWNER[[gsl::Owner]] SmallVector : public SmallVectorImpl<T>,
1169 SmallVectorStorage<T, N> {
1170public:
1171 SmallVector() : SmallVectorImpl<T>(N) {}
1172
1173 ~SmallVector() {
1174 // Destroy the constructed elements in the vector.
1175 this->destroy_range(this->begin(), this->end());
1176 }
1177
1178 explicit SmallVector(size_t Size, const T &Value = T())
1179 : SmallVectorImpl<T>(N) {
1180 this->assign(Size, Value);
1181 }
1182
1183 template <typename ItTy,
1184 typename = std::enable_if_t<std::is_convertible<
1185 typename std::iterator_traits<ItTy>::iterator_category,
1186 std::input_iterator_tag>::value>>
1187 SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
1188 this->append(S, E);
1189 }
1190
1191 template <typename RangeTy>
1192 explicit SmallVector(const iterator_range<RangeTy> &R)
1193 : SmallVectorImpl<T>(N) {
1194 this->append(R.begin(), R.end());
1195 }
1196
1197 SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
1198 this->assign(IL);
1199 }
1200
1201 SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
1202 if (!RHS.empty())
1203 SmallVectorImpl<T>::operator=(RHS);
1204 }
1205
1206 SmallVector &operator=(const SmallVector &RHS) {
1207 SmallVectorImpl<T>::operator=(RHS);
1208 return *this;
1209 }
1210
1211 SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) {
1212 if (!RHS.empty())
1213 SmallVectorImpl<T>::operator=(::std::move(RHS));
1214 }
1215
1216 SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
1217 if (!RHS.empty())
1218 SmallVectorImpl<T>::operator=(::std::move(RHS));
1219 }
1220
1221 SmallVector &operator=(SmallVector &&RHS) {
1222 SmallVectorImpl<T>::operator=(::std::move(RHS));
1223 return *this;
1224 }
1225
1226 SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
1227 SmallVectorImpl<T>::operator=(::std::move(RHS));
1228 return *this;
1229 }
1230
1231 SmallVector &operator=(std::initializer_list<T> IL) {
1232 this->assign(IL);
1233 return *this;
1234 }
1235};
1236
1237template <typename T, unsigned N>
1238inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
1239 return X.capacity_in_bytes();
1240}
1241
1242/// Given a range of type R, iterate the entire range and return a
1243/// SmallVector with elements of the vector. This is useful, for example,
1244/// when you want to iterate a range and then sort the results.
1245template <unsigned Size, typename R>
1246SmallVector<typename std::remove_const<typename std::remove_reference<
1247 decltype(*std::begin(std::declval<R &>()))>::type>::type,
1248 Size>
1249to_vector(R &&Range) {
1250 return {std::begin(Range), std::end(Range)};
1251}
1252
1253} // end namespace llvm
1254
1255namespace std {
1256
1257 /// Implement std::swap in terms of SmallVector swap.
1258 template<typename T>
1259 inline void
1260 swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) {
1261 LHS.swap(RHS);
1262 }
1263
1264 /// Implement std::swap in terms of SmallVector swap.
1265 template<typename T, unsigned N>
1266 inline void
1267 swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) {
1268 LHS.swap(RHS);
1269 }
1270
1271} // end namespace std
1272
1273#endif // LLVM_ADT_SMALLVECTOR_H