Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:56

0001 //===- VerifyDiagnosticConsumer.h - Verifying Diagnostic Client -*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
0010 #define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
0011 
0012 #include "clang/Basic/Diagnostic.h"
0013 #include "clang/Basic/FileManager.h"
0014 #include "clang/Basic/LLVM.h"
0015 #include "clang/Basic/SourceLocation.h"
0016 #include "clang/Lex/Preprocessor.h"
0017 #include "llvm/ADT/DenseMap.h"
0018 #include "llvm/ADT/PointerIntPair.h"
0019 #include "llvm/ADT/StringRef.h"
0020 #include <cassert>
0021 #include <limits>
0022 #include <memory>
0023 #include <string>
0024 #include <vector>
0025 
0026 namespace clang {
0027 
0028 class FileEntry;
0029 class LangOptions;
0030 class SourceManager;
0031 class TextDiagnosticBuffer;
0032 
0033 /// VerifyDiagnosticConsumer - Create a diagnostic client which will use
0034 /// markers in the input source to check that all the emitted diagnostics match
0035 /// those expected. See clang/docs/InternalsManual.rst for details about how to
0036 /// write tests to verify diagnostics.
0037 ///
0038 class VerifyDiagnosticConsumer: public DiagnosticConsumer,
0039                                 public CommentHandler {
0040 public:
0041   /// Directive - Abstract class representing a parsed verify directive.
0042   ///
0043   class Directive {
0044   public:
0045     static std::unique_ptr<Directive>
0046     create(bool RegexKind, SourceLocation DirectiveLoc,
0047            SourceLocation DiagnosticLoc, bool MatchAnyFileAndLine,
0048            bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max);
0049 
0050   public:
0051     /// Constant representing n or more matches.
0052     static const unsigned MaxCount = std::numeric_limits<unsigned>::max();
0053 
0054     SourceLocation DirectiveLoc;
0055     SourceLocation DiagnosticLoc;
0056     const std::string Text;
0057     unsigned Min, Max;
0058     bool MatchAnyLine;
0059     bool MatchAnyFileAndLine; // `MatchAnyFileAndLine` implies `MatchAnyLine`.
0060 
0061     Directive(const Directive &) = delete;
0062     Directive &operator=(const Directive &) = delete;
0063     virtual ~Directive() = default;
0064 
0065     // Returns true if directive text is valid.
0066     // Otherwise returns false and populates E.
0067     virtual bool isValid(std::string &Error) = 0;
0068 
0069     // Returns true on match.
0070     virtual bool match(StringRef S) = 0;
0071 
0072   protected:
0073     Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
0074               bool MatchAnyFileAndLine, bool MatchAnyLine, StringRef Text,
0075               unsigned Min, unsigned Max)
0076         : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc), Text(Text),
0077           Min(Min), Max(Max), MatchAnyLine(MatchAnyLine || MatchAnyFileAndLine),
0078           MatchAnyFileAndLine(MatchAnyFileAndLine) {
0079       assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
0080       assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
0081              "DiagnosticLoc is invalid!");
0082     }
0083   };
0084 
0085   using DirectiveList = std::vector<std::unique_ptr<Directive>>;
0086 
0087   /// ExpectedData - owns directive objects and deletes on destructor.
0088   struct ExpectedData {
0089     DirectiveList Errors;
0090     DirectiveList Warnings;
0091     DirectiveList Remarks;
0092     DirectiveList Notes;
0093 
0094     void Reset() {
0095       Errors.clear();
0096       Warnings.clear();
0097       Remarks.clear();
0098       Notes.clear();
0099     }
0100   };
0101 
0102   enum DirectiveStatus {
0103     HasNoDirectives,
0104     HasNoDirectivesReported,
0105     HasExpectedNoDiagnostics,
0106     HasOtherExpectedDirectives
0107   };
0108 
0109   class MarkerTracker;
0110 
0111 private:
0112   DiagnosticsEngine &Diags;
0113   DiagnosticConsumer *PrimaryClient;
0114   std::unique_ptr<DiagnosticConsumer> PrimaryClientOwner;
0115   std::unique_ptr<TextDiagnosticBuffer> Buffer;
0116   std::unique_ptr<MarkerTracker> Markers;
0117   const Preprocessor *CurrentPreprocessor = nullptr;
0118   const LangOptions *LangOpts = nullptr;
0119   SourceManager *SrcManager = nullptr;
0120   unsigned ActiveSourceFiles = 0;
0121   DirectiveStatus Status;
0122   ExpectedData ED;
0123 
0124   void CheckDiagnostics();
0125 
0126   void setSourceManager(SourceManager &SM) {
0127     assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!");
0128     SrcManager = &SM;
0129   }
0130 
0131   // These facilities are used for validation in debug builds.
0132   class UnparsedFileStatus {
0133     OptionalFileEntryRef File;
0134     bool FoundDirectives;
0135 
0136   public:
0137     UnparsedFileStatus(OptionalFileEntryRef File, bool FoundDirectives)
0138         : File(File), FoundDirectives(FoundDirectives) {}
0139 
0140     OptionalFileEntryRef getFile() const { return File; }
0141     bool foundDirectives() const { return FoundDirectives; }
0142   };
0143 
0144   using ParsedFilesMap = llvm::DenseMap<FileID, const FileEntry *>;
0145   using UnparsedFilesMap = llvm::DenseMap<FileID, UnparsedFileStatus>;
0146 
0147   ParsedFilesMap ParsedFiles;
0148   UnparsedFilesMap UnparsedFiles;
0149 
0150 public:
0151   /// Create a new verifying diagnostic client, which will issue errors to
0152   /// the currently-attached diagnostic client when a diagnostic does not match
0153   /// what is expected (as indicated in the source file).
0154   VerifyDiagnosticConsumer(DiagnosticsEngine &Diags);
0155   ~VerifyDiagnosticConsumer() override;
0156 
0157   void BeginSourceFile(const LangOptions &LangOpts,
0158                        const Preprocessor *PP) override;
0159 
0160   void EndSourceFile() override;
0161 
0162   enum ParsedStatus {
0163     /// File has been processed via HandleComment.
0164     IsParsed,
0165 
0166     /// File has diagnostics and may have directives.
0167     IsUnparsed,
0168 
0169     /// File has diagnostics but guaranteed no directives.
0170     IsUnparsedNoDirectives
0171   };
0172 
0173   /// Update lists of parsed and unparsed files.
0174   void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS);
0175 
0176   bool HandleComment(Preprocessor &PP, SourceRange Comment) override;
0177 
0178   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
0179                         const Diagnostic &Info) override;
0180 };
0181 
0182 } // namespace clang
0183 
0184 #endif // LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H