Diagnostic.cpp 41 KB

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