xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Diagnostic.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/DiagnosticDriver.h"
16 #include "clang/Basic/DiagnosticError.h"
17 #include "clang/Basic/DiagnosticFrontend.h"
18 #include "clang/Basic/DiagnosticIDs.h"
19 #include "clang/Basic/DiagnosticOptions.h"
20 #include "clang/Basic/IdentifierTable.h"
21 #include "clang/Basic/SourceLocation.h"
22 #include "clang/Basic/SourceManager.h"
23 #include "clang/Basic/Specifiers.h"
24 #include "clang/Basic/TokenKinds.h"
25 #include "llvm/ADT/IntrusiveRefCntPtr.h"
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/ADT/StringExtras.h"
28 #include "llvm/ADT/StringMap.h"
29 #include "llvm/ADT/StringRef.h"
30 #include "llvm/Support/ConvertUTF.h"
31 #include "llvm/Support/CrashRecoveryContext.h"
32 #include "llvm/Support/Error.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/SpecialCaseList.h"
35 #include "llvm/Support/Unicode.h"
36 #include "llvm/Support/VirtualFileSystem.h"
37 #include "llvm/Support/raw_ostream.h"
38 #include <algorithm>
39 #include <cassert>
40 #include <cstddef>
41 #include <cstdint>
42 #include <cstring>
43 #include <memory>
44 #include <string>
45 #include <utility>
46 #include <vector>
47 
48 using namespace clang;
49 
operator <<(const StreamingDiagnostic & DB,DiagNullabilityKind nullability)50 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
51                                              DiagNullabilityKind nullability) {
52   DB.AddString(
53       ("'" +
54        getNullabilitySpelling(nullability.first,
55                               /*isContextSensitive=*/nullability.second) +
56        "'")
57           .str());
58   return DB;
59 }
60 
operator <<(const StreamingDiagnostic & DB,llvm::Error && E)61 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
62                                              llvm::Error &&E) {
63   DB.AddString(toString(std::move(E)));
64   return DB;
65 }
66 
67 static void
DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK,intptr_t QT,StringRef Modifier,StringRef Argument,ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,SmallVectorImpl<char> & Output,void * Cookie,ArrayRef<intptr_t> QualTypeVals)68 DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
69                    StringRef Modifier, StringRef Argument,
70                    ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
71                    SmallVectorImpl<char> &Output, void *Cookie,
72                    ArrayRef<intptr_t> QualTypeVals) {
73   StringRef Str = "<can't format argument>";
74   Output.append(Str.begin(), Str.end());
75 }
76 
DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> diags,DiagnosticOptions & DiagOpts,DiagnosticConsumer * client,bool ShouldOwnClient)77 DiagnosticsEngine::DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> diags,
78                                      DiagnosticOptions &DiagOpts,
79                                      DiagnosticConsumer *client,
80                                      bool ShouldOwnClient)
81     : Diags(std::move(diags)), DiagOpts(DiagOpts) {
82   setClient(client, ShouldOwnClient);
83   ArgToStringFn = DummyArgToStringFn;
84 
85   Reset();
86 }
87 
~DiagnosticsEngine()88 DiagnosticsEngine::~DiagnosticsEngine() {
89   // If we own the diagnostic client, destroy it first so that it can access the
90   // engine from its destructor.
91   setClient(nullptr);
92 }
93 
dump() const94 void DiagnosticsEngine::dump() const { DiagStatesByLoc.dump(*SourceMgr); }
95 
dump(StringRef DiagName) const96 void DiagnosticsEngine::dump(StringRef DiagName) const {
97   DiagStatesByLoc.dump(*SourceMgr, DiagName);
98 }
99 
setClient(DiagnosticConsumer * client,bool ShouldOwnClient)100 void DiagnosticsEngine::setClient(DiagnosticConsumer *client,
101                                   bool ShouldOwnClient) {
102   Owner.reset(ShouldOwnClient ? client : nullptr);
103   Client = client;
104 }
105 
pushMappings(SourceLocation Loc)106 void DiagnosticsEngine::pushMappings(SourceLocation Loc) {
107   DiagStateOnPushStack.push_back(GetCurDiagState());
108 }
109 
popMappings(SourceLocation Loc)110 bool DiagnosticsEngine::popMappings(SourceLocation Loc) {
111   if (DiagStateOnPushStack.empty())
112     return false;
113 
114   if (DiagStateOnPushStack.back() != GetCurDiagState()) {
115     // State changed at some point between push/pop.
116     PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
117   }
118   DiagStateOnPushStack.pop_back();
119   return true;
120 }
121 
ResetPragmas()122 void DiagnosticsEngine::ResetPragmas() { DiagStatesByLoc.clear(/*Soft=*/true); }
123 
Reset(bool soft)124 void DiagnosticsEngine::Reset(bool soft /*=false*/) {
125   ErrorOccurred = false;
126   UncompilableErrorOccurred = false;
127   FatalErrorOccurred = false;
128   UnrecoverableErrorOccurred = false;
129 
130   NumWarnings = 0;
131   NumErrors = 0;
132   TrapNumErrorsOccurred = 0;
133   TrapNumUnrecoverableErrorsOccurred = 0;
134 
135   LastDiagLevel = Ignored;
136 
137   if (!soft) {
138     // Clear state related to #pragma diagnostic.
139     DiagStates.clear();
140     DiagStatesByLoc.clear(false);
141     DiagStateOnPushStack.clear();
142 
143     // Create a DiagState and DiagStatePoint representing diagnostic changes
144     // through command-line.
145     DiagStates.emplace_back(*Diags);
146     DiagStatesByLoc.appendFirst(&DiagStates.back());
147   }
148 }
149 
150 DiagnosticMapping &
getOrAddMapping(diag::kind Diag)151 DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) {
152   std::pair<iterator, bool> Result = DiagMap.try_emplace(Diag);
153 
154   // Initialize the entry if we added it.
155   if (Result.second) {
156     Result.first->second = DiagIDs.getDefaultMapping(Diag);
157     if (DiagnosticIDs::IsCustomDiag(Diag))
158       DiagIDs.initCustomDiagMapping(Result.first->second, Diag);
159   }
160 
161   return Result.first->second;
162 }
163 
appendFirst(DiagState * State)164 void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
165   assert(Files.empty() && "not first");
166   FirstDiagState = CurDiagState = State;
167   CurDiagStateLoc = SourceLocation();
168 }
169 
append(SourceManager & SrcMgr,SourceLocation Loc,DiagState * State)170 void DiagnosticsEngine::DiagStateMap::append(SourceManager &SrcMgr,
171                                              SourceLocation Loc,
172                                              DiagState *State) {
173   CurDiagState = State;
174   CurDiagStateLoc = Loc;
175 
176   FileIDAndOffset Decomp = SrcMgr.getDecomposedLoc(Loc);
177   unsigned Offset = Decomp.second;
178   for (File *F = getFile(SrcMgr, Decomp.first); F;
179        Offset = F->ParentOffset, F = F->Parent) {
180     F->HasLocalTransitions = true;
181     auto &Last = F->StateTransitions.back();
182     assert(Last.Offset <= Offset && "state transitions added out of order");
183 
184     if (Last.Offset == Offset) {
185       if (Last.State == State)
186         break;
187       Last.State = State;
188       continue;
189     }
190 
191     F->StateTransitions.push_back({State, Offset});
192   }
193 }
194 
195 DiagnosticsEngine::DiagState *
lookup(SourceManager & SrcMgr,SourceLocation Loc) const196 DiagnosticsEngine::DiagStateMap::lookup(SourceManager &SrcMgr,
197                                         SourceLocation Loc) const {
198   // Common case: we have not seen any diagnostic pragmas.
199   if (Files.empty())
200     return FirstDiagState;
201 
202   FileIDAndOffset Decomp = SrcMgr.getDecomposedLoc(Loc);
203   const File *F = getFile(SrcMgr, Decomp.first);
204   return F->lookup(Decomp.second);
205 }
206 
207 DiagnosticsEngine::DiagState *
lookup(unsigned Offset) const208 DiagnosticsEngine::DiagStateMap::File::lookup(unsigned Offset) const {
209   auto OnePastIt =
210       llvm::partition_point(StateTransitions, [=](const DiagStatePoint &P) {
211         return P.Offset <= Offset;
212       });
213   assert(OnePastIt != StateTransitions.begin() && "missing initial state");
214   return OnePastIt[-1].State;
215 }
216 
217 DiagnosticsEngine::DiagStateMap::File *
getFile(SourceManager & SrcMgr,FileID ID) const218 DiagnosticsEngine::DiagStateMap::getFile(SourceManager &SrcMgr,
219                                          FileID ID) const {
220   // Get or insert the File for this ID.
221   auto Range = Files.equal_range(ID);
222   if (Range.first != Range.second)
223     return &Range.first->second;
224   auto &F = Files.insert(Range.first, std::make_pair(ID, File()))->second;
225 
226   // We created a new File; look up the diagnostic state at the start of it and
227   // initialize it.
228   if (ID.isValid()) {
229     FileIDAndOffset Decomp = SrcMgr.getDecomposedIncludedLoc(ID);
230     F.Parent = getFile(SrcMgr, Decomp.first);
231     F.ParentOffset = Decomp.second;
232     F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0});
233   } else {
234     // This is the (imaginary) root file into which we pretend all top-level
235     // files are included; it descends from the initial state.
236     //
237     // FIXME: This doesn't guarantee that we use the same ordering as
238     // isBeforeInTranslationUnit in the cases where someone invented another
239     // top-level file and added diagnostic pragmas to it. See the code at the
240     // end of isBeforeInTranslationUnit for the quirks it deals with.
241     F.StateTransitions.push_back({FirstDiagState, 0});
242   }
243   return &F;
244 }
245 
dump(SourceManager & SrcMgr,StringRef DiagName) const246 void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
247                                            StringRef DiagName) const {
248   llvm::errs() << "diagnostic state at ";
249   CurDiagStateLoc.print(llvm::errs(), SrcMgr);
250   llvm::errs() << ": " << CurDiagState << "\n";
251 
252   for (auto &F : Files) {
253     FileID ID = F.first;
254     File &File = F.second;
255 
256     bool PrintedOuterHeading = false;
257     auto PrintOuterHeading = [&] {
258       if (PrintedOuterHeading)
259         return;
260       PrintedOuterHeading = true;
261 
262       llvm::errs() << "File " << &File << " <FileID " << ID.getHashValue()
263                    << ">: " << SrcMgr.getBufferOrFake(ID).getBufferIdentifier();
264 
265       if (F.second.Parent) {
266         FileIDAndOffset Decomp = SrcMgr.getDecomposedIncludedLoc(ID);
267         assert(File.ParentOffset == Decomp.second);
268         llvm::errs() << " parent " << File.Parent << " <FileID "
269                      << Decomp.first.getHashValue() << "> ";
270         SrcMgr.getLocForStartOfFile(Decomp.first)
271             .getLocWithOffset(Decomp.second)
272             .print(llvm::errs(), SrcMgr);
273       }
274       if (File.HasLocalTransitions)
275         llvm::errs() << " has_local_transitions";
276       llvm::errs() << "\n";
277     };
278 
279     if (DiagName.empty())
280       PrintOuterHeading();
281 
282     for (DiagStatePoint &Transition : File.StateTransitions) {
283       bool PrintedInnerHeading = false;
284       auto PrintInnerHeading = [&] {
285         if (PrintedInnerHeading)
286           return;
287         PrintedInnerHeading = true;
288 
289         PrintOuterHeading();
290         llvm::errs() << "  ";
291         SrcMgr.getLocForStartOfFile(ID)
292             .getLocWithOffset(Transition.Offset)
293             .print(llvm::errs(), SrcMgr);
294         llvm::errs() << ": state " << Transition.State << ":\n";
295       };
296 
297       if (DiagName.empty())
298         PrintInnerHeading();
299 
300       for (auto &Mapping : *Transition.State) {
301         StringRef Option =
302             SrcMgr.getDiagnostics().Diags->getWarningOptionForDiag(
303                 Mapping.first);
304         if (!DiagName.empty() && DiagName != Option)
305           continue;
306 
307         PrintInnerHeading();
308         llvm::errs() << "    ";
309         if (Option.empty())
310           llvm::errs() << "<unknown " << Mapping.first << ">";
311         else
312           llvm::errs() << Option;
313         llvm::errs() << ": ";
314 
315         switch (Mapping.second.getSeverity()) {
316         case diag::Severity::Ignored:
317           llvm::errs() << "ignored";
318           break;
319         case diag::Severity::Remark:
320           llvm::errs() << "remark";
321           break;
322         case diag::Severity::Warning:
323           llvm::errs() << "warning";
324           break;
325         case diag::Severity::Error:
326           llvm::errs() << "error";
327           break;
328         case diag::Severity::Fatal:
329           llvm::errs() << "fatal";
330           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 
PushDiagStatePoint(DiagState * State,SourceLocation Loc)349 void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
350                                            SourceLocation Loc) {
351   assert(Loc.isValid() && "Adding invalid loc point");
352   DiagStatesByLoc.append(*SourceMgr, Loc, State);
353 }
354 
setSeverity(diag::kind Diag,diag::Severity Map,SourceLocation L)355 void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
356                                     SourceLocation L) {
357   assert((Diags->isWarningOrExtension(Diag) ||
358           (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) &&
359          "Cannot map errors into warnings!");
360   assert((L.isInvalid() || SourceMgr) && "No SourceMgr for valid location");
361 
362   // A command line -Wfoo has an invalid L and cannot override error/fatal
363   // mapping, while a warning pragma can.
364   bool WasUpgradedFromWarning = false;
365   if (Map == diag::Severity::Warning && L.isInvalid()) {
366     DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
367     if (Info.getSeverity() == diag::Severity::Error ||
368         Info.getSeverity() == diag::Severity::Fatal) {
369       Map = Info.getSeverity();
370       WasUpgradedFromWarning = true;
371     }
372   }
373   DiagnosticMapping Mapping = makeUserMapping(Map, L);
374   Mapping.setUpgradedFromWarning(WasUpgradedFromWarning);
375 
376   // Make sure we propagate the NoWarningAsError flag from an existing
377   // mapping (which may be the default mapping).
378   DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
379   Mapping.setNoWarningAsError(Info.hasNoWarningAsError() ||
380                               Mapping.hasNoWarningAsError());
381 
382   // Common case; setting all the diagnostics of a group in one place.
383   if ((L.isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
384       DiagStatesByLoc.getCurDiagState()) {
385     // FIXME: This is theoretically wrong: if the current state is shared with
386     // some other location (via push/pop) we will change the state for that
387     // other location as well. This cannot currently happen, as we can't update
388     // the diagnostic state at the same location at which we pop.
389     DiagStatesByLoc.getCurDiagState()->setMapping(Diag, Mapping);
390     return;
391   }
392 
393   // A diagnostic pragma occurred, create a new DiagState initialized with
394   // the current one and a new DiagStatePoint to record at which location
395   // the new state became active.
396   DiagStates.push_back(*GetCurDiagState());
397   DiagStates.back().setMapping(Diag, Mapping);
398   PushDiagStatePoint(&DiagStates.back(), L);
399 }
400 
setSeverityForGroup(diag::Flavor Flavor,StringRef Group,diag::Severity Map,SourceLocation Loc)401 bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
402                                             StringRef Group, diag::Severity Map,
403                                             SourceLocation Loc) {
404   // Get the diagnostics in this group.
405   SmallVector<diag::kind, 256> GroupDiags;
406   if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
407     return true;
408 
409   Diags->setGroupSeverity(Group, Map);
410 
411   // Set the mapping.
412   for (diag::kind Diag : GroupDiags)
413     setSeverity(Diag, Map, Loc);
414 
415   return false;
416 }
417 
setSeverityForGroup(diag::Flavor Flavor,diag::Group Group,diag::Severity Map,SourceLocation Loc)418 bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
419                                             diag::Group Group,
420                                             diag::Severity Map,
421                                             SourceLocation Loc) {
422   return setSeverityForGroup(Flavor, Diags->getWarningOptionForGroup(Group),
423                              Map, Loc);
424 }
425 
setDiagnosticGroupWarningAsError(StringRef Group,bool Enabled)426 bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
427                                                          bool Enabled) {
428   // If we are enabling this feature, just set the diagnostic mappings to map to
429   // errors.
430   if (Enabled)
431     return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
432                                diag::Severity::Error);
433   Diags->setGroupSeverity(Group, diag::Severity::Warning);
434 
435   // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
436   // potentially downgrade anything already mapped to be a warning.
437 
438   // Get the diagnostics in this group.
439   SmallVector<diag::kind, 8> GroupDiags;
440   if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
441                                    GroupDiags))
442     return true;
443 
444   // Perform the mapping change.
445   for (diag::kind Diag : GroupDiags) {
446     DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
447 
448     if (Info.getSeverity() == diag::Severity::Error ||
449         Info.getSeverity() == diag::Severity::Fatal)
450       Info.setSeverity(diag::Severity::Warning);
451 
452     Info.setNoWarningAsError(true);
453   }
454 
455   return false;
456 }
457 
setDiagnosticGroupErrorAsFatal(StringRef Group,bool Enabled)458 bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
459                                                        bool Enabled) {
460   // If we are enabling this feature, just set the diagnostic mappings to map to
461   // fatal errors.
462   if (Enabled)
463     return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
464                                diag::Severity::Fatal);
465   Diags->setGroupSeverity(Group, diag::Severity::Error);
466 
467   // Otherwise, we want to set the diagnostic mapping's "no Wfatal-errors" bit,
468   // and potentially downgrade anything already mapped to be a fatal error.
469 
470   // Get the diagnostics in this group.
471   SmallVector<diag::kind, 8> GroupDiags;
472   if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
473                                    GroupDiags))
474     return true;
475 
476   // Perform the mapping change.
477   for (diag::kind Diag : GroupDiags) {
478     DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
479 
480     if (Info.getSeverity() == diag::Severity::Fatal)
481       Info.setSeverity(diag::Severity::Error);
482 
483     Info.setNoErrorAsFatal(true);
484   }
485 
486   return false;
487 }
488 
setSeverityForAll(diag::Flavor Flavor,diag::Severity Map,SourceLocation Loc)489 void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
490                                           diag::Severity Map,
491                                           SourceLocation Loc) {
492   // Get all the diagnostics.
493   std::vector<diag::kind> AllDiags;
494   DiagnosticIDs::getAllDiagnostics(Flavor, AllDiags);
495 
496   // Set the mapping.
497   for (diag::kind Diag : AllDiags)
498     if (Diags->isWarningOrExtension(Diag))
499       setSeverity(Diag, Map, Loc);
500 }
501 
502 namespace {
503 // FIXME: We should isolate the parser from SpecialCaseList and just use it
504 // here.
505 class WarningsSpecialCaseList : public llvm::SpecialCaseList {
506 public:
507   static std::unique_ptr<WarningsSpecialCaseList>
508   create(const llvm::MemoryBuffer &Input, std::string &Err);
509 
510   // Section names refer to diagnostic groups, which cover multiple individual
511   // diagnostics. Expand diagnostic groups here to individual diagnostics.
512   // A diagnostic can have multiple diagnostic groups associated with it, we let
513   // the last section take precedence in such cases.
514   void processSections(DiagnosticsEngine &Diags);
515 
516   bool isDiagSuppressed(diag::kind DiagId, SourceLocation DiagLoc,
517                         const SourceManager &SM) const;
518 
519 private:
520   // Find the longest glob pattern that matches FilePath amongst
521   // CategoriesToMatchers, return true iff the match exists and belongs to a
522   // positive category.
523   bool globsMatches(const llvm::StringMap<Matcher> &CategoriesToMatchers,
524                     StringRef FilePath) const;
525 
526   llvm::DenseMap<diag::kind, const Section *> DiagToSection;
527 };
528 } // namespace
529 
530 std::unique_ptr<WarningsSpecialCaseList>
create(const llvm::MemoryBuffer & Input,std::string & Err)531 WarningsSpecialCaseList::create(const llvm::MemoryBuffer &Input,
532                                 std::string &Err) {
533   auto WarningSuppressionList = std::make_unique<WarningsSpecialCaseList>();
534   if (!WarningSuppressionList->createInternal(&Input, Err))
535     return nullptr;
536   return WarningSuppressionList;
537 }
538 
processSections(DiagnosticsEngine & Diags)539 void WarningsSpecialCaseList::processSections(DiagnosticsEngine &Diags) {
540   // Drop the default section introduced by special case list, we only support
541   // exact diagnostic group names.
542   // FIXME: We should make this configurable in the parser instead.
543   // FIXME: C++20 can use std::erase_if(Sections, [](Section &sec) { return
544   // sec.SectionStr == "*"; });
545   llvm::erase_if(Sections, [](Section &sec) { return sec.SectionStr == "*"; });
546   // Make sure we iterate sections by their line numbers.
547   std::vector<std::pair<unsigned, const Section *>> LineAndSectionEntry;
548   LineAndSectionEntry.reserve(Sections.size());
549   for (const auto &Entry : Sections) {
550     StringRef DiagName = Entry.SectionStr;
551     // Each section has a matcher with that section's name, attached to that
552     // line.
553     const auto &DiagSectionMatcher = Entry.SectionMatcher;
554     unsigned DiagLine = 0;
555     for (const auto &Glob : DiagSectionMatcher->Globs)
556       if (Glob->Name == DiagName) {
557         DiagLine = Glob->LineNo;
558         break;
559       }
560     LineAndSectionEntry.emplace_back(DiagLine, &Entry);
561   }
562   llvm::sort(LineAndSectionEntry);
563   static constexpr auto WarningFlavor = clang::diag::Flavor::WarningOrError;
564   for (const auto &[_, SectionEntry] : LineAndSectionEntry) {
565     SmallVector<diag::kind> GroupDiags;
566     StringRef DiagGroup = SectionEntry->SectionStr;
567     if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup(
568             WarningFlavor, DiagGroup, GroupDiags)) {
569       StringRef Suggestion =
570           DiagnosticIDs::getNearestOption(WarningFlavor, DiagGroup);
571       Diags.Report(diag::warn_unknown_diag_option)
572           << static_cast<unsigned>(WarningFlavor) << DiagGroup
573           << !Suggestion.empty() << Suggestion;
574       continue;
575     }
576     for (diag::kind Diag : GroupDiags)
577       // We're intentionally overwriting any previous mappings here to make sure
578       // latest one takes precedence.
579       DiagToSection[Diag] = SectionEntry;
580   }
581 }
582 
setDiagSuppressionMapping(llvm::MemoryBuffer & Input)583 void DiagnosticsEngine::setDiagSuppressionMapping(llvm::MemoryBuffer &Input) {
584   std::string Error;
585   auto WarningSuppressionList = WarningsSpecialCaseList::create(Input, Error);
586   if (!WarningSuppressionList) {
587     // FIXME: Use a `%select` statement instead of printing `Error` as-is. This
588     // should help localization.
589     Report(diag::err_drv_malformed_warning_suppression_mapping)
590         << Input.getBufferIdentifier() << Error;
591     return;
592   }
593   WarningSuppressionList->processSections(*this);
594   DiagSuppressionMapping =
595       [WarningSuppressionList(std::move(WarningSuppressionList))](
596           diag::kind DiagId, SourceLocation DiagLoc, const SourceManager &SM) {
597         return WarningSuppressionList->isDiagSuppressed(DiagId, DiagLoc, SM);
598       };
599 }
600 
isDiagSuppressed(diag::kind DiagId,SourceLocation DiagLoc,const SourceManager & SM) const601 bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId,
602                                                SourceLocation DiagLoc,
603                                                const SourceManager &SM) const {
604   const Section *DiagSection = DiagToSection.lookup(DiagId);
605   if (!DiagSection)
606     return false;
607   const SectionEntries &EntityTypeToCategories = DiagSection->Entries;
608   auto SrcEntriesIt = EntityTypeToCategories.find("src");
609   if (SrcEntriesIt == EntityTypeToCategories.end())
610     return false;
611   const llvm::StringMap<llvm::SpecialCaseList::Matcher> &CategoriesToMatchers =
612       SrcEntriesIt->getValue();
613   // We also use presumed locations here to improve reproducibility for
614   // preprocessed inputs.
615   if (PresumedLoc PLoc = SM.getPresumedLoc(DiagLoc); PLoc.isValid())
616     return globsMatches(
617         CategoriesToMatchers,
618         llvm::sys::path::remove_leading_dotslash(PLoc.getFilename()));
619   return false;
620 }
621 
globsMatches(const llvm::StringMap<Matcher> & CategoriesToMatchers,StringRef FilePath) const622 bool WarningsSpecialCaseList::globsMatches(
623     const llvm::StringMap<Matcher> &CategoriesToMatchers,
624     StringRef FilePath) const {
625   StringRef LongestMatch;
626   bool LongestIsPositive = false;
627   for (const auto &Entry : CategoriesToMatchers) {
628     StringRef Category = Entry.getKey();
629     const llvm::SpecialCaseList::Matcher &Matcher = Entry.getValue();
630     bool IsPositive = Category != "emit";
631     for (const auto &Glob : Matcher.Globs) {
632       if (Glob->Name.size() < LongestMatch.size())
633         continue;
634       if (!Glob->Pattern.match(FilePath))
635         continue;
636       LongestMatch = Glob->Name;
637       LongestIsPositive = IsPositive;
638     }
639   }
640   return LongestIsPositive;
641 }
642 
isSuppressedViaMapping(diag::kind DiagId,SourceLocation DiagLoc) const643 bool DiagnosticsEngine::isSuppressedViaMapping(diag::kind DiagId,
644                                                SourceLocation DiagLoc) const {
645   if (!hasSourceManager() || !DiagSuppressionMapping)
646     return false;
647   return DiagSuppressionMapping(DiagId, DiagLoc, getSourceManager());
648 }
649 
Report(const StoredDiagnostic & storedDiag)650 void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
651   DiagnosticStorage DiagStorage;
652   DiagStorage.DiagRanges.append(storedDiag.range_begin(),
653                                 storedDiag.range_end());
654 
655   DiagStorage.FixItHints.append(storedDiag.fixit_begin(),
656                                 storedDiag.fixit_end());
657 
658   assert(Client && "DiagnosticConsumer not set!");
659   Level DiagLevel = storedDiag.getLevel();
660   Diagnostic Info(this, storedDiag.getLocation(), storedDiag.getID(),
661                   DiagStorage, storedDiag.getMessage());
662   Report(DiagLevel, Info);
663 }
664 
Report(Level DiagLevel,const Diagnostic & Info)665 void DiagnosticsEngine::Report(Level DiagLevel, const Diagnostic &Info) {
666   assert(DiagLevel != Ignored && "Cannot emit ignored diagnostics!");
667   Client->HandleDiagnostic(DiagLevel, Info);
668   if (Client->IncludeInDiagnosticCounts()) {
669     if (DiagLevel == Warning)
670       ++NumWarnings;
671   }
672 }
673 
674 /// ProcessDiag - This is the method used to report a diagnostic that is
675 /// finally fully formed.
ProcessDiag(const DiagnosticBuilder & DiagBuilder)676 bool DiagnosticsEngine::ProcessDiag(const DiagnosticBuilder &DiagBuilder) {
677   Diagnostic Info(this, DiagBuilder);
678 
679   assert(getClient() && "DiagnosticClient not set!");
680 
681   // Figure out the diagnostic level of this message.
682   unsigned DiagID = Info.getID();
683   Level DiagLevel = getDiagnosticLevel(DiagID, Info.getLocation());
684 
685   // Update counts for DiagnosticErrorTrap even if a fatal error occurred
686   // or diagnostics are suppressed.
687   if (DiagLevel >= Error) {
688     ++TrapNumErrorsOccurred;
689     if (Diags->isUnrecoverable(DiagID))
690       ++TrapNumUnrecoverableErrorsOccurred;
691   }
692 
693   if (SuppressAllDiagnostics)
694     return false;
695 
696   if (DiagLevel != Note) {
697     // Record that a fatal error occurred only when we see a second
698     // non-note diagnostic. This allows notes to be attached to the
699     // fatal error, but suppresses any diagnostics that follow those
700     // notes.
701     if (LastDiagLevel == Fatal)
702       FatalErrorOccurred = true;
703 
704     LastDiagLevel = DiagLevel;
705   }
706 
707   // If a fatal error has already been emitted, silence all subsequent
708   // diagnostics.
709   if (FatalErrorOccurred) {
710     if (DiagLevel >= Error && Client->IncludeInDiagnosticCounts())
711       ++NumErrors;
712 
713     return false;
714   }
715 
716   // If the client doesn't care about this message, don't issue it.  If this is
717   // a note and the last real diagnostic was ignored, ignore it too.
718   if (DiagLevel == Ignored || (DiagLevel == Note && LastDiagLevel == Ignored))
719     return false;
720 
721   if (DiagLevel >= Error) {
722     if (Diags->isUnrecoverable(DiagID))
723       UnrecoverableErrorOccurred = true;
724 
725     // Warnings which have been upgraded to errors do not prevent compilation.
726     if (Diags->isDefaultMappingAsError(DiagID))
727       UncompilableErrorOccurred = true;
728 
729     ErrorOccurred = true;
730     if (Client->IncludeInDiagnosticCounts())
731       ++NumErrors;
732 
733     // If we've emitted a lot of errors, emit a fatal error instead of it to
734     // stop a flood of bogus errors.
735     if (ErrorLimit && NumErrors > ErrorLimit && DiagLevel == Error) {
736       Report(diag::fatal_too_many_errors);
737       return false;
738     }
739   }
740 
741   // Make sure we set FatalErrorOccurred to ensure that the notes from the
742   // diagnostic that caused `fatal_too_many_errors` won't be emitted.
743   if (Info.getID() == diag::fatal_too_many_errors)
744     FatalErrorOccurred = true;
745 
746   // Finally, report it.
747   Report(DiagLevel, Info);
748   return true;
749 }
750 
EmitDiagnostic(const DiagnosticBuilder & DB,bool Force)751 bool DiagnosticsEngine::EmitDiagnostic(const DiagnosticBuilder &DB,
752                                        bool Force) {
753   assert(getClient() && "DiagnosticClient not set!");
754 
755   bool Emitted;
756   if (Force) {
757     Diagnostic Info(this, DB);
758 
759     // Figure out the diagnostic level of this message.
760     Level DiagLevel = getDiagnosticLevel(Info.getID(), Info.getLocation());
761 
762     // Emit the diagnostic regardless of suppression level.
763     Emitted = DiagLevel != Ignored;
764     if (Emitted)
765       Report(DiagLevel, Info);
766   } else {
767     // Process the diagnostic, sending the accumulated information to the
768     // DiagnosticConsumer.
769     Emitted = ProcessDiag(DB);
770   }
771 
772   return Emitted;
773 }
774 
DiagnosticBuilder(DiagnosticsEngine * DiagObj,SourceLocation DiagLoc,unsigned DiagID)775 DiagnosticBuilder::DiagnosticBuilder(DiagnosticsEngine *DiagObj,
776                                      SourceLocation DiagLoc, unsigned DiagID)
777     : StreamingDiagnostic(DiagObj->DiagAllocator), DiagObj(DiagObj),
778       DiagLoc(DiagLoc), DiagID(DiagID), IsActive(true) {
779   assert(DiagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
780 }
781 
DiagnosticBuilder(const DiagnosticBuilder & D)782 DiagnosticBuilder::DiagnosticBuilder(const DiagnosticBuilder &D)
783     : StreamingDiagnostic() {
784   DiagLoc = D.DiagLoc;
785   DiagID = D.DiagID;
786   FlagValue = D.FlagValue;
787   DiagObj = D.DiagObj;
788   DiagStorage = D.DiagStorage;
789   D.DiagStorage = nullptr;
790   Allocator = D.Allocator;
791   IsActive = D.IsActive;
792   IsForceEmit = D.IsForceEmit;
793   D.Clear();
794 }
795 
Diagnostic(const DiagnosticsEngine * DO,const DiagnosticBuilder & DiagBuilder)796 Diagnostic::Diagnostic(const DiagnosticsEngine *DO,
797                        const DiagnosticBuilder &DiagBuilder)
798     : DiagObj(DO), DiagLoc(DiagBuilder.DiagLoc), DiagID(DiagBuilder.DiagID),
799       FlagValue(DiagBuilder.FlagValue), DiagStorage(*DiagBuilder.getStorage()) {
800 }
801 
Diagnostic(const DiagnosticsEngine * DO,SourceLocation DiagLoc,unsigned DiagID,const DiagnosticStorage & DiagStorage,StringRef StoredDiagMessage)802 Diagnostic::Diagnostic(const DiagnosticsEngine *DO, SourceLocation DiagLoc,
803                        unsigned DiagID, const DiagnosticStorage &DiagStorage,
804                        StringRef StoredDiagMessage)
805     : DiagObj(DO), DiagLoc(DiagLoc), DiagID(DiagID), DiagStorage(DiagStorage),
806       StoredDiagMessage(StoredDiagMessage) {}
807 
808 DiagnosticConsumer::~DiagnosticConsumer() = default;
809 
HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,const Diagnostic & Info)810 void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
811                                           const Diagnostic &Info) {
812   if (!IncludeInDiagnosticCounts())
813     return;
814 
815   if (DiagLevel == DiagnosticsEngine::Warning)
816     ++NumWarnings;
817   else if (DiagLevel >= DiagnosticsEngine::Error)
818     ++NumErrors;
819 }
820 
821 /// ModifierIs - Return true if the specified modifier matches specified string.
822 template <std::size_t StrLen>
ModifierIs(const char * Modifier,unsigned ModifierLen,const char (& Str)[StrLen])823 static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
824                        const char (&Str)[StrLen]) {
825   return StrLen - 1 == ModifierLen && memcmp(Modifier, Str, StrLen - 1) == 0;
826 }
827 
828 /// ScanForward - Scans forward, looking for the given character, skipping
829 /// nested clauses and escaped characters.
ScanFormat(const char * I,const char * E,char Target)830 static const char *ScanFormat(const char *I, const char *E, char Target) {
831   unsigned Depth = 0;
832 
833   for (; I != E; ++I) {
834     if (Depth == 0 && *I == Target)
835       return I;
836     if (Depth != 0 && *I == '}')
837       Depth--;
838 
839     if (*I == '%') {
840       I++;
841       if (I == E)
842         break;
843 
844       // Escaped characters get implicitly skipped here.
845 
846       // Format specifier.
847       if (!isDigit(*I) && !isPunctuation(*I)) {
848         for (I++; I != E && !isDigit(*I) && *I != '{'; I++)
849           ;
850         if (I == E)
851           break;
852         if (*I == '{')
853           Depth++;
854       }
855     }
856   }
857   return E;
858 }
859 
860 /// HandleSelectModifier - Handle the integer 'select' modifier.  This is used
861 /// like this:  %select{foo|bar|baz}2.  This means that the integer argument
862 /// "%2" has a value from 0-2.  If the value is 0, the diagnostic prints 'foo'.
863 /// If the value is 1, it prints 'bar'.  If it has the value 2, it prints 'baz'.
864 /// This is very useful for certain classes of variant diagnostics.
HandleSelectModifier(const Diagnostic & DInfo,unsigned ValNo,const char * Argument,unsigned ArgumentLen,SmallVectorImpl<char> & OutStr)865 static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo,
866                                  const char *Argument, unsigned ArgumentLen,
867                                  SmallVectorImpl<char> &OutStr) {
868   const char *ArgumentEnd = Argument + ArgumentLen;
869 
870   // Skip over 'ValNo' |'s.
871   while (ValNo) {
872     const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
873     assert(NextVal != ArgumentEnd &&
874            "Value for integer select modifier was"
875            " larger than the number of options in the diagnostic string!");
876     Argument = NextVal + 1; // Skip this string.
877     --ValNo;
878   }
879 
880   // Get the end of the value.  This is either the } or the |.
881   const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
882 
883   // Recursively format the result of the select clause into the output string.
884   DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
885 }
886 
887 /// HandleIntegerSModifier - Handle the integer 's' modifier.  This adds the
888 /// letter 's' to the string if the value is not 1.  This is used in cases like
889 /// this:  "you idiot, you have %4 parameter%s4!".
HandleIntegerSModifier(unsigned ValNo,SmallVectorImpl<char> & OutStr)890 static void HandleIntegerSModifier(unsigned ValNo,
891                                    SmallVectorImpl<char> &OutStr) {
892   if (ValNo != 1)
893     OutStr.push_back('s');
894 }
895 
896 /// HandleOrdinalModifier - Handle the integer 'ord' modifier.  This
897 /// prints the ordinal form of the given integer, with 1 corresponding
898 /// to the first ordinal.  Currently this is hard-coded to use the
899 /// English form.
HandleOrdinalModifier(unsigned ValNo,SmallVectorImpl<char> & OutStr)900 static void HandleOrdinalModifier(unsigned ValNo,
901                                   SmallVectorImpl<char> &OutStr) {
902   assert(ValNo != 0 && "ValNo must be strictly positive!");
903 
904   llvm::raw_svector_ostream Out(OutStr);
905 
906   // We could use text forms for the first N ordinals, but the numeric
907   // forms are actually nicer in diagnostics because they stand out.
908   Out << ValNo << llvm::getOrdinalSuffix(ValNo);
909 }
910 
911 // 123 -> "123".
912 // 1234 -> "1.23k".
913 // 123456 -> "123.46k".
914 // 1234567 -> "1.23M".
915 // 1234567890 -> "1.23G".
916 // 1234567890123 -> "1.23T".
HandleIntegerHumanModifier(int64_t ValNo,SmallVectorImpl<char> & OutStr)917 static void HandleIntegerHumanModifier(int64_t ValNo,
918                                        SmallVectorImpl<char> &OutStr) {
919   static constexpr std::array<std::pair<int64_t, char>, 4> Units = {
920       {{1'000'000'000'000L, 'T'},
921        {1'000'000'000L, 'G'},
922        {1'000'000L, 'M'},
923        {1'000L, 'k'}}};
924 
925   llvm::raw_svector_ostream Out(OutStr);
926   if (ValNo < 0) {
927     Out << "-";
928     ValNo = -ValNo;
929   }
930   for (const auto &[UnitSize, UnitSign] : Units) {
931     if (ValNo >= UnitSize) {
932       Out << llvm::format("%0.2f%c", ValNo / static_cast<double>(UnitSize),
933                           UnitSign);
934       return;
935     }
936   }
937   Out << ValNo;
938 }
939 
940 /// PluralNumber - Parse an unsigned integer and advance Start.
PluralNumber(const char * & Start,const char * End)941 static unsigned PluralNumber(const char *&Start, const char *End) {
942   // Programming 101: Parse a decimal number :-)
943   unsigned Val = 0;
944   while (Start != End && *Start >= '0' && *Start <= '9') {
945     Val *= 10;
946     Val += *Start - '0';
947     ++Start;
948   }
949   return Val;
950 }
951 
952 /// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
TestPluralRange(unsigned Val,const char * & Start,const char * End)953 static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
954   if (*Start != '[') {
955     unsigned Ref = PluralNumber(Start, End);
956     return Ref == Val;
957   }
958 
959   ++Start;
960   unsigned Low = PluralNumber(Start, End);
961   assert(*Start == ',' && "Bad plural expression syntax: expected ,");
962   ++Start;
963   unsigned High = PluralNumber(Start, End);
964   assert(*Start == ']' && "Bad plural expression syntax: expected )");
965   ++Start;
966   return Low <= Val && Val <= High;
967 }
968 
969 /// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
EvalPluralExpr(unsigned ValNo,const char * Start,const char * End)970 static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
971   // Empty condition?
972   if (*Start == ':')
973     return true;
974 
975   while (true) {
976     char C = *Start;
977     if (C == '%') {
978       // Modulo expression
979       ++Start;
980       unsigned Arg = PluralNumber(Start, End);
981       assert(*Start == '=' && "Bad plural expression syntax: expected =");
982       ++Start;
983       unsigned ValMod = ValNo % Arg;
984       if (TestPluralRange(ValMod, Start, End))
985         return true;
986     } else {
987       assert((C == '[' || (C >= '0' && C <= '9')) &&
988              "Bad plural expression syntax: unexpected character");
989       // Range expression
990       if (TestPluralRange(ValNo, Start, End))
991         return true;
992     }
993 
994     // Scan for next or-expr part.
995     Start = std::find(Start, End, ',');
996     if (Start == End)
997       break;
998     ++Start;
999   }
1000   return false;
1001 }
1002 
1003 /// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
1004 /// for complex plural forms, or in languages where all plurals are complex.
1005 /// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
1006 /// conditions that are tested in order, the form corresponding to the first
1007 /// that applies being emitted. The empty condition is always true, making the
1008 /// last form a default case.
1009 /// Conditions are simple boolean expressions, where n is the number argument.
1010 /// Here are the rules.
1011 /// condition  := expression | empty
1012 /// empty      :=                             -> always true
1013 /// expression := numeric [',' expression]    -> logical or
1014 /// numeric    := range                       -> true if n in range
1015 ///             | '%' number '=' range        -> true if n % number in range
1016 /// range      := number
1017 ///             | '[' number ',' number ']'   -> ranges are inclusive both ends
1018 ///
1019 /// Here are some examples from the GNU gettext manual written in this form:
1020 /// English:
1021 /// {1:form0|:form1}
1022 /// Latvian:
1023 /// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
1024 /// Gaeilge:
1025 /// {1:form0|2:form1|:form2}
1026 /// Romanian:
1027 /// {1:form0|0,%100=[1,19]:form1|:form2}
1028 /// Lithuanian:
1029 /// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
1030 /// Russian (requires repeated form):
1031 /// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
1032 /// Slovak
1033 /// {1:form0|[2,4]:form1|:form2}
1034 /// Polish (requires repeated form):
1035 /// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
HandlePluralModifier(const Diagnostic & DInfo,unsigned ValNo,const char * Argument,unsigned ArgumentLen,SmallVectorImpl<char> & OutStr)1036 static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
1037                                  const char *Argument, unsigned ArgumentLen,
1038                                  SmallVectorImpl<char> &OutStr) {
1039   const char *ArgumentEnd = Argument + ArgumentLen;
1040   while (true) {
1041     assert(Argument < ArgumentEnd && "Plural expression didn't match.");
1042     const char *ExprEnd = Argument;
1043     while (*ExprEnd != ':') {
1044       assert(ExprEnd != ArgumentEnd && "Plural missing expression end");
1045       ++ExprEnd;
1046     }
1047     if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
1048       Argument = ExprEnd + 1;
1049       ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
1050 
1051       // Recursively format the result of the plural clause into the
1052       // output string.
1053       DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr);
1054       return;
1055     }
1056     Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
1057   }
1058 }
1059 
1060 /// Returns the friendly description for a token kind that will appear
1061 /// without quotes in diagnostic messages. These strings may be translatable in
1062 /// future.
getTokenDescForDiagnostic(tok::TokenKind Kind)1063 static const char *getTokenDescForDiagnostic(tok::TokenKind Kind) {
1064   switch (Kind) {
1065   case tok::identifier:
1066     return "identifier";
1067   default:
1068     return nullptr;
1069   }
1070 }
1071 
1072 /// FormatDiagnostic - Format this diagnostic into a string, substituting the
1073 /// formal arguments into the %0 slots.  The result is appended onto the Str
1074 /// array.
FormatDiagnostic(SmallVectorImpl<char> & OutStr) const1075 void Diagnostic::FormatDiagnostic(SmallVectorImpl<char> &OutStr) const {
1076   if (StoredDiagMessage.has_value()) {
1077     OutStr.append(StoredDiagMessage->begin(), StoredDiagMessage->end());
1078     return;
1079   }
1080 
1081   StringRef Diag = getDiags()->getDiagnosticIDs()->getDescription(getID());
1082 
1083   FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
1084 }
1085 
1086 /// EscapeStringForDiagnostic - Append Str to the diagnostic buffer,
1087 /// escaping non-printable characters and ill-formed code unit sequences.
EscapeStringForDiagnostic(StringRef Str,SmallVectorImpl<char> & OutStr)1088 void clang::EscapeStringForDiagnostic(StringRef Str,
1089                                       SmallVectorImpl<char> &OutStr) {
1090   OutStr.reserve(OutStr.size() + Str.size());
1091   auto *Begin = reinterpret_cast<const unsigned char *>(Str.data());
1092   llvm::raw_svector_ostream OutStream(OutStr);
1093   const unsigned char *End = Begin + Str.size();
1094   while (Begin != End) {
1095     // ASCII case
1096     if (isPrintable(*Begin) || isWhitespace(*Begin)) {
1097       OutStream << *Begin;
1098       ++Begin;
1099       continue;
1100     }
1101     if (llvm::isLegalUTF8Sequence(Begin, End)) {
1102       llvm::UTF32 CodepointValue;
1103       llvm::UTF32 *CpPtr = &CodepointValue;
1104       const unsigned char *CodepointBegin = Begin;
1105       const unsigned char *CodepointEnd =
1106           Begin + llvm::getNumBytesForUTF8(*Begin);
1107       llvm::ConversionResult Res = llvm::ConvertUTF8toUTF32(
1108           &Begin, CodepointEnd, &CpPtr, CpPtr + 1, llvm::strictConversion);
1109       (void)Res;
1110       assert(
1111           llvm::conversionOK == Res &&
1112           "the sequence is legal UTF-8 but we couldn't convert it to UTF-32");
1113       assert(Begin == CodepointEnd &&
1114              "we must be further along in the string now");
1115       if (llvm::sys::unicode::isPrintable(CodepointValue) ||
1116           llvm::sys::unicode::isFormatting(CodepointValue)) {
1117         OutStr.append(CodepointBegin, CodepointEnd);
1118         continue;
1119       }
1120       // Unprintable code point.
1121       OutStream << "<U+" << llvm::format_hex_no_prefix(CodepointValue, 4, true)
1122                 << ">";
1123       continue;
1124     }
1125     // Invalid code unit.
1126     OutStream << "<" << llvm::format_hex_no_prefix(*Begin, 2, true) << ">";
1127     ++Begin;
1128   }
1129 }
1130 
FormatDiagnostic(const char * DiagStr,const char * DiagEnd,SmallVectorImpl<char> & OutStr) const1131 void Diagnostic::FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
1132                                   SmallVectorImpl<char> &OutStr) const {
1133   // When the diagnostic string is only "%0", the entire string is being given
1134   // by an outside source.  Remove unprintable characters from this string
1135   // and skip all the other string processing.
1136   if (DiagEnd - DiagStr == 2 && StringRef(DiagStr, DiagEnd - DiagStr) == "%0" &&
1137       getArgKind(0) == DiagnosticsEngine::ak_std_string) {
1138     const std::string &S = getArgStdStr(0);
1139     EscapeStringForDiagnostic(S, OutStr);
1140     return;
1141   }
1142 
1143   /// FormattedArgs - Keep track of all of the arguments formatted by
1144   /// ConvertArgToString and pass them into subsequent calls to
1145   /// ConvertArgToString, allowing the implementation to avoid redundancies in
1146   /// obvious cases.
1147   SmallVector<DiagnosticsEngine::ArgumentValue, 8> FormattedArgs;
1148 
1149   /// QualTypeVals - Pass a vector of arrays so that QualType names can be
1150   /// compared to see if more information is needed to be printed.
1151   SmallVector<intptr_t, 2> QualTypeVals;
1152   SmallString<64> Tree;
1153 
1154   for (unsigned i = 0, e = getNumArgs(); i < e; ++i)
1155     if (getArgKind(i) == DiagnosticsEngine::ak_qualtype)
1156       QualTypeVals.push_back(getRawArg(i));
1157 
1158   while (DiagStr != DiagEnd) {
1159     if (DiagStr[0] != '%') {
1160       // Append non-%0 substrings to Str if we have one.
1161       const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
1162       OutStr.append(DiagStr, StrEnd);
1163       DiagStr = StrEnd;
1164       continue;
1165     } else if (isPunctuation(DiagStr[1])) {
1166       OutStr.push_back(DiagStr[1]); // %% -> %.
1167       DiagStr += 2;
1168       continue;
1169     }
1170 
1171     // Skip the %.
1172     ++DiagStr;
1173 
1174     // This must be a placeholder for a diagnostic argument.  The format for a
1175     // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
1176     // The digit is a number from 0-9 indicating which argument this comes from.
1177     // The modifier is a string of digits from the set [-a-z]+, arguments is a
1178     // brace enclosed string.
1179     const char *Modifier = nullptr, *Argument = nullptr;
1180     unsigned ModifierLen = 0, ArgumentLen = 0;
1181 
1182     // Check to see if we have a modifier.  If so eat it.
1183     if (!isDigit(DiagStr[0])) {
1184       Modifier = DiagStr;
1185       while (DiagStr[0] == '-' || (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
1186         ++DiagStr;
1187       ModifierLen = DiagStr - Modifier;
1188 
1189       // If we have an argument, get it next.
1190       if (DiagStr[0] == '{') {
1191         ++DiagStr; // Skip {.
1192         Argument = DiagStr;
1193 
1194         DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
1195         assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!");
1196         ArgumentLen = DiagStr - Argument;
1197         ++DiagStr; // Skip }.
1198       }
1199     }
1200 
1201     assert(isDigit(*DiagStr) && "Invalid format for argument in diagnostic");
1202     unsigned ArgNo = *DiagStr++ - '0';
1203 
1204     // Only used for type diffing.
1205     unsigned ArgNo2 = ArgNo;
1206 
1207     DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo);
1208     if (ModifierIs(Modifier, ModifierLen, "diff")) {
1209       assert(*DiagStr == ',' && isDigit(*(DiagStr + 1)) &&
1210              "Invalid format for diff modifier");
1211       ++DiagStr; // Comma.
1212       ArgNo2 = *DiagStr++ - '0';
1213       DiagnosticsEngine::ArgumentKind Kind2 = getArgKind(ArgNo2);
1214       if (Kind == DiagnosticsEngine::ak_qualtype &&
1215           Kind2 == DiagnosticsEngine::ak_qualtype)
1216         Kind = DiagnosticsEngine::ak_qualtype_pair;
1217       else {
1218         // %diff only supports QualTypes.  For other kinds of arguments,
1219         // use the default printing.  For example, if the modifier is:
1220         //   "%diff{compare $ to $|other text}1,2"
1221         // treat it as:
1222         //   "compare %1 to %2"
1223         const char *ArgumentEnd = Argument + ArgumentLen;
1224         const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
1225         assert(ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd &&
1226                "Found too many '|'s in a %diff modifier!");
1227         const char *FirstDollar = ScanFormat(Argument, Pipe, '$');
1228         const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$');
1229         const char ArgStr1[] = {'%', static_cast<char>('0' + ArgNo)};
1230         const char ArgStr2[] = {'%', static_cast<char>('0' + ArgNo2)};
1231         FormatDiagnostic(Argument, FirstDollar, OutStr);
1232         FormatDiagnostic(ArgStr1, ArgStr1 + 2, OutStr);
1233         FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
1234         FormatDiagnostic(ArgStr2, ArgStr2 + 2, OutStr);
1235         FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
1236         continue;
1237       }
1238     }
1239 
1240     switch (Kind) {
1241     // ---- STRINGS ----
1242     case DiagnosticsEngine::ak_std_string:
1243     case DiagnosticsEngine::ak_c_string: {
1244       StringRef S = [&]() -> StringRef {
1245         if (Kind == DiagnosticsEngine::ak_std_string)
1246           return getArgStdStr(ArgNo);
1247         const char *SZ = getArgCStr(ArgNo);
1248         // Don't crash if get passed a null pointer by accident.
1249         return SZ ? SZ : "(null)";
1250       }();
1251       bool Quoted = false;
1252       if (ModifierIs(Modifier, ModifierLen, "quoted")) {
1253         Quoted = true;
1254         OutStr.push_back('\'');
1255       } else {
1256         assert(ModifierLen == 0 && "unknown modifier for string");
1257       }
1258       EscapeStringForDiagnostic(S, OutStr);
1259       if (Quoted)
1260         OutStr.push_back('\'');
1261       break;
1262     }
1263     // ---- INTEGERS ----
1264     case DiagnosticsEngine::ak_sint: {
1265       int64_t Val = getArgSInt(ArgNo);
1266 
1267       if (ModifierIs(Modifier, ModifierLen, "select")) {
1268         HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen,
1269                              OutStr);
1270       } else if (ModifierIs(Modifier, ModifierLen, "s")) {
1271         HandleIntegerSModifier(Val, OutStr);
1272       } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
1273         HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
1274                              OutStr);
1275       } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
1276         HandleOrdinalModifier((unsigned)Val, OutStr);
1277       } else if (ModifierIs(Modifier, ModifierLen, "human")) {
1278         HandleIntegerHumanModifier(Val, OutStr);
1279       } else {
1280         assert(ModifierLen == 0 && "Unknown integer modifier");
1281         llvm::raw_svector_ostream(OutStr) << Val;
1282       }
1283       break;
1284     }
1285     case DiagnosticsEngine::ak_uint: {
1286       uint64_t Val = getArgUInt(ArgNo);
1287 
1288       if (ModifierIs(Modifier, ModifierLen, "select")) {
1289         HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
1290       } else if (ModifierIs(Modifier, ModifierLen, "s")) {
1291         HandleIntegerSModifier(Val, OutStr);
1292       } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
1293         HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
1294                              OutStr);
1295       } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
1296         HandleOrdinalModifier(Val, OutStr);
1297       } else if (ModifierIs(Modifier, ModifierLen, "human")) {
1298         HandleIntegerHumanModifier(Val, OutStr);
1299       } else {
1300         assert(ModifierLen == 0 && "Unknown integer modifier");
1301         llvm::raw_svector_ostream(OutStr) << Val;
1302       }
1303       break;
1304     }
1305     // ---- TOKEN SPELLINGS ----
1306     case DiagnosticsEngine::ak_tokenkind: {
1307       tok::TokenKind Kind = static_cast<tok::TokenKind>(getRawArg(ArgNo));
1308       assert(ModifierLen == 0 && "No modifiers for token kinds yet");
1309 
1310       llvm::raw_svector_ostream Out(OutStr);
1311       if (const char *S = tok::getPunctuatorSpelling(Kind))
1312         // Quoted token spelling for punctuators.
1313         Out << '\'' << S << '\'';
1314       else if ((S = tok::getKeywordSpelling(Kind)))
1315         // Unquoted token spelling for keywords.
1316         Out << S;
1317       else if ((S = getTokenDescForDiagnostic(Kind)))
1318         // Unquoted translatable token name.
1319         Out << S;
1320       else if ((S = tok::getTokenName(Kind)))
1321         // Debug name, shouldn't appear in user-facing diagnostics.
1322         Out << '<' << S << '>';
1323       else
1324         Out << "(null)";
1325       break;
1326     }
1327     // ---- NAMES and TYPES ----
1328     case DiagnosticsEngine::ak_identifierinfo: {
1329       const IdentifierInfo *II = getArgIdentifier(ArgNo);
1330       assert(ModifierLen == 0 && "No modifiers for strings yet");
1331 
1332       // Don't crash if get passed a null pointer by accident.
1333       if (!II) {
1334         const char *S = "(null)";
1335         OutStr.append(S, S + strlen(S));
1336         continue;
1337       }
1338 
1339       llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
1340       break;
1341     }
1342     case DiagnosticsEngine::ak_addrspace:
1343     case DiagnosticsEngine::ak_qual:
1344     case DiagnosticsEngine::ak_qualtype:
1345     case DiagnosticsEngine::ak_declarationname:
1346     case DiagnosticsEngine::ak_nameddecl:
1347     case DiagnosticsEngine::ak_nestednamespec:
1348     case DiagnosticsEngine::ak_declcontext:
1349     case DiagnosticsEngine::ak_attr:
1350     case DiagnosticsEngine::ak_expr:
1351     case DiagnosticsEngine::ak_attr_info:
1352       getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
1353                                      StringRef(Modifier, ModifierLen),
1354                                      StringRef(Argument, ArgumentLen),
1355                                      FormattedArgs, OutStr, QualTypeVals);
1356       break;
1357     case DiagnosticsEngine::ak_qualtype_pair: {
1358       // Create a struct with all the info needed for printing.
1359       TemplateDiffTypes TDT;
1360       TDT.FromType = getRawArg(ArgNo);
1361       TDT.ToType = getRawArg(ArgNo2);
1362       TDT.ElideType = getDiags()->ElideType;
1363       TDT.ShowColors = getDiags()->ShowColors;
1364       TDT.TemplateDiffUsed = false;
1365       intptr_t val = reinterpret_cast<intptr_t>(&TDT);
1366 
1367       const char *ArgumentEnd = Argument + ArgumentLen;
1368       const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
1369 
1370       // Print the tree.  If this diagnostic already has a tree, skip the
1371       // second tree.
1372       if (getDiags()->PrintTemplateTree && Tree.empty()) {
1373         TDT.PrintFromType = true;
1374         TDT.PrintTree = true;
1375         getDiags()->ConvertArgToString(Kind, val,
1376                                        StringRef(Modifier, ModifierLen),
1377                                        StringRef(Argument, ArgumentLen),
1378                                        FormattedArgs, Tree, QualTypeVals);
1379         // If there is no tree information, fall back to regular printing.
1380         if (!Tree.empty()) {
1381           FormatDiagnostic(Pipe + 1, ArgumentEnd, OutStr);
1382           break;
1383         }
1384       }
1385 
1386       // Non-tree printing, also the fall-back when tree printing fails.
1387       // The fall-back is triggered when the types compared are not templates.
1388       const char *FirstDollar = ScanFormat(Argument, ArgumentEnd, '$');
1389       const char *SecondDollar = ScanFormat(FirstDollar + 1, ArgumentEnd, '$');
1390 
1391       // Append before text
1392       FormatDiagnostic(Argument, FirstDollar, OutStr);
1393 
1394       // Append first type
1395       TDT.PrintTree = false;
1396       TDT.PrintFromType = true;
1397       getDiags()->ConvertArgToString(Kind, val,
1398                                      StringRef(Modifier, ModifierLen),
1399                                      StringRef(Argument, ArgumentLen),
1400                                      FormattedArgs, OutStr, QualTypeVals);
1401       if (!TDT.TemplateDiffUsed)
1402         FormattedArgs.push_back(
1403             std::make_pair(DiagnosticsEngine::ak_qualtype, TDT.FromType));
1404 
1405       // Append middle text
1406       FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
1407 
1408       // Append second type
1409       TDT.PrintFromType = false;
1410       getDiags()->ConvertArgToString(Kind, val,
1411                                      StringRef(Modifier, ModifierLen),
1412                                      StringRef(Argument, ArgumentLen),
1413                                      FormattedArgs, OutStr, QualTypeVals);
1414       if (!TDT.TemplateDiffUsed)
1415         FormattedArgs.push_back(
1416             std::make_pair(DiagnosticsEngine::ak_qualtype, TDT.ToType));
1417 
1418       // Append end text
1419       FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
1420       break;
1421     }
1422     }
1423 
1424     // Remember this argument info for subsequent formatting operations.  Turn
1425     // std::strings into a null terminated string to make it be the same case as
1426     // all the other ones.
1427     if (Kind == DiagnosticsEngine::ak_qualtype_pair)
1428       continue;
1429     else if (Kind != DiagnosticsEngine::ak_std_string)
1430       FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
1431     else
1432       FormattedArgs.push_back(
1433           std::make_pair(DiagnosticsEngine::ak_c_string,
1434                          (intptr_t)getArgStdStr(ArgNo).c_str()));
1435   }
1436 
1437   // Append the type tree to the end of the diagnostics.
1438   OutStr.append(Tree.begin(), Tree.end());
1439 }
1440 
StoredDiagnostic(DiagnosticsEngine::Level Level,unsigned ID,StringRef Message)1441 StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1442                                    StringRef Message)
1443     : ID(ID), Level(Level), Message(Message) {}
1444 
StoredDiagnostic(DiagnosticsEngine::Level Level,const Diagnostic & Info)1445 StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
1446                                    const Diagnostic &Info)
1447     : ID(Info.getID()), Level(Level) {
1448   assert(
1449       (Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
1450       "Valid source location without setting a source manager for diagnostic");
1451   if (Info.getLocation().isValid())
1452     Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
1453   SmallString<64> Message;
1454   Info.FormatDiagnostic(Message);
1455   this->Message.assign(Message.begin(), Message.end());
1456   this->Ranges.assign(Info.getRanges().begin(), Info.getRanges().end());
1457   this->FixIts.assign(Info.getFixItHints().begin(), Info.getFixItHints().end());
1458 }
1459 
StoredDiagnostic(DiagnosticsEngine::Level Level,unsigned ID,StringRef Message,FullSourceLoc Loc,ArrayRef<CharSourceRange> Ranges,ArrayRef<FixItHint> FixIts)1460 StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1461                                    StringRef Message, FullSourceLoc Loc,
1462                                    ArrayRef<CharSourceRange> Ranges,
1463                                    ArrayRef<FixItHint> FixIts)
1464     : ID(ID), Level(Level), Loc(Loc), Message(Message),
1465       Ranges(Ranges.begin(), Ranges.end()),
1466       FixIts(FixIts.begin(), FixIts.end()) {}
1467 
operator <<(llvm::raw_ostream & OS,const StoredDiagnostic & SD)1468 llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
1469                                      const StoredDiagnostic &SD) {
1470   if (SD.getLocation().hasManager())
1471     OS << SD.getLocation().printToString(SD.getLocation().getManager()) << ": ";
1472   OS << SD.getMessage();
1473   return OS;
1474 }
1475 
1476 /// IncludeInDiagnosticCounts - This method (whose default implementation
1477 ///  returns true) indicates whether the diagnostics handled by this
1478 ///  DiagnosticConsumer should be included in the number of diagnostics
1479 ///  reported by DiagnosticsEngine.
IncludeInDiagnosticCounts() const1480 bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; }
1481 
anchor()1482 void IgnoringDiagConsumer::anchor() {}
1483 
1484 ForwardingDiagnosticConsumer::~ForwardingDiagnosticConsumer() = default;
1485 
HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,const Diagnostic & Info)1486 void ForwardingDiagnosticConsumer::HandleDiagnostic(
1487     DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
1488   Target.HandleDiagnostic(DiagLevel, Info);
1489 }
1490 
clear()1491 void ForwardingDiagnosticConsumer::clear() {
1492   DiagnosticConsumer::clear();
1493   Target.clear();
1494 }
1495 
IncludeInDiagnosticCounts() const1496 bool ForwardingDiagnosticConsumer::IncludeInDiagnosticCounts() const {
1497   return Target.IncludeInDiagnosticCounts();
1498 }
1499 
DiagStorageAllocator()1500 DiagStorageAllocator::DiagStorageAllocator() {
1501   for (unsigned I = 0; I != NumCached; ++I)
1502     FreeList[I] = Cached + I;
1503   NumFreeListEntries = NumCached;
1504 }
1505 
~DiagStorageAllocator()1506 DiagStorageAllocator::~DiagStorageAllocator() {
1507   // Don't assert if we are in a CrashRecovery context, as this invariant may
1508   // be invalidated during a crash.
1509   assert((NumFreeListEntries == NumCached ||
1510           llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
1511          "A partial is on the lam");
1512 }
1513 
1514 char DiagnosticError::ID;
1515