diff options
| author | Ralf Luther <luther.ralf@gmail.com> | 2019-03-27 20:23:17 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit2@aicp-server-3> | 2019-03-27 20:23:17 +0000 |
| commit | 1ce3a9d272e564b22a1333a1e36a3d3ab7cfab01 (patch) | |
| tree | 391382eadd4fec5bb480f2e8934fa352770221d1 /clang-r353983/include/clang/Frontend | |
| parent | d1d48b140bafaa8a50107292f5fce95562575765 (diff) | |
| parent | 4f56932d3416ac03f646bc1a611b3135fec2fe08 (diff) | |
Merge "Update prebuilt Clang to r353983." into p9.0HEADp9.0-backupp9.0
Diffstat (limited to 'clang-r353983/include/clang/Frontend')
30 files changed, 5461 insertions, 0 deletions
diff --git a/clang-r353983/include/clang/Frontend/ASTConsumers.h b/clang-r353983/include/clang/Frontend/ASTConsumers.h new file mode 100644 index 00000000..34958eeb --- /dev/null +++ b/clang-r353983/include/clang/Frontend/ASTConsumers.h @@ -0,0 +1,54 @@ +//===--- ASTConsumers.h - ASTConsumer implementations -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// AST Consumers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_ASTCONSUMERS_H +#define LLVM_CLANG_FRONTEND_ASTCONSUMERS_H + +#include "clang/Basic/LLVM.h" +#include <memory> + +namespace clang { + +class ASTConsumer; +class CodeGenOptions; +class DiagnosticsEngine; +class FileManager; +class LangOptions; +class Preprocessor; +class TargetOptions; + +// AST pretty-printer: prints out the AST in a format that is close to the +// original C code. The output is intended to be in a format such that +// clang could re-parse the output back into the same AST, but the +// implementation is still incomplete. +std::unique_ptr<ASTConsumer> CreateASTPrinter(std::unique_ptr<raw_ostream> OS, + StringRef FilterString); + +// AST dumper: dumps the raw AST in human-readable form to the given output +// stream, or stdout if OS is nullptr. +std::unique_ptr<ASTConsumer> CreateASTDumper(std::unique_ptr<raw_ostream> OS, + StringRef FilterString, + bool DumpDecls, bool Deserialize, + bool DumpLookups); + +// AST Decl node lister: prints qualified names of all filterable AST Decl +// nodes. +std::unique_ptr<ASTConsumer> CreateASTDeclNodeLister(); + +// Graphical AST viewer: for each function definition, creates a graph of +// the AST and displays it with the graph viewer "dotty". Also outputs +// function declarations to stderr. +std::unique_ptr<ASTConsumer> CreateASTViewer(); + +} // end clang namespace + +#endif diff --git a/clang-r353983/include/clang/Frontend/ASTUnit.h b/clang-r353983/include/clang/Frontend/ASTUnit.h new file mode 100644 index 00000000..cef638e2 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/ASTUnit.h @@ -0,0 +1,891 @@ +//===- ASTUnit.h - ASTUnit utility ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// ASTUnit utility class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H +#define LLVM_CLANG_FRONTEND_ASTUNIT_H + +#include "clang-c/Index.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/PreprocessingRecord.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Serialization/ASTBitCodes.h" +#include "clang/Frontend/PrecompiledPreamble.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + +class MemoryBuffer; + +namespace vfs { + +class FileSystem; + +} // namespace vfs +} // namespace llvm + +namespace clang { + +class ASTContext; +class ASTDeserializationListener; +class ASTMutationListener; +class ASTReader; +class CompilerInstance; +class CompilerInvocation; +class Decl; +class FileEntry; +class FileManager; +class FrontendAction; +class HeaderSearch; +class InputKind; +class MemoryBufferCache; +class PCHContainerOperations; +class PCHContainerReader; +class Preprocessor; +class PreprocessorOptions; +class Sema; +class TargetInfo; + +/// \brief Enumerates the available scopes for skipping function bodies. +enum class SkipFunctionBodiesScope { None, Preamble, PreambleAndMainFile }; + +/// Utility class for loading a ASTContext from an AST file. +class ASTUnit { +public: + struct StandaloneFixIt { + std::pair<unsigned, unsigned> RemoveRange; + std::pair<unsigned, unsigned> InsertFromRange; + std::string CodeToInsert; + bool BeforePreviousInsertions; + }; + + struct StandaloneDiagnostic { + unsigned ID; + DiagnosticsEngine::Level Level; + std::string Message; + std::string Filename; + unsigned LocOffset; + std::vector<std::pair<unsigned, unsigned>> Ranges; + std::vector<StandaloneFixIt> FixIts; + }; + +private: + std::shared_ptr<LangOptions> LangOpts; + IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; + IntrusiveRefCntPtr<FileManager> FileMgr; + IntrusiveRefCntPtr<SourceManager> SourceMgr; + IntrusiveRefCntPtr<MemoryBufferCache> PCMCache; + std::unique_ptr<HeaderSearch> HeaderInfo; + IntrusiveRefCntPtr<TargetInfo> Target; + std::shared_ptr<Preprocessor> PP; + IntrusiveRefCntPtr<ASTContext> Ctx; + std::shared_ptr<TargetOptions> TargetOpts; + std::shared_ptr<HeaderSearchOptions> HSOpts; + std::shared_ptr<PreprocessorOptions> PPOpts; + IntrusiveRefCntPtr<ASTReader> Reader; + bool HadModuleLoaderFatalFailure = false; + + struct ASTWriterData; + std::unique_ptr<ASTWriterData> WriterData; + + FileSystemOptions FileSystemOpts; + + /// The AST consumer that received information about the translation + /// unit as it was parsed or loaded. + std::unique_ptr<ASTConsumer> Consumer; + + /// The semantic analysis object used to type-check the translation + /// unit. + std::unique_ptr<Sema> TheSema; + + /// Optional owned invocation, just used to make the invocation used in + /// LoadFromCommandLine available. + std::shared_ptr<CompilerInvocation> Invocation; + + /// Fake module loader: the AST unit doesn't need to load any modules. + TrivialModuleLoader ModuleLoader; + + // OnlyLocalDecls - when true, walking this AST should only visit declarations + // that come from the AST itself, not from included precompiled headers. + // FIXME: This is temporary; eventually, CIndex will always do this. + bool OnlyLocalDecls = false; + + /// Whether to capture any diagnostics produced. + bool CaptureDiagnostics = false; + + /// Track whether the main file was loaded from an AST or not. + bool MainFileIsAST; + + /// What kind of translation unit this AST represents. + TranslationUnitKind TUKind = TU_Complete; + + /// Whether we should time each operation. + bool WantTiming; + + /// Whether the ASTUnit should delete the remapped buffers. + bool OwnsRemappedFileBuffers = true; + + /// Track the top-level decls which appeared in an ASTUnit which was loaded + /// from a source file. + // + // FIXME: This is just an optimization hack to avoid deserializing large parts + // of a PCH file when using the Index library on an ASTUnit loaded from + // source. In the long term we should make the Index library use efficient and + // more scalable search mechanisms. + std::vector<Decl*> TopLevelDecls; + + /// Sorted (by file offset) vector of pairs of file offset/Decl. + using LocDeclsTy = SmallVector<std::pair<unsigned, Decl *>, 64>; + using FileDeclsTy = llvm::DenseMap<FileID, LocDeclsTy *>; + + /// Map from FileID to the file-level declarations that it contains. + /// The files and decls are only local (and non-preamble) ones. + FileDeclsTy FileDecls; + + /// The name of the original source file used to generate this ASTUnit. + std::string OriginalSourceFile; + + /// The set of diagnostics produced when creating the preamble. + SmallVector<StandaloneDiagnostic, 4> PreambleDiagnostics; + + /// The set of diagnostics produced when creating this + /// translation unit. + SmallVector<StoredDiagnostic, 4> StoredDiagnostics; + + /// The set of diagnostics produced when failing to parse, e.g. due + /// to failure to load the PCH. + SmallVector<StoredDiagnostic, 4> FailedParseDiagnostics; + + /// The number of stored diagnostics that come from the driver + /// itself. + /// + /// Diagnostics that come from the driver are retained from one parse to + /// the next. + unsigned NumStoredDiagnosticsFromDriver = 0; + + /// Counter that determines when we want to try building a + /// precompiled preamble. + /// + /// If zero, we will never build a precompiled preamble. Otherwise, + /// it's treated as a counter that decrements each time we reparse + /// without the benefit of a precompiled preamble. When it hits 1, + /// we'll attempt to rebuild the precompiled header. This way, if + /// building the precompiled preamble fails, we won't try again for + /// some number of calls. + unsigned PreambleRebuildCounter = 0; + + /// Cache pairs "filename - source location" + /// + /// Cache contains only source locations from preamble so it is + /// guaranteed that they stay valid when the SourceManager is recreated. + /// This cache is used when loading preamble to increase performance + /// of that loading. It must be cleared when preamble is recreated. + llvm::StringMap<SourceLocation> PreambleSrcLocCache; + + /// The contents of the preamble. + llvm::Optional<PrecompiledPreamble> Preamble; + + /// When non-NULL, this is the buffer used to store the contents of + /// the main file when it has been padded for use with the precompiled + /// preamble. + std::unique_ptr<llvm::MemoryBuffer> SavedMainFileBuffer; + + /// The number of warnings that occurred while parsing the preamble. + /// + /// This value will be used to restore the state of the \c DiagnosticsEngine + /// object when re-using the precompiled preamble. Note that only the + /// number of warnings matters, since we will not save the preamble + /// when any errors are present. + unsigned NumWarningsInPreamble = 0; + + /// A list of the serialization ID numbers for each of the top-level + /// declarations parsed within the precompiled preamble. + std::vector<serialization::DeclID> TopLevelDeclsInPreamble; + + /// Whether we should be caching code-completion results. + bool ShouldCacheCodeCompletionResults : 1; + + /// Whether to include brief documentation within the set of code + /// completions cached. + bool IncludeBriefCommentsInCodeCompletion : 1; + + /// True if non-system source files should be treated as volatile + /// (likely to change while trying to use them). + bool UserFilesAreVolatile : 1; + + static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + ASTUnit &AST, bool CaptureDiagnostics); + + void TranslateStoredDiagnostics(FileManager &FileMgr, + SourceManager &SrcMan, + const SmallVectorImpl<StandaloneDiagnostic> &Diags, + SmallVectorImpl<StoredDiagnostic> &Out); + + void clearFileLevelDecls(); + +public: + /// A cached code-completion result, which may be introduced in one of + /// many different contexts. + struct CachedCodeCompletionResult { + /// The code-completion string corresponding to this completion + /// result. + CodeCompletionString *Completion; + + /// A bitmask that indicates which code-completion contexts should + /// contain this completion result. + /// + /// The bits in the bitmask correspond to the values of + /// CodeCompleteContext::Kind. To map from a completion context kind to a + /// bit, shift 1 by that number of bits. Many completions can occur in + /// several different contexts. + uint64_t ShowInContexts; + + /// The priority given to this code-completion result. + unsigned Priority; + + /// The libclang cursor kind corresponding to this code-completion + /// result. + CXCursorKind Kind; + + /// The availability of this code-completion result. + CXAvailabilityKind Availability; + + /// The simplified type class for a non-macro completion result. + SimplifiedTypeClass TypeClass; + + /// The type of a non-macro completion result, stored as a unique + /// integer used by the string map of cached completion types. + /// + /// This value will be zero if the type is not known, or a unique value + /// determined by the formatted type string. Se \c CachedCompletionTypes + /// for more information. + unsigned Type; + }; + + /// Retrieve the mapping from formatted type names to unique type + /// identifiers. + llvm::StringMap<unsigned> &getCachedCompletionTypes() { + return CachedCompletionTypes; + } + + /// Retrieve the allocator used to cache global code completions. + std::shared_ptr<GlobalCodeCompletionAllocator> + getCachedCompletionAllocator() { + return CachedCompletionAllocator; + } + + CodeCompletionTUInfo &getCodeCompletionTUInfo() { + if (!CCTUInfo) + CCTUInfo = llvm::make_unique<CodeCompletionTUInfo>( + std::make_shared<GlobalCodeCompletionAllocator>()); + return *CCTUInfo; + } + +private: + /// Allocator used to store cached code completions. + std::shared_ptr<GlobalCodeCompletionAllocator> CachedCompletionAllocator; + + std::unique_ptr<CodeCompletionTUInfo> CCTUInfo; + + /// The set of cached code-completion results. + std::vector<CachedCodeCompletionResult> CachedCompletionResults; + + /// A mapping from the formatted type name to a unique number for that + /// type, which is used for type equality comparisons. + llvm::StringMap<unsigned> CachedCompletionTypes; + + /// A string hash of the top-level declaration and macro definition + /// names processed the last time that we reparsed the file. + /// + /// This hash value is used to determine when we need to refresh the + /// global code-completion cache. + unsigned CompletionCacheTopLevelHashValue = 0; + + /// A string hash of the top-level declaration and macro definition + /// names processed the last time that we reparsed the precompiled preamble. + /// + /// This hash value is used to determine when we need to refresh the + /// global code-completion cache after a rebuild of the precompiled preamble. + unsigned PreambleTopLevelHashValue = 0; + + /// The current hash value for the top-level declaration and macro + /// definition names + unsigned CurrentTopLevelHashValue = 0; + + /// Bit used by CIndex to mark when a translation unit may be in an + /// inconsistent state, and is not safe to free. + unsigned UnsafeToFree : 1; + + /// \brief Enumerator specifying the scope for skipping function bodies. + SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None; + + /// Cache any "global" code-completion results, so that we can avoid + /// recomputing them with each completion. + void CacheCodeCompletionResults(); + + /// Clear out and deallocate + void ClearCachedCompletionResults(); + + explicit ASTUnit(bool MainFileIsAST); + + bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, + std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS); + + std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble( + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + CompilerInvocation &PreambleInvocationIn, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild = true, + unsigned MaxLines = 0); + void RealizeTopLevelDeclsFromPreamble(); + + /// Transfers ownership of the objects (like SourceManager) from + /// \param CI to this ASTUnit. + void transferASTDataFromCompilerInstance(CompilerInstance &CI); + + /// Allows us to assert that ASTUnit is not being used concurrently, + /// which is not supported. + /// + /// Clients should create instances of the ConcurrencyCheck class whenever + /// using the ASTUnit in a way that isn't intended to be concurrent, which is + /// just about any usage. + /// Becomes a noop in release mode; only useful for debug mode checking. + class ConcurrencyState { + void *Mutex; // a llvm::sys::MutexImpl in debug; + + public: + ConcurrencyState(); + ~ConcurrencyState(); + + void start(); + void finish(); + }; + ConcurrencyState ConcurrencyCheckValue; + +public: + friend class ConcurrencyCheck; + + class ConcurrencyCheck { + ASTUnit &Self; + + public: + explicit ConcurrencyCheck(ASTUnit &Self) : Self(Self) { + Self.ConcurrencyCheckValue.start(); + } + + ~ConcurrencyCheck() { + Self.ConcurrencyCheckValue.finish(); + } + }; + + ASTUnit(const ASTUnit &) = delete; + ASTUnit &operator=(const ASTUnit &) = delete; + ~ASTUnit(); + + bool isMainFileAST() const { return MainFileIsAST; } + + bool isUnsafeToFree() const { return UnsafeToFree; } + void setUnsafeToFree(bool Value) { UnsafeToFree = Value; } + + const DiagnosticsEngine &getDiagnostics() const { return *Diagnostics; } + DiagnosticsEngine &getDiagnostics() { return *Diagnostics; } + + const SourceManager &getSourceManager() const { return *SourceMgr; } + SourceManager &getSourceManager() { return *SourceMgr; } + + const Preprocessor &getPreprocessor() const { return *PP; } + Preprocessor &getPreprocessor() { return *PP; } + std::shared_ptr<Preprocessor> getPreprocessorPtr() const { return PP; } + + const ASTContext &getASTContext() const { return *Ctx; } + ASTContext &getASTContext() { return *Ctx; } + + void setASTContext(ASTContext *ctx) { Ctx = ctx; } + void setPreprocessor(std::shared_ptr<Preprocessor> pp); + + /// Enable source-range based diagnostic messages. + /// + /// If diagnostic messages with source-range information are to be expected + /// and AST comes not from file (e.g. after LoadFromCompilerInvocation) this + /// function has to be called. + /// The function is to be called only once and the AST should be associated + /// with the same source file afterwards. + void enableSourceFileDiagnostics(); + + bool hasSema() const { return (bool)TheSema; } + + Sema &getSema() const { + assert(TheSema && "ASTUnit does not have a Sema object!"); + return *TheSema; + } + + const LangOptions &getLangOpts() const { + assert(LangOpts && "ASTUnit does not have language options"); + return *LangOpts; + } + + const HeaderSearchOptions &getHeaderSearchOpts() const { + assert(HSOpts && "ASTUnit does not have header search options"); + return *HSOpts; + } + + const PreprocessorOptions &getPreprocessorOpts() const { + assert(PPOpts && "ASTUnit does not have preprocessor options"); + return *PPOpts; + } + + const FileManager &getFileManager() const { return *FileMgr; } + FileManager &getFileManager() { return *FileMgr; } + + const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } + + IntrusiveRefCntPtr<ASTReader> getASTReader() const; + + StringRef getOriginalSourceFileName() const { + return OriginalSourceFile; + } + + ASTMutationListener *getASTMutationListener(); + ASTDeserializationListener *getDeserializationListener(); + + bool getOnlyLocalDecls() const { return OnlyLocalDecls; } + + bool getOwnsRemappedFileBuffers() const { return OwnsRemappedFileBuffers; } + void setOwnsRemappedFileBuffers(bool val) { OwnsRemappedFileBuffers = val; } + + StringRef getMainFileName() const; + + /// If this ASTUnit came from an AST file, returns the filename for it. + StringRef getASTFileName() const; + + using top_level_iterator = std::vector<Decl *>::iterator; + + top_level_iterator top_level_begin() { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + if (!TopLevelDeclsInPreamble.empty()) + RealizeTopLevelDeclsFromPreamble(); + return TopLevelDecls.begin(); + } + + top_level_iterator top_level_end() { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + if (!TopLevelDeclsInPreamble.empty()) + RealizeTopLevelDeclsFromPreamble(); + return TopLevelDecls.end(); + } + + std::size_t top_level_size() const { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + return TopLevelDeclsInPreamble.size() + TopLevelDecls.size(); + } + + bool top_level_empty() const { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty(); + } + + /// Add a new top-level declaration. + void addTopLevelDecl(Decl *D) { + TopLevelDecls.push_back(D); + } + + /// Add a new local file-level declaration. + void addFileLevelDecl(Decl *D); + + /// Get the decls that are contained in a file in the Offset/Length + /// range. \p Length can be 0 to indicate a point at \p Offset instead of + /// a range. + void findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, + SmallVectorImpl<Decl *> &Decls); + + /// Retrieve a reference to the current top-level name hash value. + /// + /// Note: This is used internally by the top-level tracking action + unsigned &getCurrentTopLevelHashValue() { return CurrentTopLevelHashValue; } + + /// Get the source location for the given file:line:col triplet. + /// + /// The difference with SourceManager::getLocation is that this method checks + /// whether the requested location points inside the precompiled preamble + /// in which case the returned source location will be a "loaded" one. + SourceLocation getLocation(const FileEntry *File, + unsigned Line, unsigned Col) const; + + /// Get the source location for the given file:offset pair. + SourceLocation getLocation(const FileEntry *File, unsigned Offset) const; + + /// If \p Loc is a loaded location from the preamble, returns + /// the corresponding local location of the main file, otherwise it returns + /// \p Loc. + SourceLocation mapLocationFromPreamble(SourceLocation Loc) const; + + /// If \p Loc is a local location of the main file but inside the + /// preamble chunk, returns the corresponding loaded location from the + /// preamble, otherwise it returns \p Loc. + SourceLocation mapLocationToPreamble(SourceLocation Loc) const; + + bool isInPreambleFileID(SourceLocation Loc) const; + bool isInMainFileID(SourceLocation Loc) const; + SourceLocation getStartOfMainFileID() const; + SourceLocation getEndOfPreambleFileID() const; + + /// \see mapLocationFromPreamble. + SourceRange mapRangeFromPreamble(SourceRange R) const { + return SourceRange(mapLocationFromPreamble(R.getBegin()), + mapLocationFromPreamble(R.getEnd())); + } + + /// \see mapLocationToPreamble. + SourceRange mapRangeToPreamble(SourceRange R) const { + return SourceRange(mapLocationToPreamble(R.getBegin()), + mapLocationToPreamble(R.getEnd())); + } + + // Retrieve the diagnostics associated with this AST + using stored_diag_iterator = StoredDiagnostic *; + using stored_diag_const_iterator = const StoredDiagnostic *; + + stored_diag_const_iterator stored_diag_begin() const { + return StoredDiagnostics.begin(); + } + + stored_diag_iterator stored_diag_begin() { + return StoredDiagnostics.begin(); + } + + stored_diag_const_iterator stored_diag_end() const { + return StoredDiagnostics.end(); + } + + stored_diag_iterator stored_diag_end() { + return StoredDiagnostics.end(); + } + + unsigned stored_diag_size() const { return StoredDiagnostics.size(); } + + stored_diag_iterator stored_diag_afterDriver_begin() { + if (NumStoredDiagnosticsFromDriver > StoredDiagnostics.size()) + NumStoredDiagnosticsFromDriver = 0; + return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver; + } + + using cached_completion_iterator = + std::vector<CachedCodeCompletionResult>::iterator; + + cached_completion_iterator cached_completion_begin() { + return CachedCompletionResults.begin(); + } + + cached_completion_iterator cached_completion_end() { + return CachedCompletionResults.end(); + } + + unsigned cached_completion_size() const { + return CachedCompletionResults.size(); + } + + /// Returns an iterator range for the local preprocessing entities + /// of the local Preprocessor, if this is a parsed source file, or the loaded + /// preprocessing entities of the primary module if this is an AST file. + llvm::iterator_range<PreprocessingRecord::iterator> + getLocalPreprocessingEntities() const; + + /// Type for a function iterating over a number of declarations. + /// \returns true to continue iteration and false to abort. + using DeclVisitorFn = bool (*)(void *context, const Decl *D); + + /// Iterate over local declarations (locally parsed if this is a parsed + /// source file or the loaded declarations of the primary module if this is an + /// AST file). + /// \returns true if the iteration was complete or false if it was aborted. + bool visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn); + + /// Get the PCH file if one was included. + const FileEntry *getPCHFile(); + + /// Returns true if the ASTUnit was constructed from a serialized + /// module file. + bool isModuleFile() const; + + std::unique_ptr<llvm::MemoryBuffer> + getBufferForFile(StringRef Filename, std::string *ErrorStr = nullptr); + + /// Determine what kind of translation unit this AST represents. + TranslationUnitKind getTranslationUnitKind() const { return TUKind; } + + /// Determine the input kind this AST unit represents. + InputKind getInputKind() const; + + /// A mapping from a file name to the memory buffer that stores the + /// remapped contents of that file. + using RemappedFile = std::pair<std::string, llvm::MemoryBuffer *>; + + /// Create a ASTUnit. Gets ownership of the passed CompilerInvocation. + static std::unique_ptr<ASTUnit> + create(std::shared_ptr<CompilerInvocation> CI, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool CaptureDiagnostics, + bool UserFilesAreVolatile); + + enum WhatToLoad { + /// Load options and the preprocessor state. + LoadPreprocessorOnly, + + /// Load the AST, but do not restore Sema state. + LoadASTOnly, + + /// Load everything, including Sema. + LoadEverything + }; + + /// Create a ASTUnit from an AST file. + /// + /// \param Filename - The AST file to load. + /// + /// \param PCHContainerRdr - The PCHContainerOperations to use for loading and + /// creating modules. + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + /// + /// \returns - The initialized ASTUnit or null if the AST failed to load. + static std::unique_ptr<ASTUnit> LoadFromASTFile( + const std::string &Filename, const PCHContainerReader &PCHContainerRdr, + WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + const FileSystemOptions &FileSystemOpts, bool UseDebugInfo = false, + bool OnlyLocalDecls = false, ArrayRef<RemappedFile> RemappedFiles = None, + bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false, + bool UserFilesAreVolatile = false); + +private: + /// Helper function for \c LoadFromCompilerInvocation() and + /// \c LoadFromCommandLine(), which loads an AST from a compiler invocation. + /// + /// \param PrecompilePreambleAfterNParses After how many parses the preamble + /// of this translation unit should be precompiled, to improve the performance + /// of reparsing. Set to zero to disable preambles. + /// + /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses. + /// Note that preamble is saved to a temporary directory on a RealFileSystem, + /// so in order for it to be loaded correctly, VFS should have access to + /// it(i.e., be an overlay over RealFileSystem). + /// + /// \returns \c true if a catastrophic failure occurred (which means that the + /// \c ASTUnit itself is invalid), or \c false otherwise. + bool LoadFromCompilerInvocation( + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + unsigned PrecompilePreambleAfterNParses, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS); + +public: + /// Create an ASTUnit from a source file, via a CompilerInvocation + /// object, by invoking the optionally provided ASTFrontendAction. + /// + /// \param CI - The compiler invocation to use; it must have exactly one input + /// source file. The ASTUnit takes ownership of the CompilerInvocation object. + /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. + /// + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + /// + /// \param Action - The ASTFrontendAction to invoke. Its ownership is not + /// transferred. + /// + /// \param Unit - optionally an already created ASTUnit. Its ownership is not + /// transferred. + /// + /// \param Persistent - if true the returned ASTUnit will be complete. + /// false means the caller is only interested in getting info through the + /// provided \see Action. + /// + /// \param ErrAST - If non-null and parsing failed without any AST to return + /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit + /// mainly to allow the caller to see the diagnostics. + /// This will only receive an ASTUnit if a new one was created. If an already + /// created ASTUnit was passed in \p Unit then the caller can check that. + /// + static ASTUnit *LoadFromCompilerInvocationAction( + std::shared_ptr<CompilerInvocation> CI, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + FrontendAction *Action = nullptr, ASTUnit *Unit = nullptr, + bool Persistent = true, StringRef ResourceFilesPath = StringRef(), + bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, + unsigned PrecompilePreambleAfterNParses = 0, + bool CacheCodeCompletionResults = false, + bool IncludeBriefCommentsInCodeCompletion = false, + bool UserFilesAreVolatile = false, + std::unique_ptr<ASTUnit> *ErrAST = nullptr); + + /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a + /// CompilerInvocation object. + /// + /// \param CI - The compiler invocation to use; it must have exactly one input + /// source file. The ASTUnit takes ownership of the CompilerInvocation object. + /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. + /// + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + // + // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we + // shouldn't need to specify them at construction time. + static std::unique_ptr<ASTUnit> LoadFromCompilerInvocation( + std::shared_ptr<CompilerInvocation> CI, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr, + bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, + unsigned PrecompilePreambleAfterNParses = 0, + TranslationUnitKind TUKind = TU_Complete, + bool CacheCodeCompletionResults = false, + bool IncludeBriefCommentsInCodeCompletion = false, + bool UserFilesAreVolatile = false); + + /// LoadFromCommandLine - Create an ASTUnit from a vector of command line + /// arguments, which must specify exactly one source file. + /// + /// \param ArgBegin - The beginning of the argument vector. + /// + /// \param ArgEnd - The end of the argument vector. + /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. + /// + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + /// + /// \param ResourceFilesPath - The path to the compiler resource files. + /// + /// \param ModuleFormat - If provided, uses the specific module format. + /// + /// \param ErrAST - If non-null and parsing failed without any AST to return + /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit + /// mainly to allow the caller to see the diagnostics. + /// + /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses. + /// Note that preamble is saved to a temporary directory on a RealFileSystem, + /// so in order for it to be loaded correctly, VFS should have access to + /// it(i.e., be an overlay over RealFileSystem). RealFileSystem will be used + /// if \p VFS is nullptr. + /// + // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we + // shouldn't need to specify them at construction time. + static ASTUnit *LoadFromCommandLine( + const char **ArgBegin, const char **ArgEnd, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath, + bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, + ArrayRef<RemappedFile> RemappedFiles = None, + bool RemappedFilesKeepOriginalName = true, + unsigned PrecompilePreambleAfterNParses = 0, + TranslationUnitKind TUKind = TU_Complete, + bool CacheCodeCompletionResults = false, + bool IncludeBriefCommentsInCodeCompletion = false, + bool AllowPCHWithCompilerErrors = false, + SkipFunctionBodiesScope SkipFunctionBodies = + SkipFunctionBodiesScope::None, + bool SingleFileParse = false, bool UserFilesAreVolatile = false, + bool ForSerialization = false, + llvm::Optional<StringRef> ModuleFormat = llvm::None, + std::unique_ptr<ASTUnit> *ErrAST = nullptr, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr); + + /// Reparse the source files using the same command-line options that + /// were originally used to produce this translation unit. + /// + /// \param VFS - A llvm::vfs::FileSystem to be used for all file accesses. + /// Note that preamble is saved to a temporary directory on a RealFileSystem, + /// so in order for it to be loaded correctly, VFS should give an access to + /// this(i.e. be an overlay over RealFileSystem). + /// FileMgr->getVirtualFileSystem() will be used if \p VFS is nullptr. + /// + /// \returns True if a failure occurred that causes the ASTUnit not to + /// contain any translation-unit information, false otherwise. + bool Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, + ArrayRef<RemappedFile> RemappedFiles = None, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr); + + /// Free data that will be re-generated on the next parse. + /// + /// Preamble-related data is not affected. + void ResetForParse(); + + /// Perform code completion at the given file, line, and + /// column within this translation unit. + /// + /// \param File The file in which code completion will occur. + /// + /// \param Line The line at which code completion will occur. + /// + /// \param Column The column at which code completion will occur. + /// + /// \param IncludeMacros Whether to include macros in the code-completion + /// results. + /// + /// \param IncludeCodePatterns Whether to include code patterns (such as a + /// for loop) in the code-completion results. + /// + /// \param IncludeBriefComments Whether to include brief documentation within + /// the set of code completions returned. + /// + /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and + /// OwnedBuffers parameters are all disgusting hacks. They will go away. + void CodeComplete(StringRef File, unsigned Line, unsigned Column, + ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros, + bool IncludeCodePatterns, bool IncludeBriefComments, + CodeCompleteConsumer &Consumer, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticsEngine &Diag, LangOptions &LangOpts, + SourceManager &SourceMgr, FileManager &FileMgr, + SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, + SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers); + + /// Save this translation unit to a file with the given name. + /// + /// \returns true if there was a file error or false if the save was + /// successful. + bool Save(StringRef File); + + /// Serialize this translation unit with the given output stream. + /// + /// \returns True if an error occurred, false otherwise. + bool serialize(raw_ostream &OS); +}; + +} // namespace clang + +#endif // LLVM_CLANG_FRONTEND_ASTUNIT_H diff --git a/clang-r353983/include/clang/Frontend/ChainedDiagnosticConsumer.h b/clang-r353983/include/clang/Frontend/ChainedDiagnosticConsumer.h new file mode 100644 index 00000000..ca284560 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/ChainedDiagnosticConsumer.h @@ -0,0 +1,71 @@ +//===- ChainedDiagnosticConsumer.h - Chain Diagnostic Clients ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCONSUMER_H +#define LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCONSUMER_H + +#include "clang/Basic/Diagnostic.h" +#include <memory> + +namespace clang { +class LangOptions; + +/// ChainedDiagnosticConsumer - Chain two diagnostic clients so that diagnostics +/// go to the first client and then the second. The first diagnostic client +/// should be the "primary" client, and will be used for computing whether the +/// diagnostics should be included in counts. +class ChainedDiagnosticConsumer : public DiagnosticConsumer { + virtual void anchor(); + std::unique_ptr<DiagnosticConsumer> OwningPrimary; + DiagnosticConsumer *Primary; + std::unique_ptr<DiagnosticConsumer> Secondary; + +public: + ChainedDiagnosticConsumer(std::unique_ptr<DiagnosticConsumer> Primary, + std::unique_ptr<DiagnosticConsumer> Secondary) + : OwningPrimary(std::move(Primary)), Primary(OwningPrimary.get()), + Secondary(std::move(Secondary)) {} + + /// Construct without taking ownership of \c Primary. + ChainedDiagnosticConsumer(DiagnosticConsumer *Primary, + std::unique_ptr<DiagnosticConsumer> Secondary) + : Primary(Primary), Secondary(std::move(Secondary)) {} + + void BeginSourceFile(const LangOptions &LO, + const Preprocessor *PP) override { + Primary->BeginSourceFile(LO, PP); + Secondary->BeginSourceFile(LO, PP); + } + + void EndSourceFile() override { + Secondary->EndSourceFile(); + Primary->EndSourceFile(); + } + + void finish() override { + Secondary->finish(); + Primary->finish(); + } + + bool IncludeInDiagnosticCounts() const override { + return Primary->IncludeInDiagnosticCounts(); + } + + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override { + // Default implementation (Warnings/errors count). + DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info); + + Primary->HandleDiagnostic(DiagLevel, Info); + Secondary->HandleDiagnostic(DiagLevel, Info); + } +}; + +} // end namspace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/CommandLineSourceLoc.h b/clang-r353983/include/clang/Frontend/CommandLineSourceLoc.h new file mode 100644 index 00000000..e95d100f --- /dev/null +++ b/clang-r353983/include/clang/Frontend/CommandLineSourceLoc.h @@ -0,0 +1,132 @@ + +//===--- CommandLineSourceLoc.h - Parsing for source locations-*- C++ -*---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Command line parsing for source locations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H +#define LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H + +#include "clang/Basic/LLVM.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { + +/// A source location that has been parsed on the command line. +struct ParsedSourceLocation { + std::string FileName; + unsigned Line; + unsigned Column; + +public: + /// Construct a parsed source location from a string; the Filename is empty on + /// error. + static ParsedSourceLocation FromString(StringRef Str) { + ParsedSourceLocation PSL; + std::pair<StringRef, StringRef> ColSplit = Str.rsplit(':'); + std::pair<StringRef, StringRef> LineSplit = + ColSplit.first.rsplit(':'); + + // If both tail splits were valid integers, return success. + if (!ColSplit.second.getAsInteger(10, PSL.Column) && + !LineSplit.second.getAsInteger(10, PSL.Line)) { + PSL.FileName = LineSplit.first; + + // On the command-line, stdin may be specified via "-". Inside the + // compiler, stdin is called "<stdin>". + if (PSL.FileName == "-") + PSL.FileName = "<stdin>"; + } + + return PSL; + } +}; + +/// A source range that has been parsed on the command line. +struct ParsedSourceRange { + std::string FileName; + /// The starting location of the range. The first element is the line and + /// the second element is the column. + std::pair<unsigned, unsigned> Begin; + /// The ending location of the range. The first element is the line and the + /// second element is the column. + std::pair<unsigned, unsigned> End; + + /// Returns a parsed source range from a string or None if the string is + /// invalid. + /// + /// These source string has the following format: + /// + /// file:start_line:start_column[-end_line:end_column] + /// + /// If the end line and column are omitted, the starting line and columns + /// are used as the end values. + static Optional<ParsedSourceRange> fromString(StringRef Str) { + std::pair<StringRef, StringRef> RangeSplit = Str.rsplit('-'); + unsigned EndLine, EndColumn; + bool HasEndLoc = false; + if (!RangeSplit.second.empty()) { + std::pair<StringRef, StringRef> Split = RangeSplit.second.rsplit(':'); + if (Split.first.getAsInteger(10, EndLine) || + Split.second.getAsInteger(10, EndColumn)) { + // The string does not end in end_line:end_column, so the '-' + // probably belongs to the filename which menas the whole + // string should be parsed. + RangeSplit.first = Str; + } else + HasEndLoc = true; + } + auto Begin = ParsedSourceLocation::FromString(RangeSplit.first); + if (Begin.FileName.empty()) + return None; + if (!HasEndLoc) { + EndLine = Begin.Line; + EndColumn = Begin.Column; + } + return ParsedSourceRange{std::move(Begin.FileName), + {Begin.Line, Begin.Column}, + {EndLine, EndColumn}}; + } +}; +} + +namespace llvm { + namespace cl { + /// Command-line option parser that parses source locations. + /// + /// Source locations are of the form filename:line:column. + template<> + class parser<clang::ParsedSourceLocation> final + : public basic_parser<clang::ParsedSourceLocation> { + public: + inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue, + clang::ParsedSourceLocation &Val); + }; + + bool + parser<clang::ParsedSourceLocation>:: + parse(Option &O, StringRef ArgName, StringRef ArgValue, + clang::ParsedSourceLocation &Val) { + using namespace clang; + + Val = ParsedSourceLocation::FromString(ArgValue); + if (Val.FileName.empty()) { + errs() << "error: " + << "source location must be of the form filename:line:column\n"; + return true; + } + + return false; + } + } +} + +#endif diff --git a/clang-r353983/include/clang/Frontend/CompilerInstance.h b/clang-r353983/include/clang/Frontend/CompilerInstance.h new file mode 100644 index 00000000..002cc61e --- /dev/null +++ b/clang-r353983/include/clang/Frontend/CompilerInstance.h @@ -0,0 +1,821 @@ +//===-- CompilerInstance.h - Clang Compiler Instance ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ +#define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ + +#include "clang/AST/ASTConsumer.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/PCHContainerOperations.h" +#include "clang/Frontend/Utils.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/ModuleLoader.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/BuryPointer.h" +#include <cassert> +#include <list> +#include <memory> +#include <string> +#include <utility> + +namespace llvm { +class raw_fd_ostream; +class Timer; +class TimerGroup; +} + +namespace clang { +class ASTContext; +class ASTReader; +class CodeCompleteConsumer; +class DiagnosticsEngine; +class DiagnosticConsumer; +class ExternalASTSource; +class FileEntry; +class FileManager; +class FrontendAction; +class MemoryBufferCache; +class Module; +class Preprocessor; +class Sema; +class SourceManager; +class TargetInfo; + +/// CompilerInstance - Helper class for managing a single instance of the Clang +/// compiler. +/// +/// The CompilerInstance serves two purposes: +/// (1) It manages the various objects which are necessary to run the compiler, +/// for example the preprocessor, the target information, and the AST +/// context. +/// (2) It provides utility routines for constructing and manipulating the +/// common Clang objects. +/// +/// The compiler instance generally owns the instance of all the objects that it +/// manages. However, clients can still share objects by manually setting the +/// object and retaking ownership prior to destroying the CompilerInstance. +/// +/// The compiler instance is intended to simplify clients, but not to lock them +/// in to the compiler instance for everything. When possible, utility functions +/// come in two forms; a short form that reuses the CompilerInstance objects, +/// and a long form that takes explicit instances of any required objects. +class CompilerInstance : public ModuleLoader { + /// The options used in this compiler instance. + std::shared_ptr<CompilerInvocation> Invocation; + + /// The diagnostics engine instance. + IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; + + /// The target being compiled for. + IntrusiveRefCntPtr<TargetInfo> Target; + + /// Auxiliary Target info. + IntrusiveRefCntPtr<TargetInfo> AuxTarget; + + /// The virtual file system. + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VirtualFileSystem; + + /// The file manager. + IntrusiveRefCntPtr<FileManager> FileMgr; + + /// The source manager. + IntrusiveRefCntPtr<SourceManager> SourceMgr; + + /// The cache of PCM files. + IntrusiveRefCntPtr<MemoryBufferCache> PCMCache; + + /// The preprocessor. + std::shared_ptr<Preprocessor> PP; + + /// The AST context. + IntrusiveRefCntPtr<ASTContext> Context; + + /// An optional sema source that will be attached to sema. + IntrusiveRefCntPtr<ExternalSemaSource> ExternalSemaSrc; + + /// The AST consumer. + std::unique_ptr<ASTConsumer> Consumer; + + /// The code completion consumer. + std::unique_ptr<CodeCompleteConsumer> CompletionConsumer; + + /// The semantic analysis object. + std::unique_ptr<Sema> TheSema; + + /// The frontend timer group. + std::unique_ptr<llvm::TimerGroup> FrontendTimerGroup; + + /// The frontend timer. + std::unique_ptr<llvm::Timer> FrontendTimer; + + /// The ASTReader, if one exists. + IntrusiveRefCntPtr<ASTReader> ModuleManager; + + /// The module dependency collector for crashdumps + std::shared_ptr<ModuleDependencyCollector> ModuleDepCollector; + + /// The module provider. + std::shared_ptr<PCHContainerOperations> ThePCHContainerOperations; + + /// The dependency file generator. + std::unique_ptr<DependencyFileGenerator> TheDependencyFileGenerator; + + std::vector<std::shared_ptr<DependencyCollector>> DependencyCollectors; + + /// The set of top-level modules that has already been loaded, + /// along with the module map + llvm::DenseMap<const IdentifierInfo *, Module *> KnownModules; + + /// The set of top-level modules that has already been built on the + /// fly as part of this overall compilation action. + std::map<std::string, std::string> BuiltModules; + + /// Should we delete the BuiltModules when we're done? + bool DeleteBuiltModules = true; + + /// The location of the module-import keyword for the last module + /// import. + SourceLocation LastModuleImportLoc; + + /// The result of the last module import. + /// + ModuleLoadResult LastModuleImportResult; + + /// Whether we should (re)build the global module index once we + /// have finished with this translation unit. + bool BuildGlobalModuleIndex = false; + + /// We have a full global module index, with all modules. + bool HaveFullGlobalModuleIndex = false; + + /// One or more modules failed to build. + bool ModuleBuildFailed = false; + + /// Holds information about the output file. + /// + /// If TempFilename is not empty we must rename it to Filename at the end. + /// TempFilename may be empty and Filename non-empty if creating the temporary + /// failed. + struct OutputFile { + std::string Filename; + std::string TempFilename; + + OutputFile(std::string filename, std::string tempFilename) + : Filename(std::move(filename)), TempFilename(std::move(tempFilename)) { + } + }; + + /// If the output doesn't support seeking (terminal, pipe). we switch + /// the stream to a buffer_ostream. These are the buffer and the original + /// stream. + std::unique_ptr<llvm::raw_fd_ostream> NonSeekStream; + + /// The list of active output files. + std::list<OutputFile> OutputFiles; + + /// Force an output buffer. + std::unique_ptr<llvm::raw_pwrite_stream> OutputStream; + + CompilerInstance(const CompilerInstance &) = delete; + void operator=(const CompilerInstance &) = delete; +public: + explicit CompilerInstance( + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>(), + MemoryBufferCache *SharedPCMCache = nullptr); + ~CompilerInstance() override; + + /// @name High-Level Operations + /// { + + /// ExecuteAction - Execute the provided action against the compiler's + /// CompilerInvocation object. + /// + /// This function makes the following assumptions: + /// + /// - The invocation options should be initialized. This function does not + /// handle the '-help' or '-version' options, clients should handle those + /// directly. + /// + /// - The diagnostics engine should have already been created by the client. + /// + /// - No other CompilerInstance state should have been initialized (this is + /// an unchecked error). + /// + /// - Clients should have initialized any LLVM target features that may be + /// required. + /// + /// - Clients should eventually call llvm_shutdown() upon the completion of + /// this routine to ensure that any managed objects are properly destroyed. + /// + /// Note that this routine may write output to 'stderr'. + /// + /// \param Act - The action to execute. + /// \return - True on success. + // + // FIXME: This function should take the stream to write any debugging / + // verbose output to as an argument. + // + // FIXME: Eliminate the llvm_shutdown requirement, that should either be part + // of the context or else not CompilerInstance specific. + bool ExecuteAction(FrontendAction &Act); + + /// } + /// @name Compiler Invocation and Options + /// { + + bool hasInvocation() const { return Invocation != nullptr; } + + CompilerInvocation &getInvocation() { + assert(Invocation && "Compiler instance has no invocation!"); + return *Invocation; + } + + /// setInvocation - Replace the current invocation. + void setInvocation(std::shared_ptr<CompilerInvocation> Value); + + /// Indicates whether we should (re)build the global module index. + bool shouldBuildGlobalModuleIndex() const; + + /// Set the flag indicating whether we should (re)build the global + /// module index. + void setBuildGlobalModuleIndex(bool Build) { + BuildGlobalModuleIndex = Build; + } + + /// } + /// @name Forwarding Methods + /// { + + AnalyzerOptionsRef getAnalyzerOpts() { + return Invocation->getAnalyzerOpts(); + } + + CodeGenOptions &getCodeGenOpts() { + return Invocation->getCodeGenOpts(); + } + const CodeGenOptions &getCodeGenOpts() const { + return Invocation->getCodeGenOpts(); + } + + DependencyOutputOptions &getDependencyOutputOpts() { + return Invocation->getDependencyOutputOpts(); + } + const DependencyOutputOptions &getDependencyOutputOpts() const { + return Invocation->getDependencyOutputOpts(); + } + + DiagnosticOptions &getDiagnosticOpts() { + return Invocation->getDiagnosticOpts(); + } + const DiagnosticOptions &getDiagnosticOpts() const { + return Invocation->getDiagnosticOpts(); + } + + FileSystemOptions &getFileSystemOpts() { + return Invocation->getFileSystemOpts(); + } + const FileSystemOptions &getFileSystemOpts() const { + return Invocation->getFileSystemOpts(); + } + + FrontendOptions &getFrontendOpts() { + return Invocation->getFrontendOpts(); + } + const FrontendOptions &getFrontendOpts() const { + return Invocation->getFrontendOpts(); + } + + HeaderSearchOptions &getHeaderSearchOpts() { + return Invocation->getHeaderSearchOpts(); + } + const HeaderSearchOptions &getHeaderSearchOpts() const { + return Invocation->getHeaderSearchOpts(); + } + std::shared_ptr<HeaderSearchOptions> getHeaderSearchOptsPtr() const { + return Invocation->getHeaderSearchOptsPtr(); + } + + LangOptions &getLangOpts() { + return *Invocation->getLangOpts(); + } + const LangOptions &getLangOpts() const { + return *Invocation->getLangOpts(); + } + + PreprocessorOptions &getPreprocessorOpts() { + return Invocation->getPreprocessorOpts(); + } + const PreprocessorOptions &getPreprocessorOpts() const { + return Invocation->getPreprocessorOpts(); + } + + PreprocessorOutputOptions &getPreprocessorOutputOpts() { + return Invocation->getPreprocessorOutputOpts(); + } + const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { + return Invocation->getPreprocessorOutputOpts(); + } + + TargetOptions &getTargetOpts() { + return Invocation->getTargetOpts(); + } + const TargetOptions &getTargetOpts() const { + return Invocation->getTargetOpts(); + } + + /// } + /// @name Diagnostics Engine + /// { + + bool hasDiagnostics() const { return Diagnostics != nullptr; } + + /// Get the current diagnostics engine. + DiagnosticsEngine &getDiagnostics() const { + assert(Diagnostics && "Compiler instance has no diagnostics!"); + return *Diagnostics; + } + + /// setDiagnostics - Replace the current diagnostics engine. + void setDiagnostics(DiagnosticsEngine *Value); + + DiagnosticConsumer &getDiagnosticClient() const { + assert(Diagnostics && Diagnostics->getClient() && + "Compiler instance has no diagnostic client!"); + return *Diagnostics->getClient(); + } + + /// } + /// @name Target Info + /// { + + bool hasTarget() const { return Target != nullptr; } + + TargetInfo &getTarget() const { + assert(Target && "Compiler instance has no target!"); + return *Target; + } + + /// Replace the current Target. + void setTarget(TargetInfo *Value); + + /// } + /// @name AuxTarget Info + /// { + + TargetInfo *getAuxTarget() const { return AuxTarget.get(); } + + /// Replace the current AuxTarget. + void setAuxTarget(TargetInfo *Value); + + /// } + /// @name Virtual File System + /// { + + bool hasVirtualFileSystem() const { return VirtualFileSystem != nullptr; } + + llvm::vfs::FileSystem &getVirtualFileSystem() const { + assert(hasVirtualFileSystem() && + "Compiler instance has no virtual file system"); + return *VirtualFileSystem; + } + + /// Replace the current virtual file system. + /// + /// \note Most clients should use setFileManager, which will implicitly reset + /// the virtual file system to the one contained in the file manager. + void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) { + VirtualFileSystem = std::move(FS); + } + + /// } + /// @name File Manager + /// { + + bool hasFileManager() const { return FileMgr != nullptr; } + + /// Return the current file manager to the caller. + FileManager &getFileManager() const { + assert(FileMgr && "Compiler instance has no file manager!"); + return *FileMgr; + } + + void resetAndLeakFileManager() { + llvm::BuryPointer(FileMgr.get()); + FileMgr.resetWithoutRelease(); + } + + /// Replace the current file manager and virtual file system. + void setFileManager(FileManager *Value); + + /// } + /// @name Source Manager + /// { + + bool hasSourceManager() const { return SourceMgr != nullptr; } + + /// Return the current source manager. + SourceManager &getSourceManager() const { + assert(SourceMgr && "Compiler instance has no source manager!"); + return *SourceMgr; + } + + void resetAndLeakSourceManager() { + llvm::BuryPointer(SourceMgr.get()); + SourceMgr.resetWithoutRelease(); + } + + /// setSourceManager - Replace the current source manager. + void setSourceManager(SourceManager *Value); + + /// } + /// @name Preprocessor + /// { + + bool hasPreprocessor() const { return PP != nullptr; } + + /// Return the current preprocessor. + Preprocessor &getPreprocessor() const { + assert(PP && "Compiler instance has no preprocessor!"); + return *PP; + } + + std::shared_ptr<Preprocessor> getPreprocessorPtr() { return PP; } + + void resetAndLeakPreprocessor() { + llvm::BuryPointer(new std::shared_ptr<Preprocessor>(PP)); + } + + /// Replace the current preprocessor. + void setPreprocessor(std::shared_ptr<Preprocessor> Value); + + /// } + /// @name ASTContext + /// { + + bool hasASTContext() const { return Context != nullptr; } + + ASTContext &getASTContext() const { + assert(Context && "Compiler instance has no AST context!"); + return *Context; + } + + void resetAndLeakASTContext() { + llvm::BuryPointer(Context.get()); + Context.resetWithoutRelease(); + } + + /// setASTContext - Replace the current AST context. + void setASTContext(ASTContext *Value); + + /// Replace the current Sema; the compiler instance takes ownership + /// of S. + void setSema(Sema *S); + + /// } + /// @name ASTConsumer + /// { + + bool hasASTConsumer() const { return (bool)Consumer; } + + ASTConsumer &getASTConsumer() const { + assert(Consumer && "Compiler instance has no AST consumer!"); + return *Consumer; + } + + /// takeASTConsumer - Remove the current AST consumer and give ownership to + /// the caller. + std::unique_ptr<ASTConsumer> takeASTConsumer() { return std::move(Consumer); } + + /// setASTConsumer - Replace the current AST consumer; the compiler instance + /// takes ownership of \p Value. + void setASTConsumer(std::unique_ptr<ASTConsumer> Value); + + /// } + /// @name Semantic analysis + /// { + bool hasSema() const { return (bool)TheSema; } + + Sema &getSema() const { + assert(TheSema && "Compiler instance has no Sema object!"); + return *TheSema; + } + + std::unique_ptr<Sema> takeSema(); + void resetAndLeakSema(); + + /// } + /// @name Module Management + /// { + + IntrusiveRefCntPtr<ASTReader> getModuleManager() const; + void setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader); + + std::shared_ptr<ModuleDependencyCollector> getModuleDepCollector() const; + void setModuleDepCollector( + std::shared_ptr<ModuleDependencyCollector> Collector); + + std::shared_ptr<PCHContainerOperations> getPCHContainerOperations() const { + return ThePCHContainerOperations; + } + + /// Return the appropriate PCHContainerWriter depending on the + /// current CodeGenOptions. + const PCHContainerWriter &getPCHContainerWriter() const { + assert(Invocation && "cannot determine module format without invocation"); + StringRef Format = getHeaderSearchOpts().ModuleFormat; + auto *Writer = ThePCHContainerOperations->getWriterOrNull(Format); + if (!Writer) { + if (Diagnostics) + Diagnostics->Report(diag::err_module_format_unhandled) << Format; + llvm::report_fatal_error("unknown module format"); + } + return *Writer; + } + + /// Return the appropriate PCHContainerReader depending on the + /// current CodeGenOptions. + const PCHContainerReader &getPCHContainerReader() const { + assert(Invocation && "cannot determine module format without invocation"); + StringRef Format = getHeaderSearchOpts().ModuleFormat; + auto *Reader = ThePCHContainerOperations->getReaderOrNull(Format); + if (!Reader) { + if (Diagnostics) + Diagnostics->Report(diag::err_module_format_unhandled) << Format; + llvm::report_fatal_error("unknown module format"); + } + return *Reader; + } + + /// } + /// @name Code Completion + /// { + + bool hasCodeCompletionConsumer() const { return (bool)CompletionConsumer; } + + CodeCompleteConsumer &getCodeCompletionConsumer() const { + assert(CompletionConsumer && + "Compiler instance has no code completion consumer!"); + return *CompletionConsumer; + } + + /// setCodeCompletionConsumer - Replace the current code completion consumer; + /// the compiler instance takes ownership of \p Value. + void setCodeCompletionConsumer(CodeCompleteConsumer *Value); + + /// } + /// @name Frontend timer + /// { + + bool hasFrontendTimer() const { return (bool)FrontendTimer; } + + llvm::Timer &getFrontendTimer() const { + assert(FrontendTimer && "Compiler instance has no frontend timer!"); + return *FrontendTimer; + } + + /// } + /// @name Output Files + /// { + + /// addOutputFile - Add an output file onto the list of tracked output files. + /// + /// \param OutFile - The output file info. + void addOutputFile(OutputFile &&OutFile); + + /// clearOutputFiles - Clear the output file list. The underlying output + /// streams must have been closed beforehand. + /// + /// \param EraseFiles - If true, attempt to erase the files from disk. + void clearOutputFiles(bool EraseFiles); + + /// } + /// @name Construction Utility Methods + /// { + + /// Create the diagnostics engine using the invocation's diagnostic options + /// and replace any existing one with it. + /// + /// Note that this routine also replaces the diagnostic client, + /// allocating one if one is not provided. + /// + /// \param Client If non-NULL, a diagnostic client that will be + /// attached to (and, then, owned by) the DiagnosticsEngine inside this AST + /// unit. + /// + /// \param ShouldOwnClient If Client is non-NULL, specifies whether + /// the diagnostic object should take ownership of the client. + void createDiagnostics(DiagnosticConsumer *Client = nullptr, + bool ShouldOwnClient = true); + + /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter. + /// + /// If no diagnostic client is provided, this creates a + /// DiagnosticConsumer that is owned by the returned diagnostic + /// object, if using directly the caller is responsible for + /// releasing the returned DiagnosticsEngine's client eventually. + /// + /// \param Opts - The diagnostic options; note that the created text + /// diagnostic object contains a reference to these options. + /// + /// \param Client If non-NULL, a diagnostic client that will be + /// attached to (and, then, owned by) the returned DiagnosticsEngine + /// object. + /// + /// \param CodeGenOpts If non-NULL, the code gen options in use, which may be + /// used by some diagnostics printers (for logging purposes only). + /// + /// \return The new object on success, or null on failure. + static IntrusiveRefCntPtr<DiagnosticsEngine> + createDiagnostics(DiagnosticOptions *Opts, + DiagnosticConsumer *Client = nullptr, + bool ShouldOwnClient = true, + const CodeGenOptions *CodeGenOpts = nullptr); + + /// Create the file manager and replace any existing one with it. + /// + /// \return The new file manager on success, or null on failure. + FileManager *createFileManager(); + + /// Create the source manager and replace any existing one with it. + void createSourceManager(FileManager &FileMgr); + + /// Create the preprocessor, using the invocation, file, and source managers, + /// and replace any existing one with it. + void createPreprocessor(TranslationUnitKind TUKind); + + std::string getSpecificModuleCachePath(); + + /// Create the AST context. + void createASTContext(); + + /// Create an external AST source to read a PCH file and attach it to the AST + /// context. + void createPCHExternalASTSource(StringRef Path, bool DisablePCHValidation, + bool AllowPCHWithCompilerErrors, + void *DeserializationListener, + bool OwnDeserializationListener); + + /// Create an external AST source to read a PCH file. + /// + /// \return - The new object on success, or null on failure. + static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource( + StringRef Path, StringRef Sysroot, bool DisablePCHValidation, + bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, + const PCHContainerReader &PCHContainerRdr, + ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, + DependencyFileGenerator *DependencyFile, + ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors, + void *DeserializationListener, bool OwnDeserializationListener, + bool Preamble, bool UseGlobalModuleIndex); + + /// Create a code completion consumer using the invocation; note that this + /// will cause the source manager to truncate the input source file at the + /// completion point. + void createCodeCompletionConsumer(); + + /// Create a code completion consumer to print code completion results, at + /// \p Filename, \p Line, and \p Column, to the given output stream \p OS. + static CodeCompleteConsumer *createCodeCompletionConsumer( + Preprocessor &PP, StringRef Filename, unsigned Line, unsigned Column, + const CodeCompleteOptions &Opts, raw_ostream &OS); + + /// Create the Sema object to be used for parsing. + void createSema(TranslationUnitKind TUKind, + CodeCompleteConsumer *CompletionConsumer); + + /// Create the frontend timer and replace any existing one with it. + void createFrontendTimer(); + + /// Create the default output file (from the invocation's options) and add it + /// to the list of tracked output files. + /// + /// The files created by this function always use temporary files to write to + /// their result (that is, the data is written to a temporary file which will + /// atomically replace the target output on success). + /// + /// \return - Null on error. + std::unique_ptr<raw_pwrite_stream> + createDefaultOutputFile(bool Binary = true, StringRef BaseInput = "", + StringRef Extension = ""); + + /// Create a new output file and add it to the list of tracked output files, + /// optionally deriving the output path name. + /// + /// \return - Null on error. + std::unique_ptr<raw_pwrite_stream> + createOutputFile(StringRef OutputPath, bool Binary, bool RemoveFileOnSignal, + StringRef BaseInput, StringRef Extension, bool UseTemporary, + bool CreateMissingDirectories = false); + + /// Create a new output file, optionally deriving the output path name. + /// + /// If \p OutputPath is empty, then createOutputFile will derive an output + /// path location as \p BaseInput, with any suffix removed, and \p Extension + /// appended. If \p OutputPath is not stdout and \p UseTemporary + /// is true, createOutputFile will create a new temporary file that must be + /// renamed to \p OutputPath in the end. + /// + /// \param OutputPath - If given, the path to the output file. + /// \param Error [out] - On failure, the error. + /// \param BaseInput - If \p OutputPath is empty, the input path name to use + /// for deriving the output path. + /// \param Extension - The extension to use for derived output names. + /// \param Binary - The mode to open the file in. + /// \param RemoveFileOnSignal - Whether the file should be registered with + /// llvm::sys::RemoveFileOnSignal. Note that this is not safe for + /// multithreaded use, as the underlying signal mechanism is not reentrant + /// \param UseTemporary - Create a new temporary file that must be renamed to + /// OutputPath in the end. + /// \param CreateMissingDirectories - When \p UseTemporary is true, create + /// missing directories in the output path. + /// \param ResultPathName [out] - If given, the result path name will be + /// stored here on success. + /// \param TempPathName [out] - If given, the temporary file path name + /// will be stored here on success. + std::unique_ptr<raw_pwrite_stream> + createOutputFile(StringRef OutputPath, std::error_code &Error, bool Binary, + bool RemoveFileOnSignal, StringRef BaseInput, + StringRef Extension, bool UseTemporary, + bool CreateMissingDirectories, std::string *ResultPathName, + std::string *TempPathName); + + std::unique_ptr<raw_pwrite_stream> createNullOutputFile(); + + /// } + /// @name Initialization Utility Methods + /// { + + /// InitializeSourceManager - Initialize the source manager to set InputFile + /// as the main file. + /// + /// \return True on success. + bool InitializeSourceManager(const FrontendInputFile &Input); + + /// InitializeSourceManager - Initialize the source manager to set InputFile + /// as the main file. + /// + /// \return True on success. + static bool InitializeSourceManager(const FrontendInputFile &Input, + DiagnosticsEngine &Diags, + FileManager &FileMgr, + SourceManager &SourceMgr, + HeaderSearch *HS, + DependencyOutputOptions &DepOpts, + const FrontendOptions &Opts); + + /// } + + void setOutputStream(std::unique_ptr<llvm::raw_pwrite_stream> OutStream) { + OutputStream = std::move(OutStream); + } + + std::unique_ptr<llvm::raw_pwrite_stream> takeOutputStream() { + return std::move(OutputStream); + } + + // Create module manager. + void createModuleManager(); + + bool loadModuleFile(StringRef FileName); + + ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) override; + + void loadModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName, + StringRef Source) override; + + void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility, + SourceLocation ImportLoc) override; + + bool hadModuleLoaderFatalFailure() const { + return ModuleLoader::HadFatalFailure; + } + + GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override; + + bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override; + + void addDependencyCollector(std::shared_ptr<DependencyCollector> Listener) { + DependencyCollectors.push_back(std::move(Listener)); + } + + void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS); + + MemoryBufferCache &getPCMCache() const { return *PCMCache; } +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/CompilerInvocation.h b/clang-r353983/include/clang/Frontend/CompilerInvocation.h new file mode 100644 index 00000000..413134be --- /dev/null +++ b/clang-r353983/include/clang/Frontend/CompilerInvocation.h @@ -0,0 +1,235 @@ +//===- CompilerInvocation.h - Compiler Invocation Helper Data ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H +#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H + +#include "clang/Basic/CodeGenOptions.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Frontend/DependencyOutputOptions.h" +#include "clang/Frontend/FrontendOptions.h" +#include "clang/Frontend/LangStandard.h" +#include "clang/Frontend/MigratorOptions.h" +#include "clang/Frontend/PreprocessorOutputOptions.h" +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include <memory> +#include <string> + +namespace llvm { + +class Triple; + +namespace opt { + +class ArgList; + +} // namespace opt + +namespace vfs { + +class FileSystem; + +} // namespace vfs + +} // namespace llvm + +namespace clang { + +class DiagnosticsEngine; +class HeaderSearchOptions; +class PreprocessorOptions; +class TargetOptions; + +/// Fill out Opts based on the options given in Args. +/// +/// Args must have been created from the OptTable returned by +/// createCC1OptTable(). +/// +/// When errors are encountered, return false and, if Diags is non-null, +/// report the error(s). +bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args, + DiagnosticsEngine *Diags = nullptr, + bool DefaultDiagColor = true, + bool DefaultShowOpt = true); + +class CompilerInvocationBase { +public: + /// Options controlling the language variant. + std::shared_ptr<LangOptions> LangOpts; + + /// Options controlling the target. + std::shared_ptr<TargetOptions> TargetOpts; + + /// Options controlling the diagnostic engine. + IntrusiveRefCntPtr<DiagnosticOptions> DiagnosticOpts; + + /// Options controlling the \#include directive. + std::shared_ptr<HeaderSearchOptions> HeaderSearchOpts; + + /// Options controlling the preprocessor (aside from \#include handling). + std::shared_ptr<PreprocessorOptions> PreprocessorOpts; + + CompilerInvocationBase(); + CompilerInvocationBase(const CompilerInvocationBase &X); + CompilerInvocationBase &operator=(const CompilerInvocationBase &) = delete; + ~CompilerInvocationBase(); + + LangOptions *getLangOpts() { return LangOpts.get(); } + const LangOptions *getLangOpts() const { return LangOpts.get(); } + + TargetOptions &getTargetOpts() { return *TargetOpts.get(); } + const TargetOptions &getTargetOpts() const { return *TargetOpts.get(); } + + DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; } + + HeaderSearchOptions &getHeaderSearchOpts() { return *HeaderSearchOpts; } + + const HeaderSearchOptions &getHeaderSearchOpts() const { + return *HeaderSearchOpts; + } + + std::shared_ptr<HeaderSearchOptions> getHeaderSearchOptsPtr() const { + return HeaderSearchOpts; + } + + std::shared_ptr<PreprocessorOptions> getPreprocessorOptsPtr() { + return PreprocessorOpts; + } + + PreprocessorOptions &getPreprocessorOpts() { return *PreprocessorOpts; } + + const PreprocessorOptions &getPreprocessorOpts() const { + return *PreprocessorOpts; + } +}; + +/// Helper class for holding the data necessary to invoke the compiler. +/// +/// This class is designed to represent an abstract "invocation" of the +/// compiler, including data such as the include paths, the code generation +/// options, the warning flags, and so on. +class CompilerInvocation : public CompilerInvocationBase { + /// Options controlling the static analyzer. + AnalyzerOptionsRef AnalyzerOpts; + + MigratorOptions MigratorOpts; + + /// Options controlling IRgen and the backend. + CodeGenOptions CodeGenOpts; + + /// Options controlling dependency output. + DependencyOutputOptions DependencyOutputOpts; + + /// Options controlling file system operations. + FileSystemOptions FileSystemOpts; + + /// Options controlling the frontend itself. + FrontendOptions FrontendOpts; + + /// Options controlling preprocessed output. + PreprocessorOutputOptions PreprocessorOutputOpts; + +public: + CompilerInvocation() : AnalyzerOpts(new AnalyzerOptions()) {} + + /// @name Utility Methods + /// @{ + + /// Create a compiler invocation from a list of input options. + /// \returns true on success. + /// + /// \param [out] Res - The resulting invocation. + /// \param ArgBegin - The first element in the argument vector. + /// \param ArgEnd - The last element in the argument vector. + /// \param Diags - The diagnostic engine to use for errors. + static bool CreateFromArgs(CompilerInvocation &Res, + const char* const *ArgBegin, + const char* const *ArgEnd, + DiagnosticsEngine &Diags); + + /// Get the directory where the compiler headers + /// reside, relative to the compiler binary (found by the passed in + /// arguments). + /// + /// \param Argv0 - The program path (from argv[0]), for finding the builtin + /// compiler path. + /// \param MainAddr - The address of main (or some other function in the main + /// executable), for finding the builtin compiler path. + static std::string GetResourcesPath(const char *Argv0, void *MainAddr); + + /// Set language defaults for the given input language and + /// language standard in the given LangOptions object. + /// + /// \param Opts - The LangOptions object to set up. + /// \param IK - The input language. + /// \param T - The target triple. + /// \param PPOpts - The PreprocessorOptions affected. + /// \param LangStd - The input language standard. + static void setLangDefaults(LangOptions &Opts, InputKind IK, + const llvm::Triple &T, PreprocessorOptions &PPOpts, + LangStandard::Kind LangStd = LangStandard::lang_unspecified); + + /// Retrieve a module hash string that is suitable for uniquely + /// identifying the conditions under which the module was built. + std::string getModuleHash() const; + + /// @} + /// @name Option Subgroups + /// @{ + + AnalyzerOptionsRef getAnalyzerOpts() const { return AnalyzerOpts; } + + MigratorOptions &getMigratorOpts() { return MigratorOpts; } + const MigratorOptions &getMigratorOpts() const { return MigratorOpts; } + + CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; } + const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } + + DependencyOutputOptions &getDependencyOutputOpts() { + return DependencyOutputOpts; + } + + const DependencyOutputOptions &getDependencyOutputOpts() const { + return DependencyOutputOpts; + } + + FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; } + + const FileSystemOptions &getFileSystemOpts() const { + return FileSystemOpts; + } + + FrontendOptions &getFrontendOpts() { return FrontendOpts; } + const FrontendOptions &getFrontendOpts() const { return FrontendOpts; } + + PreprocessorOutputOptions &getPreprocessorOutputOpts() { + return PreprocessorOutputOpts; + } + + const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { + return PreprocessorOutputOpts; + } + + /// @} +}; + +IntrusiveRefCntPtr<llvm::vfs::FileSystem> +createVFSFromCompilerInvocation(const CompilerInvocation &CI, + DiagnosticsEngine &Diags); + +IntrusiveRefCntPtr<llvm::vfs::FileSystem> createVFSFromCompilerInvocation( + const CompilerInvocation &CI, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS); + +} // namespace clang + +#endif // LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H diff --git a/clang-r353983/include/clang/Frontend/DependencyOutputOptions.h b/clang-r353983/include/clang/Frontend/DependencyOutputOptions.h new file mode 100644 index 00000000..7a4f3337 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/DependencyOutputOptions.h @@ -0,0 +1,74 @@ +//===--- DependencyOutputOptions.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H +#define LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H + +#include <string> +#include <vector> + +namespace clang { + +/// ShowIncludesDestination - Destination for /showIncludes output. +enum class ShowIncludesDestination { None, Stdout, Stderr }; + +/// DependencyOutputFormat - Format for the compiler dependency file. +enum class DependencyOutputFormat { Make, NMake }; + +/// DependencyOutputOptions - Options for controlling the compiler dependency +/// file generation. +class DependencyOutputOptions { +public: + unsigned IncludeSystemHeaders : 1; ///< Include system header dependencies. + unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H). + unsigned UsePhonyTargets : 1; ///< Include phony targets for each + /// dependency, which can avoid some 'make' + /// problems. + unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list + unsigned IncludeModuleFiles : 1; ///< Include module file dependencies. + + /// Destination of cl.exe style /showIncludes info. + ShowIncludesDestination ShowIncludesDest = ShowIncludesDestination::None; + + /// The format for the dependency file. + DependencyOutputFormat OutputFormat = DependencyOutputFormat::Make; + + /// The file to write dependency output to. + std::string OutputFile; + + /// The file to write header include output to. This is orthogonal to + /// ShowHeaderIncludes (-H) and will include headers mentioned in the + /// predefines buffer. If the output file is "-", output will be sent to + /// stderr. + std::string HeaderIncludeOutputFile; + + /// A list of names to use as the targets in the dependency file; this list + /// must contain at least one entry. + std::vector<std::string> Targets; + + /// A list of filenames to be used as extra dependencies for every target. + std::vector<std::string> ExtraDeps; + + /// In /showIncludes mode, pretend the main TU is a header with this name. + std::string ShowIncludesPretendHeader; + + /// The file to write GraphViz-formatted header dependencies to. + std::string DOTOutputFile; + + /// The directory to copy module dependencies to when collecting them. + std::string ModuleDependencyOutputDir; + +public: + DependencyOutputOptions() + : IncludeSystemHeaders(0), ShowHeaderIncludes(0), UsePhonyTargets(0), + AddMissingHeaderDeps(0), IncludeModuleFiles(0) {} +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/DiagnosticRenderer.h b/clang-r353983/include/clang/Frontend/DiagnosticRenderer.h new file mode 100644 index 00000000..b939ebe9 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/DiagnosticRenderer.h @@ -0,0 +1,163 @@ +//===- DiagnosticRenderer.h - Diagnostic Pretty-Printing --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is a utility class that provides support for pretty-printing of +// diagnostics. It is used to implement the different code paths which require +// such functionality in a consistent way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H +#define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { + +class LangOptions; +class SourceManager; + +using DiagOrStoredDiag = + llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *>; + +/// Class to encapsulate the logic for formatting a diagnostic message. +/// +/// Actual "printing" logic is implemented by subclasses. +/// +/// This class provides an interface for building and emitting +/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt +/// Hints, and code snippets. In the presence of macros this involves +/// a recursive process, synthesizing notes for each macro expansion. +/// +/// A brief worklist: +/// FIXME: Sink the recursive printing of template instantiations into this +/// class. +class DiagnosticRenderer { +protected: + const LangOptions &LangOpts; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; + + /// The location of the previous diagnostic if known. + /// + /// This will be invalid in cases where there is no (known) previous + /// diagnostic location, or that location itself is invalid or comes from + /// a different source manager than SM. + SourceLocation LastLoc; + + /// The location of the last include whose stack was printed if known. + /// + /// Same restriction as LastLoc essentially, but tracking include stack + /// root locations rather than diagnostic locations. + SourceLocation LastIncludeLoc; + + /// The level of the last diagnostic emitted. + /// + /// The level of the last diagnostic emitted. Used to detect level changes + /// which change the amount of information displayed. + DiagnosticsEngine::Level LastLevel = DiagnosticsEngine::Ignored; + + DiagnosticRenderer(const LangOptions &LangOpts, + DiagnosticOptions *DiagOpts); + + virtual ~DiagnosticRenderer(); + + virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + StringRef Message, + ArrayRef<CharSourceRange> Ranges, + DiagOrStoredDiag Info) = 0; + + virtual void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges) = 0; + + virtual void emitCodeContext(FullSourceLoc Loc, + DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange> &Ranges, + ArrayRef<FixItHint> Hints) = 0; + + virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) = 0; + virtual void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) = 0; + virtual void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) = 0; + + virtual void beginDiagnostic(DiagOrStoredDiag D, + DiagnosticsEngine::Level Level) {} + virtual void endDiagnostic(DiagOrStoredDiag D, + DiagnosticsEngine::Level Level) {} + +private: + void emitBasicNote(StringRef Message); + void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level); + void emitIncludeStackRecursively(FullSourceLoc Loc); + void emitImportStack(FullSourceLoc Loc); + void emitImportStackRecursively(FullSourceLoc Loc, StringRef ModuleName); + void emitModuleBuildStack(const SourceManager &SM); + void emitCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints); + void emitSingleMacroExpansion(FullSourceLoc Loc, + DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges); + void emitMacroExpansions(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges, + ArrayRef<FixItHint> Hints); + +public: + /// Emit a diagnostic. + /// + /// This is the primary entry point for emitting diagnostic messages. + /// It handles formatting and rendering the message as well as any ancillary + /// information needed based on macros whose expansions impact the + /// diagnostic. + /// + /// \param Loc The location for this caret. + /// \param Level The level of the diagnostic to be emitted. + /// \param Message The diagnostic message to emit. + /// \param Ranges The underlined ranges for this code snippet. + /// \param FixItHints The FixIt hints active for this diagnostic. + void emitDiagnostic(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + StringRef Message, ArrayRef<CharSourceRange> Ranges, + ArrayRef<FixItHint> FixItHints, + DiagOrStoredDiag D = (Diagnostic *)nullptr); + + void emitStoredDiagnostic(StoredDiagnostic &Diag); +}; + +/// Subclass of DiagnosticRender that turns all subdiagostics into explicit +/// notes. It is up to subclasses to further define the behavior. +class DiagnosticNoteRenderer : public DiagnosticRenderer { +public: + DiagnosticNoteRenderer(const LangOptions &LangOpts, + DiagnosticOptions *DiagOpts) + : DiagnosticRenderer(LangOpts, DiagOpts) {} + + ~DiagnosticNoteRenderer() override; + + void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override; + + void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) override; + + void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) override; + + virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0; +}; + +} // namespace clang + +#endif // LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H diff --git a/clang-r353983/include/clang/Frontend/FrontendAction.h b/clang-r353983/include/clang/Frontend/FrontendAction.h new file mode 100644 index 00000000..3a107d54 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/FrontendAction.h @@ -0,0 +1,330 @@ +//===-- FrontendAction.h - Generic Frontend Action Interface ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines the clang::FrontendAction interface and various convenience +/// abstract classes (clang::ASTFrontendAction, clang::PluginASTAction, +/// clang::PreprocessorFrontendAction, and clang::WrapperFrontendAction) +/// derived from it. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H +#define LLVM_CLANG_FRONTEND_FRONTENDACTION_H + +#include "clang/AST/ASTConsumer.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Frontend/ASTUnit.h" +#include "clang/Frontend/FrontendOptions.h" +#include "llvm/ADT/StringRef.h" +#include <memory> +#include <string> +#include <vector> + +namespace clang { +class ASTMergeAction; +class CompilerInstance; + +/// Abstract base class for actions which can be performed by the frontend. +class FrontendAction { + FrontendInputFile CurrentInput; + std::unique_ptr<ASTUnit> CurrentASTUnit; + CompilerInstance *Instance; + friend class ASTMergeAction; + friend class WrapperFrontendAction; + +private: + std::unique_ptr<ASTConsumer> CreateWrappedASTConsumer(CompilerInstance &CI, + StringRef InFile); + +protected: + /// @name Implementation Action Interface + /// @{ + + /// Prepare to execute the action on the given CompilerInstance. + /// + /// This is called before executing the action on any inputs, and can modify + /// the configuration as needed (including adjusting the input list). + virtual bool PrepareToExecuteAction(CompilerInstance &CI) { return true; } + + /// Create the AST consumer object for this action, if supported. + /// + /// This routine is called as part of BeginSourceFile(), which will + /// fail if the AST consumer cannot be created. This will not be called if the + /// action has indicated that it only uses the preprocessor. + /// + /// \param CI - The current compiler instance, provided as a convenience, see + /// getCompilerInstance(). + /// + /// \param InFile - The current input file, provided as a convenience, see + /// getCurrentFile(). + /// + /// \return The new AST consumer, or null on failure. + virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) = 0; + + /// Callback before starting processing a single input, giving the + /// opportunity to modify the CompilerInvocation or do some other action + /// before BeginSourceFileAction is called. + /// + /// \return True on success; on failure BeginSourceFileAction(), + /// ExecuteAction() and EndSourceFileAction() will not be called. + virtual bool BeginInvocation(CompilerInstance &CI) { return true; } + + /// Callback at the start of processing a single input. + /// + /// \return True on success; on failure ExecutionAction() and + /// EndSourceFileAction() will not be called. + virtual bool BeginSourceFileAction(CompilerInstance &CI) { + return true; + } + + /// Callback to run the program action, using the initialized + /// compiler instance. + /// + /// This is guaranteed to only be called between BeginSourceFileAction() + /// and EndSourceFileAction(). + virtual void ExecuteAction() = 0; + + /// Callback at the end of processing a single input. + /// + /// This is guaranteed to only be called following a successful call to + /// BeginSourceFileAction (and BeginSourceFile). + virtual void EndSourceFileAction() {} + + /// Callback at the end of processing a single input, to determine + /// if the output files should be erased or not. + /// + /// By default it returns true if a compiler error occurred. + /// This is guaranteed to only be called following a successful call to + /// BeginSourceFileAction (and BeginSourceFile). + virtual bool shouldEraseOutputFiles(); + + /// @} + +public: + FrontendAction(); + virtual ~FrontendAction(); + + /// @name Compiler Instance Access + /// @{ + + CompilerInstance &getCompilerInstance() const { + assert(Instance && "Compiler instance not registered!"); + return *Instance; + } + + void setCompilerInstance(CompilerInstance *Value) { Instance = Value; } + + /// @} + /// @name Current File Information + /// @{ + + bool isCurrentFileAST() const { + assert(!CurrentInput.isEmpty() && "No current file!"); + return (bool)CurrentASTUnit; + } + + const FrontendInputFile &getCurrentInput() const { + return CurrentInput; + } + + StringRef getCurrentFile() const { + assert(!CurrentInput.isEmpty() && "No current file!"); + return CurrentInput.getFile(); + } + + StringRef getCurrentFileOrBufferName() const { + assert(!CurrentInput.isEmpty() && "No current file!"); + return CurrentInput.isFile() + ? CurrentInput.getFile() + : CurrentInput.getBuffer()->getBufferIdentifier(); + } + + InputKind getCurrentFileKind() const { + assert(!CurrentInput.isEmpty() && "No current file!"); + return CurrentInput.getKind(); + } + + ASTUnit &getCurrentASTUnit() const { + assert(CurrentASTUnit && "No current AST unit!"); + return *CurrentASTUnit; + } + + Module *getCurrentModule() const; + + std::unique_ptr<ASTUnit> takeCurrentASTUnit() { + return std::move(CurrentASTUnit); + } + + void setCurrentInput(const FrontendInputFile &CurrentInput, + std::unique_ptr<ASTUnit> AST = nullptr); + + /// @} + /// @name Supported Modes + /// @{ + + /// Is this action invoked on a model file? + /// + /// Model files are incomplete translation units that relies on type + /// information from another translation unit. Check ParseModelFileAction for + /// details. + virtual bool isModelParsingAction() const { return false; } + + /// Does this action only use the preprocessor? + /// + /// If so no AST context will be created and this action will be invalid + /// with AST file inputs. + virtual bool usesPreprocessorOnly() const = 0; + + /// For AST-based actions, the kind of translation unit we're handling. + virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; } + + /// Does this action support use with PCH? + virtual bool hasPCHSupport() const { return true; } + + /// Does this action support use with AST files? + virtual bool hasASTFileSupport() const { return true; } + + /// Does this action support use with IR files? + virtual bool hasIRSupport() const { return false; } + + /// Does this action support use with code completion? + virtual bool hasCodeCompletionSupport() const { return false; } + + /// @} + /// @name Public Action Interface + /// @{ + + /// Prepare the action to execute on the given compiler instance. + bool PrepareToExecute(CompilerInstance &CI) { + return PrepareToExecuteAction(CI); + } + + /// Prepare the action for processing the input file \p Input. + /// + /// This is run after the options and frontend have been initialized, + /// but prior to executing any per-file processing. + /// + /// \param CI - The compiler instance this action is being run from. The + /// action may store and use this object up until the matching EndSourceFile + /// action. + /// + /// \param Input - The input filename and kind. Some input kinds are handled + /// specially, for example AST inputs, since the AST file itself contains + /// several objects which would normally be owned by the + /// CompilerInstance. When processing AST input files, these objects should + /// generally not be initialized in the CompilerInstance -- they will + /// automatically be shared with the AST file in between + /// BeginSourceFile() and EndSourceFile(). + /// + /// \return True on success; on failure the compilation of this file should + /// be aborted and neither Execute() nor EndSourceFile() should be called. + bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input); + + /// Set the source manager's main input file, and run the action. + bool Execute(); + + /// Perform any per-file post processing, deallocate per-file + /// objects, and run statistics and output file cleanup code. + void EndSourceFile(); + + /// @} +}; + +/// Abstract base class to use for AST consumer-based frontend actions. +class ASTFrontendAction : public FrontendAction { +protected: + /// Implement the ExecuteAction interface by running Sema on + /// the already-initialized AST consumer. + /// + /// This will also take care of instantiating a code completion consumer if + /// the user requested it and the action supports it. + void ExecuteAction() override; + +public: + ASTFrontendAction() {} + bool usesPreprocessorOnly() const override { return false; } +}; + +class PluginASTAction : public ASTFrontendAction { + virtual void anchor(); +public: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override = 0; + + /// Parse the given plugin command line arguments. + /// + /// \param CI - The compiler instance, for use in reporting diagnostics. + /// \return True if the parsing succeeded; otherwise the plugin will be + /// destroyed and no action run. The plugin is responsible for using the + /// CompilerInstance's Diagnostic object to report errors. + virtual bool ParseArgs(const CompilerInstance &CI, + const std::vector<std::string> &arg) = 0; + + enum ActionType { + Cmdline, ///< Action is determined by the cc1 command-line + ReplaceAction, ///< Replace the main action + AddBeforeMainAction, ///< Execute the action before the main action + AddAfterMainAction ///< Execute the action after the main action + }; + /// Get the action type for this plugin + /// + /// \return The action type. If the type is Cmdline then by default the + /// plugin does nothing and what it does is determined by the cc1 + /// command-line. + virtual ActionType getActionType() { return Cmdline; } +}; + +/// Abstract base class to use for preprocessor-based frontend actions. +class PreprocessorFrontendAction : public FrontendAction { +protected: + /// Provide a default implementation which returns aborts; + /// this method should never be called by FrontendAction clients. + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + +public: + bool usesPreprocessorOnly() const override { return true; } +}; + +/// A frontend action which simply wraps some other runtime-specified +/// frontend action. +/// +/// Deriving from this class allows an action to inject custom logic around +/// some existing action's behavior. It implements every virtual method in +/// the FrontendAction interface by forwarding to the wrapped action. +class WrapperFrontendAction : public FrontendAction { + std::unique_ptr<FrontendAction> WrappedAction; + +protected: + bool PrepareToExecuteAction(CompilerInstance &CI) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + bool BeginInvocation(CompilerInstance &CI) override; + bool BeginSourceFileAction(CompilerInstance &CI) override; + void ExecuteAction() override; + void EndSourceFileAction() override; + +public: + /// Construct a WrapperFrontendAction from an existing action, taking + /// ownership of it. + WrapperFrontendAction(std::unique_ptr<FrontendAction> WrappedAction); + + bool usesPreprocessorOnly() const override; + TranslationUnitKind getTranslationUnitKind() override; + bool hasPCHSupport() const override; + bool hasASTFileSupport() const override; + bool hasIRSupport() const override; + bool hasCodeCompletionSupport() const override; +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/FrontendActions.h b/clang-r353983/include/clang/Frontend/FrontendActions.h new file mode 100644 index 00000000..3acd1e77 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/FrontendActions.h @@ -0,0 +1,277 @@ +//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H +#define LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H + +#include "clang/Frontend/FrontendAction.h" +#include <string> +#include <vector> + +namespace clang { + +class Module; +class FileEntry; + +//===----------------------------------------------------------------------===// +// Custom Consumer Actions +//===----------------------------------------------------------------------===// + +class InitOnlyAction : public FrontendAction { + void ExecuteAction() override; + + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + +public: + // Don't claim to only use the preprocessor, we want to follow the AST path, + // but do nothing. + bool usesPreprocessorOnly() const override { return false; } +}; + +class DumpCompilerOptionsAction : public FrontendAction { + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override { + return nullptr; + } + + void ExecuteAction() override; + +public: + bool usesPreprocessorOnly() const override { return true; } +}; + +//===----------------------------------------------------------------------===// +// AST Consumer Actions +//===----------------------------------------------------------------------===// + +class ASTPrintAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; +}; + +class ASTDumpAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; +}; + +class ASTDeclListAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; +}; + +class ASTViewAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; +}; + +class DeclContextPrintAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; +}; + +class GeneratePCHAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + TranslationUnitKind getTranslationUnitKind() override { + return TU_Prefix; + } + + bool hasASTFileSupport() const override { return false; } + + bool shouldEraseOutputFiles() override; + +public: + /// Compute the AST consumer arguments that will be used to + /// create the PCHGenerator instance returned by CreateASTConsumer. + /// + /// \returns false if an error occurred, true otherwise. + static bool ComputeASTConsumerArguments(CompilerInstance &CI, + std::string &Sysroot); + + /// Creates file to write the PCH into and returns a stream to write it + /// into. On error, returns null. + static std::unique_ptr<llvm::raw_pwrite_stream> + CreateOutputFile(CompilerInstance &CI, StringRef InFile, + std::string &OutputFile); + + bool BeginSourceFileAction(CompilerInstance &CI) override; +}; + +class GenerateModuleAction : public ASTFrontendAction { + virtual std::unique_ptr<raw_pwrite_stream> + CreateOutputFile(CompilerInstance &CI, StringRef InFile) = 0; + +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + TranslationUnitKind getTranslationUnitKind() override { + return TU_Module; + } + + bool hasASTFileSupport() const override { return false; } +}; + +class GenerateModuleFromModuleMapAction : public GenerateModuleAction { +private: + bool BeginSourceFileAction(CompilerInstance &CI) override; + + std::unique_ptr<raw_pwrite_stream> + CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; +}; + +class GenerateModuleInterfaceAction : public GenerateModuleAction { +private: + bool BeginSourceFileAction(CompilerInstance &CI) override; + + std::unique_ptr<raw_pwrite_stream> + CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; +}; + +class GenerateHeaderModuleAction : public GenerateModuleAction { + /// The synthesized module input buffer for the current compilation. + std::unique_ptr<llvm::MemoryBuffer> Buffer; + std::vector<std::string> ModuleHeaders; + +private: + bool PrepareToExecuteAction(CompilerInstance &CI) override; + bool BeginSourceFileAction(CompilerInstance &CI) override; + + std::unique_ptr<raw_pwrite_stream> + CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; +}; + +class SyntaxOnlyAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + +public: + ~SyntaxOnlyAction() override; + bool hasCodeCompletionSupport() const override { return true; } +}; + +/// Dump information about the given module file, to be used for +/// basic debugging and discovery. +class DumpModuleInfoAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + bool BeginInvocation(CompilerInstance &CI) override; + void ExecuteAction() override; + +public: + bool hasPCHSupport() const override { return false; } + bool hasASTFileSupport() const override { return true; } + bool hasIRSupport() const override { return false; } + bool hasCodeCompletionSupport() const override { return false; } +}; + +class VerifyPCHAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + void ExecuteAction() override; + +public: + bool hasCodeCompletionSupport() const override { return false; } +}; + +class TemplightDumpAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + void ExecuteAction() override; +}; + +/** + * Frontend action adaptor that merges ASTs together. + * + * This action takes an existing AST file and "merges" it into the AST + * context, producing a merged context. This action is an action + * adaptor, which forwards most of its calls to another action that + * will consume the merged context. + */ +class ASTMergeAction : public FrontendAction { + /// The action that the merge action adapts. + std::unique_ptr<FrontendAction> AdaptedAction; + + /// The set of AST files to merge. + std::vector<std::string> ASTFiles; + +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + bool BeginSourceFileAction(CompilerInstance &CI) override; + + void ExecuteAction() override; + void EndSourceFileAction() override; + +public: + ASTMergeAction(std::unique_ptr<FrontendAction> AdaptedAction, + ArrayRef<std::string> ASTFiles); + ~ASTMergeAction() override; + + bool usesPreprocessorOnly() const override; + TranslationUnitKind getTranslationUnitKind() override; + bool hasPCHSupport() const override; + bool hasASTFileSupport() const override; + bool hasCodeCompletionSupport() const override; +}; + +class PrintPreambleAction : public FrontendAction { +protected: + void ExecuteAction() override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &, + StringRef) override { + return nullptr; + } + + bool usesPreprocessorOnly() const override { return true; } +}; + +//===----------------------------------------------------------------------===// +// Preprocessor Actions +//===----------------------------------------------------------------------===// + +class DumpRawTokensAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction() override; +}; + +class DumpTokensAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction() override; +}; + +class PreprocessOnlyAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction() override; +}; + +class PrintPreprocessedAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction() override; + + bool hasPCHSupport() const override { return true; } +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/FrontendDiagnostic.h b/clang-r353983/include/clang/Frontend/FrontendDiagnostic.h new file mode 100644 index 00000000..f41504d8 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/FrontendDiagnostic.h @@ -0,0 +1,14 @@ +//===--- DiagnosticFrontend.h - Diagnostics for frontend --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H +#define LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H + +#include "clang/Basic/DiagnosticFrontend.h" + +#endif diff --git a/clang-r353983/include/clang/Frontend/FrontendOptions.h b/clang-r353983/include/clang/Frontend/FrontendOptions.h new file mode 100644 index 00000000..4c4ed96d --- /dev/null +++ b/clang-r353983/include/clang/Frontend/FrontendOptions.h @@ -0,0 +1,458 @@ +//===- FrontendOptions.h ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H +#define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H + +#include "clang/Frontend/CommandLineSourceLoc.h" +#include "clang/Serialization/ModuleFileExtension.h" +#include "clang/Sema/CodeCompleteOptions.h" +#include "llvm/ADT/StringRef.h" +#include <cassert> +#include <memory> +#include <string> +#include <vector> +#include <unordered_map> + +namespace llvm { + +class MemoryBuffer; + +} // namespace llvm + +namespace clang { + +namespace frontend { + +enum ActionKind { + /// Parse ASTs and list Decl nodes. + ASTDeclList, + + /// Parse ASTs and dump them. + ASTDump, + + /// Parse ASTs and print them. + ASTPrint, + + /// Parse ASTs and view them in Graphviz. + ASTView, + + /// Dump the compiler configuration. + DumpCompilerOptions, + + /// Dump out raw tokens. + DumpRawTokens, + + /// Dump out preprocessed tokens. + DumpTokens, + + /// Emit a .s file. + EmitAssembly, + + /// Emit a .bc file. + EmitBC, + + /// Translate input source into HTML. + EmitHTML, + + /// Emit a .ll file. + EmitLLVM, + + /// Generate LLVM IR, but do not emit anything. + EmitLLVMOnly, + + /// Generate machine code, but don't emit anything. + EmitCodeGenOnly, + + /// Emit a .o file. + EmitObj, + + /// Parse and apply any fixits to the source. + FixIt, + + /// Generate pre-compiled module from a module map. + GenerateModule, + + /// Generate pre-compiled module from a C++ module interface file. + GenerateModuleInterface, + + /// Generate pre-compiled module from a set of header files. + GenerateHeaderModule, + + /// Generate pre-compiled header. + GeneratePCH, + + /// Only execute frontend initialization. + InitOnly, + + /// Dump information about a module file. + ModuleFileInfo, + + /// Load and verify that a PCH file is usable. + VerifyPCH, + + /// Parse and perform semantic analysis. + ParseSyntaxOnly, + + /// Run a plugin action, \see ActionName. + PluginAction, + + /// Print the "preamble" of the input file + PrintPreamble, + + /// -E mode. + PrintPreprocessedInput, + + /// Expand macros but not \#includes. + RewriteMacros, + + /// ObjC->C Rewriter. + RewriteObjC, + + /// Rewriter playground + RewriteTest, + + /// Run one or more source code analyses. + RunAnalysis, + + /// Dump template instantiations + TemplightDump, + + /// Run migrator. + MigrateSource, + + /// Just lex, no output. + RunPreprocessorOnly +}; + +} // namespace frontend + +/// The kind of a file that we've been handed as an input. +class InputKind { +private: + unsigned Lang : 4; + unsigned Fmt : 3; + unsigned Preprocessed : 1; + +public: + /// The language for the input, used to select and validate the language + /// standard and possible actions. + enum Language { + Unknown, + + /// Assembly: we accept this only so that we can preprocess it. + Asm, + + /// LLVM IR: we accept this so that we can run the optimizer on it, + /// and compile it to assembly or object code. + LLVM_IR, + + ///@{ Languages that the frontend can parse and compile. + C, + CXX, + ObjC, + ObjCXX, + OpenCL, + CUDA, + RenderScript, + HIP, + ///@} + }; + + /// The input file format. + enum Format { + Source, + ModuleMap, + Precompiled + }; + + constexpr InputKind(Language L = Unknown, Format F = Source, + bool PP = false) + : Lang(L), Fmt(F), Preprocessed(PP) {} + + Language getLanguage() const { return static_cast<Language>(Lang); } + Format getFormat() const { return static_cast<Format>(Fmt); } + bool isPreprocessed() const { return Preprocessed; } + + /// Is the input kind fully-unknown? + bool isUnknown() const { return Lang == Unknown && Fmt == Source; } + + /// Is the language of the input some dialect of Objective-C? + bool isObjectiveC() const { return Lang == ObjC || Lang == ObjCXX; } + + InputKind getPreprocessed() const { + return InputKind(getLanguage(), getFormat(), true); + } + + InputKind withFormat(Format F) const { + return InputKind(getLanguage(), F, isPreprocessed()); + } +}; + +/// An input file for the front end. +class FrontendInputFile { + /// The file name, or "-" to read from standard input. + std::string File; + + /// The input, if it comes from a buffer rather than a file. This object + /// does not own the buffer, and the caller is responsible for ensuring + /// that it outlives any users. + llvm::MemoryBuffer *Buffer = nullptr; + + /// The kind of input, e.g., C source, AST file, LLVM IR. + InputKind Kind; + + /// Whether we're dealing with a 'system' input (vs. a 'user' input). + bool IsSystem = false; + +public: + FrontendInputFile() = default; + FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false) + : File(File.str()), Kind(Kind), IsSystem(IsSystem) {} + FrontendInputFile(llvm::MemoryBuffer *Buffer, InputKind Kind, + bool IsSystem = false) + : Buffer(Buffer), Kind(Kind), IsSystem(IsSystem) {} + + InputKind getKind() const { return Kind; } + bool isSystem() const { return IsSystem; } + + bool isEmpty() const { return File.empty() && Buffer == nullptr; } + bool isFile() const { return !isBuffer(); } + bool isBuffer() const { return Buffer != nullptr; } + bool isPreprocessed() const { return Kind.isPreprocessed(); } + + StringRef getFile() const { + assert(isFile()); + return File; + } + + llvm::MemoryBuffer *getBuffer() const { + assert(isBuffer()); + return Buffer; + } +}; + +/// FrontendOptions - Options for controlling the behavior of the frontend. +class FrontendOptions { +public: + /// Disable memory freeing on exit. + unsigned DisableFree : 1; + + /// When generating PCH files, instruct the AST writer to create relocatable + /// PCH files. + unsigned RelocatablePCH : 1; + + /// Show the -help text. + unsigned ShowHelp : 1; + + /// Show frontend performance metrics and statistics. + unsigned ShowStats : 1; + + /// Show timers for individual actions. + unsigned ShowTimers : 1; + + /// Show the -version text. + unsigned ShowVersion : 1; + + /// Apply fixes even if there are unfixable errors. + unsigned FixWhatYouCan : 1; + + /// Apply fixes only for warnings. + unsigned FixOnlyWarnings : 1; + + /// Apply fixes and recompile. + unsigned FixAndRecompile : 1; + + /// Apply fixes to temporary files. + unsigned FixToTemporaries : 1; + + /// Emit ARC errors even if the migrator can fix them. + unsigned ARCMTMigrateEmitARCErrors : 1; + + /// Skip over function bodies to speed up parsing in cases you do not need + /// them (e.g. with code completion). + unsigned SkipFunctionBodies : 1; + + /// Whether we can use the global module index if available. + unsigned UseGlobalModuleIndex : 1; + + /// Whether we can generate the global module index if needed. + unsigned GenerateGlobalModuleIndex : 1; + + /// Whether we include declaration dumps in AST dumps. + unsigned ASTDumpDecls : 1; + + /// Whether we deserialize all decls when forming AST dumps. + unsigned ASTDumpAll : 1; + + /// Whether we include lookup table dumps in AST dumps. + unsigned ASTDumpLookups : 1; + + /// Whether we are performing an implicit module build. + unsigned BuildingImplicitModule : 1; + + /// Whether we should embed all used files into the PCM file. + unsigned ModulesEmbedAllFiles : 1; + + /// Whether timestamps should be written to the produced PCH file. + unsigned IncludeTimestamps : 1; + + CodeCompleteOptions CodeCompleteOpts; + + enum { + ARCMT_None, + ARCMT_Check, + ARCMT_Modify, + ARCMT_Migrate + } ARCMTAction = ARCMT_None; + + enum { + ObjCMT_None = 0, + + /// Enable migration to modern ObjC literals. + ObjCMT_Literals = 0x1, + + /// Enable migration to modern ObjC subscripting. + ObjCMT_Subscripting = 0x2, + + /// Enable migration to modern ObjC readonly property. + ObjCMT_ReadonlyProperty = 0x4, + + /// Enable migration to modern ObjC readwrite property. + ObjCMT_ReadwriteProperty = 0x8, + + /// Enable migration to modern ObjC property. + ObjCMT_Property = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty), + + /// Enable annotation of ObjCMethods of all kinds. + ObjCMT_Annotation = 0x10, + + /// Enable migration of ObjC methods to 'instancetype'. + ObjCMT_Instancetype = 0x20, + + /// Enable migration to NS_ENUM/NS_OPTIONS macros. + ObjCMT_NsMacros = 0x40, + + /// Enable migration to add conforming protocols. + ObjCMT_ProtocolConformance = 0x80, + + /// prefer 'atomic' property over 'nonatomic'. + ObjCMT_AtomicProperty = 0x100, + + /// annotate property with NS_RETURNS_INNER_POINTER + ObjCMT_ReturnsInnerPointerProperty = 0x200, + + /// use NS_NONATOMIC_IOSONLY for property 'atomic' attribute + ObjCMT_NsAtomicIOSOnlyProperty = 0x400, + + /// Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods. + ObjCMT_DesignatedInitializer = 0x800, + + /// Enable converting setter/getter expressions to property-dot syntx. + ObjCMT_PropertyDotSyntax = 0x1000, + + ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty | + ObjCMT_Annotation | ObjCMT_Instancetype | + ObjCMT_NsMacros | ObjCMT_ProtocolConformance | + ObjCMT_NsAtomicIOSOnlyProperty | + ObjCMT_DesignatedInitializer), + ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting | + ObjCMT_MigrateDecls | ObjCMT_PropertyDotSyntax) + }; + unsigned ObjCMTAction = ObjCMT_None; + std::string ObjCMTWhiteListPath; + + std::string MTMigrateDir; + std::string ARCMTMigrateReportOut; + + /// The input files and their types. + std::vector<FrontendInputFile> Inputs; + + /// When the input is a module map, the original module map file from which + /// that map was inferred, if any (for umbrella modules). + std::string OriginalModuleMap; + + /// The output file, if any. + std::string OutputFile; + + /// If given, the new suffix for fix-it rewritten files. + std::string FixItSuffix; + + /// If given, filter dumped AST Decl nodes by this substring. + std::string ASTDumpFilter; + + /// If given, enable code completion at the provided location. + ParsedSourceLocation CodeCompletionAt; + + /// The frontend action to perform. + frontend::ActionKind ProgramAction = frontend::ParseSyntaxOnly; + + /// The name of the action to run when using a plugin action. + std::string ActionName; + + /// Args to pass to the plugins + std::unordered_map<std::string,std::vector<std::string>> PluginArgs; + + /// The list of plugin actions to run in addition to the normal action. + std::vector<std::string> AddPluginActions; + + /// The list of plugins to load. + std::vector<std::string> Plugins; + + /// The list of module file extensions. + std::vector<std::shared_ptr<ModuleFileExtension>> ModuleFileExtensions; + + /// The list of module map files to load before processing the input. + std::vector<std::string> ModuleMapFiles; + + /// The list of additional prebuilt module files to load before + /// processing the input. + std::vector<std::string> ModuleFiles; + + /// The list of files to embed into the compiled module file. + std::vector<std::string> ModulesEmbedFiles; + + /// The list of AST files to merge. + std::vector<std::string> ASTMergeFiles; + + /// A list of arguments to forward to LLVM's option processing; this + /// should only be used for debugging and experimental features. + std::vector<std::string> LLVMArgs; + + /// File name of the file that will provide record layouts + /// (in the format produced by -fdump-record-layouts). + std::string OverrideRecordLayoutsFile; + + /// Auxiliary triple for CUDA compilation. + std::string AuxTriple; + + /// Filename to write statistics to. + std::string StatsFile; + +public: + FrontendOptions() + : DisableFree(false), RelocatablePCH(false), ShowHelp(false), + ShowStats(false), ShowTimers(false), ShowVersion(false), + FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), + FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), + SkipFunctionBodies(false), UseGlobalModuleIndex(true), + GenerateGlobalModuleIndex(true), ASTDumpDecls(false), + ASTDumpLookups(false), BuildingImplicitModule(false), + ModulesEmbedAllFiles(false), IncludeTimestamps(true) {} + + /// getInputKindForExtension - Return the appropriate input kind for a file + /// extension. For example, "c" would return InputKind::C. + /// + /// \return The input kind for the extension, or InputKind::Unknown if the + /// extension is not recognized. + static InputKind getInputKindForExtension(StringRef Extension); +}; + +} // namespace clang + +#endif // LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H diff --git a/clang-r353983/include/clang/Frontend/FrontendPluginRegistry.h b/clang-r353983/include/clang/Frontend/FrontendPluginRegistry.h new file mode 100644 index 00000000..81057853 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/FrontendPluginRegistry.h @@ -0,0 +1,26 @@ +//===- FrontendPluginRegistry.h ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Pluggable Frontend Action Interface +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H +#define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H + +#include "clang/Frontend/FrontendAction.h" +#include "llvm/Support/Registry.h" + +namespace clang { + +/// The frontend plugin registry. +using FrontendPluginRegistry = llvm::Registry<PluginASTAction>; + +} // namespace clang + +#endif // LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H diff --git a/clang-r353983/include/clang/Frontend/LangStandard.h b/clang-r353983/include/clang/Frontend/LangStandard.h new file mode 100644 index 00000000..406ca56c --- /dev/null +++ b/clang-r353983/include/clang/Frontend/LangStandard.h @@ -0,0 +1,113 @@ +//===--- LangStandard.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_LANGSTANDARD_H +#define LLVM_CLANG_FRONTEND_LANGSTANDARD_H + +#include "clang/Basic/LLVM.h" +#include "clang/Frontend/FrontendOptions.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { + +namespace frontend { + +enum LangFeatures { + LineComment = (1 << 0), + C99 = (1 << 1), + C11 = (1 << 2), + C17 = (1 << 3), + CPlusPlus = (1 << 4), + CPlusPlus11 = (1 << 5), + CPlusPlus14 = (1 << 6), + CPlusPlus17 = (1 << 7), + CPlusPlus2a = (1 << 8), + Digraphs = (1 << 9), + GNUMode = (1 << 10), + HexFloat = (1 << 11), + ImplicitInt = (1 << 12), + OpenCL = (1 << 13) +}; + +} + +/// LangStandard - Information about the properties of a particular language +/// standard. +struct LangStandard { + enum Kind { +#define LANGSTANDARD(id, name, lang, desc, features) \ + lang_##id, +#include "clang/Frontend/LangStandards.def" + lang_unspecified + }; + + const char *ShortName; + const char *Description; + unsigned Flags; + InputKind::Language Language; + +public: + /// getName - Get the name of this standard. + const char *getName() const { return ShortName; } + + /// getDescription - Get the description of this standard. + const char *getDescription() const { return Description; } + + /// Get the language that this standard describes. + InputKind::Language getLanguage() const { return Language; } + + /// Language supports '//' comments. + bool hasLineComments() const { return Flags & frontend::LineComment; } + + /// isC99 - Language is a superset of C99. + bool isC99() const { return Flags & frontend::C99; } + + /// isC11 - Language is a superset of C11. + bool isC11() const { return Flags & frontend::C11; } + + /// isC17 - Language is a superset of C17. + bool isC17() const { return Flags & frontend::C17; } + + /// isCPlusPlus - Language is a C++ variant. + bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; } + + /// isCPlusPlus11 - Language is a C++11 variant (or later). + bool isCPlusPlus11() const { return Flags & frontend::CPlusPlus11; } + + /// isCPlusPlus14 - Language is a C++14 variant (or later). + bool isCPlusPlus14() const { return Flags & frontend::CPlusPlus14; } + + /// isCPlusPlus17 - Language is a C++17 variant (or later). + bool isCPlusPlus17() const { return Flags & frontend::CPlusPlus17; } + + /// isCPlusPlus2a - Language is a post-C++17 variant (or later). + bool isCPlusPlus2a() const { return Flags & frontend::CPlusPlus2a; } + + + /// hasDigraphs - Language supports digraphs. + bool hasDigraphs() const { return Flags & frontend::Digraphs; } + + /// isGNUMode - Language includes GNU extensions. + bool isGNUMode() const { return Flags & frontend::GNUMode; } + + /// hasHexFloats - Language supports hexadecimal float constants. + bool hasHexFloats() const { return Flags & frontend::HexFloat; } + + /// hasImplicitInt - Language allows variables to be typed as int implicitly. + bool hasImplicitInt() const { return Flags & frontend::ImplicitInt; } + + /// isOpenCL - Language is a OpenCL variant. + bool isOpenCL() const { return Flags & frontend::OpenCL; } + + static const LangStandard &getLangStandardForKind(Kind K); + static const LangStandard *getLangStandardForName(StringRef Name); +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/LangStandards.def b/clang-r353983/include/clang/Frontend/LangStandards.def new file mode 100644 index 00000000..196cb43e --- /dev/null +++ b/clang-r353983/include/clang/Frontend/LangStandards.def @@ -0,0 +1,179 @@ +//===-- LangStandards.def - Language Standard Data --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LANGSTANDARD +#error "LANGSTANDARD must be defined before including this file" +#endif + +/// LANGSTANDARD(IDENT, NAME, LANG, DESC, FEATURES) +/// +/// \param IDENT - The name of the standard as a C++ identifier. +/// \param NAME - The name of the standard. +/// \param LANG - The InputKind::Language for which this is a standard. +/// \param DESC - A short description of the standard. +/// \param FEATURES - The standard features as flags, these are enums from the +/// clang::frontend namespace, which is assumed to be be available. + +/// LANGSTANDARD_ALIAS(IDENT, ALIAS) +/// \param IDENT - The name of the standard as a C++ identifier. +/// \param ALIAS - The alias of the standard. + +/// LANGSTANDARD_ALIAS_DEPR(IDENT, ALIAS) +/// Same as LANGSTANDARD_ALIAS, but for a deprecated alias. + +#ifndef LANGSTANDARD_ALIAS +#define LANGSTANDARD_ALIAS(IDENT, ALIAS) +#endif + +#ifndef LANGSTANDARD_ALIAS_DEPR +#define LANGSTANDARD_ALIAS_DEPR(IDENT, ALIAS) LANGSTANDARD_ALIAS(IDENT, ALIAS) +#endif + +// C89-ish modes. +LANGSTANDARD(c89, "c89", + C, "ISO C 1990", + ImplicitInt) +LANGSTANDARD_ALIAS(c89, "c90") +LANGSTANDARD_ALIAS(c89, "iso9899:1990") + +LANGSTANDARD(c94, "iso9899:199409", + C, "ISO C 1990 with amendment 1", + Digraphs | ImplicitInt) + +LANGSTANDARD(gnu89, "gnu89", + C, "ISO C 1990 with GNU extensions", + LineComment | Digraphs | GNUMode | ImplicitInt) +LANGSTANDARD_ALIAS(gnu89, "gnu90") + +// C99-ish modes +LANGSTANDARD(c99, "c99", + C, "ISO C 1999", + LineComment | C99 | Digraphs | HexFloat) +LANGSTANDARD_ALIAS(c99, "iso9899:1999") +LANGSTANDARD_ALIAS_DEPR(c99, "c9x") +LANGSTANDARD_ALIAS_DEPR(c99, "iso9899:199x") + +LANGSTANDARD(gnu99, "gnu99", + C, "ISO C 1999 with GNU extensions", + LineComment | C99 | Digraphs | GNUMode | HexFloat) +LANGSTANDARD_ALIAS_DEPR(gnu99, "gnu9x") + +// C11 modes +LANGSTANDARD(c11, "c11", + C, "ISO C 2011", + LineComment | C99 | C11 | Digraphs | HexFloat) +LANGSTANDARD_ALIAS(c11, "iso9899:2011") +LANGSTANDARD_ALIAS_DEPR(c11, "c1x") +LANGSTANDARD_ALIAS_DEPR(c11, "iso9899:201x") + +LANGSTANDARD(gnu11, "gnu11", + C, "ISO C 2011 with GNU extensions", + LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat) +LANGSTANDARD_ALIAS_DEPR(gnu11, "gnu1x") + +// C17 modes +LANGSTANDARD(c17, "c17", + C, "ISO C 2017", + LineComment | C99 | C11 | C17 | Digraphs | HexFloat) +LANGSTANDARD_ALIAS(c17, "iso9899:2017") +LANGSTANDARD_ALIAS(c17, "c18") +LANGSTANDARD_ALIAS(c17, "iso9899:2018") +LANGSTANDARD(gnu17, "gnu17", + C, "ISO C 2017 with GNU extensions", + LineComment | C99 | C11 | C17 | Digraphs | GNUMode | HexFloat) +LANGSTANDARD_ALIAS(gnu17, "gnu18") + +// C++ modes +LANGSTANDARD(cxx98, "c++98", + CXX, "ISO C++ 1998 with amendments", + LineComment | CPlusPlus | Digraphs) +LANGSTANDARD_ALIAS(cxx98, "c++03") + +LANGSTANDARD(gnucxx98, "gnu++98", + CXX, "ISO C++ 1998 with amendments and GNU extensions", + LineComment | CPlusPlus | Digraphs | GNUMode) +LANGSTANDARD_ALIAS(gnucxx98, "gnu++03") + +LANGSTANDARD(cxx11, "c++11", + CXX, "ISO C++ 2011 with amendments", + LineComment | CPlusPlus | CPlusPlus11 | Digraphs) +LANGSTANDARD_ALIAS_DEPR(cxx11, "c++0x") + +LANGSTANDARD(gnucxx11, "gnu++11", CXX, + "ISO C++ 2011 with amendments and GNU extensions", + LineComment | CPlusPlus | CPlusPlus11 | Digraphs | GNUMode) +LANGSTANDARD_ALIAS_DEPR(gnucxx11, "gnu++0x") + +LANGSTANDARD(cxx14, "c++14", + CXX, "ISO C++ 2014 with amendments", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs) +LANGSTANDARD_ALIAS_DEPR(cxx14, "c++1y") + +LANGSTANDARD(gnucxx14, "gnu++14", + CXX, "ISO C++ 2014 with amendments and GNU extensions", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs | + GNUMode) +LANGSTANDARD_ALIAS_DEPR(gnucxx14, "gnu++1y") + +LANGSTANDARD(cxx17, "c++17", + CXX, "ISO C++ 2017 with amendments", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | + Digraphs | HexFloat) +LANGSTANDARD_ALIAS_DEPR(cxx17, "c++1z") + +LANGSTANDARD(gnucxx17, "gnu++17", + CXX, "ISO C++ 2017 with amendments and GNU extensions", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | + Digraphs | HexFloat | GNUMode) +LANGSTANDARD_ALIAS_DEPR(gnucxx17, "gnu++1z") + +LANGSTANDARD(cxx2a, "c++2a", + CXX, "Working draft for ISO C++ 2020", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | + CPlusPlus2a | Digraphs | HexFloat) + +LANGSTANDARD(gnucxx2a, "gnu++2a", + CXX, "Working draft for ISO C++ 2020 with GNU extensions", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | + CPlusPlus2a | Digraphs | HexFloat | GNUMode) + +// OpenCL +LANGSTANDARD(opencl10, "cl1.0", + OpenCL, "OpenCL 1.0", + LineComment | C99 | Digraphs | HexFloat | OpenCL) +LANGSTANDARD_ALIAS_DEPR(opencl10, "cl") + +LANGSTANDARD(opencl11, "cl1.1", + OpenCL, "OpenCL 1.1", + LineComment | C99 | Digraphs | HexFloat | OpenCL) +LANGSTANDARD(opencl12, "cl1.2", + OpenCL, "OpenCL 1.2", + LineComment | C99 | Digraphs | HexFloat | OpenCL) +LANGSTANDARD(opencl20, "cl2.0", + OpenCL, "OpenCL 2.0", + LineComment | C99 | Digraphs | HexFloat | OpenCL) +LANGSTANDARD(openclcpp, "c++", + OpenCL, "OpenCL C++ 1.0", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs | OpenCL) + +LANGSTANDARD_ALIAS_DEPR(opencl10, "CL") +LANGSTANDARD_ALIAS_DEPR(opencl11, "CL1.1") +LANGSTANDARD_ALIAS_DEPR(opencl12, "CL1.2") +LANGSTANDARD_ALIAS_DEPR(opencl20, "CL2.0") + +// CUDA +LANGSTANDARD(cuda, "cuda", CUDA, "NVIDIA CUDA(tm)", + LineComment | CPlusPlus | Digraphs) + +// HIP +LANGSTANDARD(hip, "hip", HIP, "HIP", + LineComment | CPlusPlus | Digraphs) + +#undef LANGSTANDARD +#undef LANGSTANDARD_ALIAS +#undef LANGSTANDARD_ALIAS_DEPR diff --git a/clang-r353983/include/clang/Frontend/LayoutOverrideSource.h b/clang-r353983/include/clang/Frontend/LayoutOverrideSource.h new file mode 100644 index 00000000..ea161147 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/LayoutOverrideSource.h @@ -0,0 +1,62 @@ +//===--- LayoutOverrideSource.h --Override Record Layouts -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_LAYOUTOVERRIDESOURCE_H +#define LLVM_CLANG_FRONTEND_LAYOUTOVERRIDESOURCE_H + +#include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { + /// An external AST source that overrides the layout of + /// a specified set of record types. + /// + /// This class is used only for testing the ability of external AST sources + /// to override the layout of record types. Its input is the output format + /// of the command-line argument -fdump-record-layouts. + class LayoutOverrideSource : public ExternalASTSource { + /// The layout of a given record. + struct Layout { + /// The size of the record. + uint64_t Size; + + /// The alignment of the record. + uint64_t Align; + + /// The offsets of the fields, in source order. + SmallVector<uint64_t, 8> FieldOffsets; + }; + + /// The set of layouts that will be overridden. + llvm::StringMap<Layout> Layouts; + + public: + /// Create a new AST source that overrides the layout of some + /// set of record types. + /// + /// The file is the result of passing -fdump-record-layouts to a file. + explicit LayoutOverrideSource(StringRef Filename); + + /// If this particular record type has an overridden layout, + /// return that layout. + bool + layoutRecordType(const RecordDecl *Record, + uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, + llvm::DenseMap<const CXXRecordDecl *, + CharUnits> &VirtualBaseOffsets) override; + + /// Dump the overridden layouts. + void dump(); + }; +} + +#endif diff --git a/clang-r353983/include/clang/Frontend/LogDiagnosticPrinter.h b/clang-r353983/include/clang/Frontend/LogDiagnosticPrinter.h new file mode 100644 index 00000000..4816275c --- /dev/null +++ b/clang-r353983/include/clang/Frontend/LogDiagnosticPrinter.h @@ -0,0 +1,84 @@ +//===--- LogDiagnosticPrinter.h - Log Diagnostic Client ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_LOGDIAGNOSTICPRINTER_H +#define LLVM_CLANG_FRONTEND_LOGDIAGNOSTICPRINTER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { +class DiagnosticOptions; +class LangOptions; + +class LogDiagnosticPrinter : public DiagnosticConsumer { + struct DiagEntry { + /// The primary message line of the diagnostic. + std::string Message; + + /// The source file name, if available. + std::string Filename; + + /// The source file line number, if available. + unsigned Line; + + /// The source file column number, if available. + unsigned Column; + + /// The ID of the diagnostic. + unsigned DiagnosticID; + + /// The Option Flag for the diagnostic + std::string WarningOption; + + /// The level of the diagnostic. + DiagnosticsEngine::Level DiagnosticLevel; + }; + + void EmitDiagEntry(llvm::raw_ostream &OS, + const LogDiagnosticPrinter::DiagEntry &DE); + + // Conditional ownership (when StreamOwner is non-null, it's keeping OS + // alive). We might want to replace this with a wrapper for conditional + // ownership eventually - it seems to pop up often enough. + raw_ostream &OS; + std::unique_ptr<raw_ostream> StreamOwner; + const LangOptions *LangOpts; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; + + SourceLocation LastWarningLoc; + FullSourceLoc LastLoc; + + SmallVector<DiagEntry, 8> Entries; + + std::string MainFilename; + std::string DwarfDebugFlags; + +public: + LogDiagnosticPrinter(raw_ostream &OS, DiagnosticOptions *Diags, + std::unique_ptr<raw_ostream> StreamOwner); + + void setDwarfDebugFlags(StringRef Value) { + DwarfDebugFlags = Value; + } + + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override { + LangOpts = &LO; + } + + void EndSourceFile() override; + + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override; +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/MigratorOptions.h b/clang-r353983/include/clang/Frontend/MigratorOptions.h new file mode 100644 index 00000000..cf50ffcf --- /dev/null +++ b/clang-r353983/include/clang/Frontend/MigratorOptions.h @@ -0,0 +1,30 @@ +//===--- MigratorOptions.h - MigratorOptions Options ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This header contains the structures necessary for a front-end to specify +// various migration analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_MIGRATOROPTIONS_H +#define LLVM_CLANG_FRONTEND_MIGRATOROPTIONS_H + +namespace clang { + +class MigratorOptions { +public: + unsigned NoNSAllocReallocError : 1; + unsigned NoFinalizeRemoval : 1; + MigratorOptions() { + NoNSAllocReallocError = 0; + NoFinalizeRemoval = 0; + } +}; + +} +#endif diff --git a/clang-r353983/include/clang/Frontend/MultiplexConsumer.h b/clang-r353983/include/clang/Frontend/MultiplexConsumer.h new file mode 100644 index 00000000..ca6ed831 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/MultiplexConsumer.h @@ -0,0 +1,87 @@ +//===-- MultiplexConsumer.h - AST Consumer for PCH Generation ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the MultiplexConsumer class, which can be used to +// multiplex ASTConsumer and SemaConsumer messages to many consumers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_MULTIPLEXCONSUMER_H +#define LLVM_CLANG_FRONTEND_MULTIPLEXCONSUMER_H + +#include "clang/Basic/LLVM.h" +#include "clang/Sema/SemaConsumer.h" +#include "clang/Serialization/ASTDeserializationListener.h" +#include <memory> +#include <vector> + +namespace clang { + +class MultiplexASTMutationListener; + +// This ASTDeserializationListener forwards its notifications to a set of +// child listeners. +class MultiplexASTDeserializationListener : public ASTDeserializationListener { +public: + // Does NOT take ownership of the elements in L. + MultiplexASTDeserializationListener( + const std::vector<ASTDeserializationListener *> &L); + void ReaderInitialized(ASTReader *Reader) override; + void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) override; + void MacroRead(serialization::MacroID ID, MacroInfo *MI) override; + void TypeRead(serialization::TypeIdx Idx, QualType T) override; + void DeclRead(serialization::DeclID ID, const Decl *D) override; + void SelectorRead(serialization::SelectorID iD, Selector Sel) override; + void MacroDefinitionRead(serialization::PreprocessedEntityID, + MacroDefinitionRecord *MD) override; + void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override; + +private: + std::vector<ASTDeserializationListener *> Listeners; +}; + +// Has a list of ASTConsumers and calls each of them. Owns its children. +class MultiplexConsumer : public SemaConsumer { +public: + // Takes ownership of the pointers in C. + MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>> C); + ~MultiplexConsumer() override; + + // ASTConsumer + void Initialize(ASTContext &Context) override; + void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override; + bool HandleTopLevelDecl(DeclGroupRef D) override; + void HandleInlineFunctionDefinition(FunctionDecl *D) override; + void HandleInterestingDecl(DeclGroupRef D) override; + void HandleTranslationUnit(ASTContext &Ctx) override; + void HandleTagDeclDefinition(TagDecl *D) override; + void HandleTagDeclRequiredDefinition(const TagDecl *D) override; + void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override; + void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override; + void HandleImplicitImportDecl(ImportDecl *D) override; + void CompleteTentativeDefinition(VarDecl *D) override; + void AssignInheritanceModel(CXXRecordDecl *RD) override; + void HandleVTable(CXXRecordDecl *RD) override; + ASTMutationListener *GetASTMutationListener() override; + ASTDeserializationListener *GetASTDeserializationListener() override; + void PrintStats() override; + bool shouldSkipFunctionBody(Decl *D) override; + + // SemaConsumer + void InitializeSema(Sema &S) override; + void ForgetSema() override; + +private: + std::vector<std::unique_ptr<ASTConsumer>> Consumers; // Owns these. + std::unique_ptr<MultiplexASTMutationListener> MutationListener; + std::unique_ptr<MultiplexASTDeserializationListener> DeserializationListener; +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/PCHContainerOperations.h b/clang-r353983/include/clang/Frontend/PCHContainerOperations.h new file mode 100644 index 00000000..fa977a63 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/PCHContainerOperations.h @@ -0,0 +1,14 @@ +//===--- Frontend/PCHContainerOperations.h - PCH Containers -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H +#define LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H + +#include "clang/Serialization/PCHContainerOperations.h" + +#endif diff --git a/clang-r353983/include/clang/Frontend/PrecompiledPreamble.h b/clang-r353983/include/clang/Frontend/PrecompiledPreamble.h new file mode 100644 index 00000000..b1d55d80 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/PrecompiledPreamble.h @@ -0,0 +1,311 @@ +//===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Helper class to build precompiled preamble. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H +#define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H + +#include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/MD5.h" +#include <cstddef> +#include <memory> +#include <system_error> +#include <type_traits> + +namespace llvm { +class MemoryBuffer; +namespace vfs { +class FileSystem; +} +} // namespace llvm + +namespace clang { +class CompilerInstance; +class CompilerInvocation; +class DeclGroupRef; +class PCHContainerOperations; + +/// Runs lexer to compute suggested preamble bounds. +PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, + llvm::MemoryBuffer *Buffer, + unsigned MaxLines); + +class PreambleCallbacks; + +/// A class holding a PCH and all information to check whether it is valid to +/// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and +/// CanReusePreamble + AddImplicitPreamble to make use of it. +class PrecompiledPreamble { + class PCHStorage; + struct PreambleFileHash; + +public: + /// Try to build PrecompiledPreamble for \p Invocation. See + /// BuildPreambleError for possible error codes. + /// + /// \param Invocation Original CompilerInvocation with options to compile the + /// file. + /// + /// \param MainFileBuffer Buffer with the contents of the main file. + /// + /// \param Bounds Bounds of the preamble, result of calling + /// ComputePreambleBounds. + /// + /// \param Diagnostics Diagnostics engine to be used while building the + /// preamble. + /// + /// \param VFS An instance of vfs::FileSystem to be used for file + /// accesses. + /// + /// \param PCHContainerOps An instance of PCHContainerOperations. + /// + /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in + /// a temporary file. + /// + /// \param Callbacks A set of callbacks to be executed when building + /// the preamble. + static llvm::ErrorOr<PrecompiledPreamble> + Build(const CompilerInvocation &Invocation, + const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, + DiagnosticsEngine &Diagnostics, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + bool StoreInMemory, PreambleCallbacks &Callbacks); + + PrecompiledPreamble(PrecompiledPreamble &&) = default; + PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default; + + /// PreambleBounds used to build the preamble. + PreambleBounds getBounds() const; + + /// Returns the size, in bytes, that preamble takes on disk or in memory. + /// For on-disk preambles returns 0 if filesystem operations fail. Intended to + /// be used for logging and debugging purposes only. + std::size_t getSize() const; + + /// Check whether PrecompiledPreamble can be reused for the new contents(\p + /// MainFileBuffer) of the main file. + bool CanReuse(const CompilerInvocation &Invocation, + const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, + llvm::vfs::FileSystem *VFS) const; + + /// Changes options inside \p CI to use PCH from this preamble. Also remaps + /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble + /// is accessible. + /// Requires that CanReuse() is true. + /// For in-memory preambles, PrecompiledPreamble instance continues to own the + /// MemoryBuffer with the Preamble after this method returns. The caller is + /// responsible for making sure the PrecompiledPreamble instance outlives the + /// compiler run and the AST that will be using the PCH. + void AddImplicitPreamble(CompilerInvocation &CI, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, + llvm::MemoryBuffer *MainFileBuffer) const; + + /// Configure \p CI to use this preamble. + /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true. + /// If this preamble does not match the file, it may parse differently. + void OverridePreamble(CompilerInvocation &CI, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, + llvm::MemoryBuffer *MainFileBuffer) const; + +private: + PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes, + bool PreambleEndsAtStartOfLine, + llvm::StringMap<PreambleFileHash> FilesInPreamble); + + /// A temp file that would be deleted on destructor call. If destructor is not + /// called for any reason, the file will be deleted at static objects' + /// destruction. + /// An assertion will fire if two TempPCHFiles are created with the same name, + /// so it's not intended to be used outside preamble-handling. + class TempPCHFile { + public: + // A main method used to construct TempPCHFile. + static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile(); + + /// Call llvm::sys::fs::createTemporaryFile to create a new temporary file. + static llvm::ErrorOr<TempPCHFile> createInSystemTempDir(const Twine &Prefix, + StringRef Suffix); + /// Create a new instance of TemporaryFile for file at \p Path. Use with + /// extreme caution, there's an assertion checking that there's only a + /// single instance of TempPCHFile alive for each path. + static llvm::ErrorOr<TempPCHFile> createFromCustomPath(const Twine &Path); + + private: + TempPCHFile(std::string FilePath); + + public: + TempPCHFile(TempPCHFile &&Other); + TempPCHFile &operator=(TempPCHFile &&Other); + + TempPCHFile(const TempPCHFile &) = delete; + ~TempPCHFile(); + + /// A path where temporary file is stored. + llvm::StringRef getFilePath() const; + + private: + void RemoveFileIfPresent(); + + private: + llvm::Optional<std::string> FilePath; + }; + + class InMemoryPreamble { + public: + std::string Data; + }; + + class PCHStorage { + public: + enum class Kind { Empty, InMemory, TempFile }; + + PCHStorage() = default; + PCHStorage(TempPCHFile File); + PCHStorage(InMemoryPreamble Memory); + + PCHStorage(const PCHStorage &) = delete; + PCHStorage &operator=(const PCHStorage &) = delete; + + PCHStorage(PCHStorage &&Other); + PCHStorage &operator=(PCHStorage &&Other); + + ~PCHStorage(); + + Kind getKind() const; + + TempPCHFile &asFile(); + const TempPCHFile &asFile() const; + + InMemoryPreamble &asMemory(); + const InMemoryPreamble &asMemory() const; + + private: + void destroy(); + void setEmpty(); + + private: + Kind StorageKind = Kind::Empty; + llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {}; + }; + + /// Data used to determine if a file used in the preamble has been changed. + struct PreambleFileHash { + /// All files have size set. + off_t Size = 0; + + /// Modification time is set for files that are on disk. For memory + /// buffers it is zero. + time_t ModTime = 0; + + /// Memory buffers have MD5 instead of modification time. We don't + /// compute MD5 for on-disk files because we hope that modification time is + /// enough to tell if the file was changed. + llvm::MD5::MD5Result MD5 = {}; + + static PreambleFileHash createForFile(off_t Size, time_t ModTime); + static PreambleFileHash + createForMemoryBuffer(const llvm::MemoryBuffer *Buffer); + + friend bool operator==(const PreambleFileHash &LHS, + const PreambleFileHash &RHS) { + return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime && + LHS.MD5 == RHS.MD5; + } + friend bool operator!=(const PreambleFileHash &LHS, + const PreambleFileHash &RHS) { + return !(LHS == RHS); + } + }; + + /// Helper function to set up PCH for the preamble into \p CI and \p VFS to + /// with the specified \p Bounds. + void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, + llvm::MemoryBuffer *MainFileBuffer) const; + + /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p + /// Storage is accessible to clang. This method is an implementation detail of + /// AddImplicitPreamble. + static void + setupPreambleStorage(const PCHStorage &Storage, + PreprocessorOptions &PreprocessorOpts, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS); + + /// Manages the memory buffer or temporary file that stores the PCH. + PCHStorage Storage; + /// Keeps track of the files that were used when computing the + /// preamble, with both their buffer size and their modification time. + /// + /// If any of the files have changed from one compile to the next, + /// the preamble must be thrown away. + llvm::StringMap<PreambleFileHash> FilesInPreamble; + /// The contents of the file that was used to precompile the preamble. Only + /// contains first PreambleBounds::Size bytes. Used to compare if the relevant + /// part of the file has not changed, so that preamble can be reused. + std::vector<char> PreambleBytes; + /// See PreambleBounds::PreambleEndsAtStartOfLine + bool PreambleEndsAtStartOfLine; +}; + +/// A set of callbacks to gather useful information while building a preamble. +class PreambleCallbacks { +public: + virtual ~PreambleCallbacks() = default; + + /// Called before FrontendAction::BeginSourceFile. + /// Can be used to store references to various CompilerInstance fields + /// (e.g. SourceManager) that may be interesting to the consumers of other + /// callbacks. + virtual void BeforeExecute(CompilerInstance &CI); + /// Called after FrontendAction::Execute(), but before + /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of + /// various CompilerInstance fields before they are destroyed. + virtual void AfterExecute(CompilerInstance &CI); + /// Called after PCH has been emitted. \p Writer may be used to retrieve + /// information about AST, serialized in PCH. + virtual void AfterPCHEmitted(ASTWriter &Writer); + /// Called for each TopLevelDecl. + /// NOTE: To allow more flexibility a custom ASTConsumer could probably be + /// used instead, but having only this method allows a simpler API. + virtual void HandleTopLevelDecl(DeclGroupRef DG); + /// Creates wrapper class for PPCallbacks so we can also process information + /// about includes that are inside of a preamble + virtual std::unique_ptr<PPCallbacks> createPPCallbacks(); + /// The returned CommentHandler will be added to the preprocessor if not null. + virtual CommentHandler *getCommentHandler(); +}; + +enum class BuildPreambleError { + CouldntCreateTempFile = 1, + CouldntCreateTargetInfo, + BeginSourceFileFailed, + CouldntEmitPCH +}; + +class BuildPreambleErrorCategory final : public std::error_category { +public: + const char *name() const noexcept override; + std::string message(int condition) const override; +}; + +std::error_code make_error_code(BuildPreambleError Error); +} // namespace clang + +namespace std { +template <> +struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {}; +} // namespace std + +#endif diff --git a/clang-r353983/include/clang/Frontend/PreprocessorOutputOptions.h b/clang-r353983/include/clang/Frontend/PreprocessorOutputOptions.h new file mode 100644 index 00000000..72e5ad11 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/PreprocessorOutputOptions.h @@ -0,0 +1,44 @@ +//===--- PreprocessorOutputOptions.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H +#define LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H + +namespace clang { + +/// PreprocessorOutputOptions - Options for controlling the C preprocessor +/// output (e.g., -E). +class PreprocessorOutputOptions { +public: + unsigned ShowCPP : 1; ///< Print normal preprocessed output. + unsigned ShowComments : 1; ///< Show comments. + unsigned ShowLineMarkers : 1; ///< Show \#line markers. + unsigned UseLineDirectives : 1; ///< Use \#line instead of GCC-style \# N. + unsigned ShowMacroComments : 1; ///< Show comments, even in macros. + unsigned ShowMacros : 1; ///< Print macro definitions. + unsigned ShowIncludeDirectives : 1; ///< Print includes, imports etc. within preprocessed output. + unsigned RewriteIncludes : 1; ///< Preprocess include directives only. + unsigned RewriteImports : 1; ///< Include contents of transitively-imported modules. + +public: + PreprocessorOutputOptions() { + ShowCPP = 0; + ShowComments = 0; + ShowLineMarkers = 1; + UseLineDirectives = 0; + ShowMacroComments = 0; + ShowMacros = 0; + ShowIncludeDirectives = 0; + RewriteIncludes = 0; + RewriteImports = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/SerializedDiagnosticPrinter.h b/clang-r353983/include/clang/Frontend/SerializedDiagnosticPrinter.h new file mode 100644 index 00000000..5c1ff7a0 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -0,0 +1,42 @@ +//===--- SerializedDiagnosticPrinter.h - Diagnostics serializer -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICPRINTER_H +#define LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICPRINTER_H + +#include "clang/Basic/LLVM.h" +#include "clang/Frontend/SerializedDiagnostics.h" +#include "llvm/Bitcode/BitstreamWriter.h" + +namespace llvm { +class raw_ostream; +} + +namespace clang { +class DiagnosticConsumer; +class DiagnosticsEngine; +class DiagnosticOptions; + +namespace serialized_diags { + +/// Returns a DiagnosticConsumer that serializes diagnostics to +/// a bitcode file. +/// +/// The created DiagnosticConsumer is designed for quick and lightweight +/// transfer of diagnostics to the enclosing build system (e.g., an IDE). +/// This allows wrapper tools for Clang to get diagnostics from Clang +/// (via libclang) without needing to parse Clang's command line output. +/// +std::unique_ptr<DiagnosticConsumer> create(StringRef OutputFile, + DiagnosticOptions *Diags, + bool MergeChildRecords = false); + +} // end serialized_diags namespace +} // end clang namespace + +#endif diff --git a/clang-r353983/include/clang/Frontend/SerializedDiagnosticReader.h b/clang-r353983/include/clang/Frontend/SerializedDiagnosticReader.h new file mode 100644 index 00000000..7b3a6dba --- /dev/null +++ b/clang-r353983/include/clang/Frontend/SerializedDiagnosticReader.h @@ -0,0 +1,138 @@ +//===- SerializedDiagnosticReader.h - Reads diagnostics ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H +#define LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H + +#include "clang/Basic/LLVM.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorOr.h" +#include <system_error> + +namespace clang { +namespace serialized_diags { + +enum class SDError { + CouldNotLoad = 1, + InvalidSignature, + InvalidDiagnostics, + MalformedTopLevelBlock, + MalformedSubBlock, + MalformedBlockInfoBlock, + MalformedMetadataBlock, + MalformedDiagnosticBlock, + MalformedDiagnosticRecord, + MissingVersion, + VersionMismatch, + UnsupportedConstruct, + /// A generic error for subclass handlers that don't want or need to define + /// their own error_category. + HandlerFailed +}; + +const std::error_category &SDErrorCategory(); + +inline std::error_code make_error_code(SDError E) { + return std::error_code(static_cast<int>(E), SDErrorCategory()); +} + +/// A location that is represented in the serialized diagnostics. +struct Location { + unsigned FileID; + unsigned Line; + unsigned Col; + unsigned Offset; + + Location(unsigned FileID, unsigned Line, unsigned Col, unsigned Offset) + : FileID(FileID), Line(Line), Col(Col), Offset(Offset) {} +}; + +/// A base class that handles reading serialized diagnostics from a file. +/// +/// Subclasses should override the visit* methods with their logic for handling +/// the various constructs that are found in serialized diagnostics. +class SerializedDiagnosticReader { +public: + SerializedDiagnosticReader() = default; + virtual ~SerializedDiagnosticReader() = default; + + /// Read the diagnostics in \c File + std::error_code readDiagnostics(StringRef File); + +private: + enum class Cursor; + + /// Read to the next record or block to process. + llvm::ErrorOr<Cursor> skipUntilRecordOrBlock(llvm::BitstreamCursor &Stream, + unsigned &BlockOrRecordId); + + /// Read a metadata block from \c Stream. + std::error_code readMetaBlock(llvm::BitstreamCursor &Stream); + + /// Read a diagnostic block from \c Stream. + std::error_code readDiagnosticBlock(llvm::BitstreamCursor &Stream); + +protected: + /// Visit the start of a diagnostic block. + virtual std::error_code visitStartOfDiagnostic() { return {}; } + + /// Visit the end of a diagnostic block. + virtual std::error_code visitEndOfDiagnostic() { return {}; } + + /// Visit a category. This associates the category \c ID to a \c Name. + virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name) { + return {}; + } + + /// Visit a flag. This associates the flag's \c ID to a \c Name. + virtual std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) { + return {}; + } + + /// Visit a diagnostic. + virtual std::error_code + visitDiagnosticRecord(unsigned Severity, const Location &Location, + unsigned Category, unsigned Flag, StringRef Message) { + return {}; + } + + /// Visit a filename. This associates the file's \c ID to a \c Name. + virtual std::error_code visitFilenameRecord(unsigned ID, unsigned Size, + unsigned Timestamp, + StringRef Name) { + return {}; + } + + /// Visit a fixit hint. + virtual std::error_code + visitFixitRecord(const Location &Start, const Location &End, StringRef Text) { + return {}; + } + + /// Visit a source range. + virtual std::error_code visitSourceRangeRecord(const Location &Start, + const Location &End) { + return {}; + } + + /// Visit the version of the set of diagnostics. + virtual std::error_code visitVersionRecord(unsigned Version) { return {}; } +}; + +} // namespace serialized_diags +} // namespace clang + +namespace std { + +template <> +struct is_error_code_enum<clang::serialized_diags::SDError> : std::true_type {}; + +} // namespace std + +#endif // LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H diff --git a/clang-r353983/include/clang/Frontend/SerializedDiagnostics.h b/clang-r353983/include/clang/Frontend/SerializedDiagnostics.h new file mode 100644 index 00000000..6ffcf520 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/SerializedDiagnostics.h @@ -0,0 +1,58 @@ +//===--- SerializedDiagnostics.h - Common data for serialized diagnostics -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTICS_H_ +#define LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTICS_H_ + +#include "llvm/Bitcode/BitCodes.h" + +namespace clang { +namespace serialized_diags { + +enum BlockIDs { + /// A top-level block which represents any meta data associated + /// with the diagostics, including versioning of the format. + BLOCK_META = llvm::bitc::FIRST_APPLICATION_BLOCKID, + + /// The this block acts as a container for all the information + /// for a specific diagnostic. + BLOCK_DIAG +}; + +enum RecordIDs { + RECORD_VERSION = 1, + RECORD_DIAG, + RECORD_SOURCE_RANGE, + RECORD_DIAG_FLAG, + RECORD_CATEGORY, + RECORD_FILENAME, + RECORD_FIXIT, + RECORD_FIRST = RECORD_VERSION, + RECORD_LAST = RECORD_FIXIT +}; + +/// A stable version of DiagnosticIDs::Level. +/// +/// Do not change the order of values in this enum, and please increment the +/// serialized diagnostics version number when you add to it. +enum Level { + Ignored = 0, + Note, + Warning, + Error, + Fatal, + Remark +}; + +/// The serialized diagnostics version number. +enum { VersionNumber = 2 }; + +} // end serialized_diags namespace +} // end clang namespace + +#endif diff --git a/clang-r353983/include/clang/Frontend/TextDiagnostic.h b/clang-r353983/include/clang/Frontend/TextDiagnostic.h new file mode 100644 index 00000000..7cf54839 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/TextDiagnostic.h @@ -0,0 +1,114 @@ +//===--- TextDiagnostic.h - Text Diagnostic Pretty-Printing -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is a utility class that provides support for textual pretty-printing of +// diagnostics. It is used to implement the different code paths which require +// such functionality in a consistent way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H +#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H + +#include "clang/Frontend/DiagnosticRenderer.h" + +namespace clang { + +/// Class to encapsulate the logic for formatting and printing a textual +/// diagnostic message. +/// +/// This class provides an interface for building and emitting a textual +/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt +/// Hints, and code snippets. In the presence of macros this involves +/// a recursive process, synthesizing notes for each macro expansion. +/// +/// The purpose of this class is to isolate the implementation of printing +/// beautiful text diagnostics from any particular interfaces. The Clang +/// DiagnosticClient is implemented through this class as is diagnostic +/// printing coming out of libclang. +class TextDiagnostic : public DiagnosticRenderer { + raw_ostream &OS; + +public: + TextDiagnostic(raw_ostream &OS, + const LangOptions &LangOpts, + DiagnosticOptions *DiagOpts); + + ~TextDiagnostic() override; + + /// Print the diagonstic level to a raw_ostream. + /// + /// This is a static helper that handles colorizing the level and formatting + /// it into an arbitrary output stream. This is used internally by the + /// TextDiagnostic emission code, but it can also be used directly by + /// consumers that don't have a source manager or other state that the full + /// TextDiagnostic logic requires. + static void printDiagnosticLevel(raw_ostream &OS, + DiagnosticsEngine::Level Level, + bool ShowColors, + bool CLFallbackMode = false); + + /// Pretty-print a diagnostic message to a raw_ostream. + /// + /// This is a static helper to handle the line wrapping, colorizing, and + /// rendering of a diagnostic message to a particular ostream. It is + /// publicly visible so that clients which do not have sufficient state to + /// build a complete TextDiagnostic object can still get consistent + /// formatting of their diagnostic messages. + /// + /// \param OS Where the message is printed + /// \param IsSupplemental true if this is a continuation note diagnostic + /// \param Message The text actually printed + /// \param CurrentColumn The starting column of the first line, accounting + /// for any prefix. + /// \param Columns The number of columns to use in line-wrapping, 0 disables + /// all line-wrapping. + /// \param ShowColors Enable colorizing of the message. + static void printDiagnosticMessage(raw_ostream &OS, bool IsSupplemental, + StringRef Message, unsigned CurrentColumn, + unsigned Columns, bool ShowColors); + +protected: + void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, + ArrayRef<CharSourceRange> Ranges, + DiagOrStoredDiag D) override; + + void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + ArrayRef<CharSourceRange> Ranges) override; + + void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange> &Ranges, + ArrayRef<FixItHint> Hints) override { + emitSnippetAndCaret(Loc, Level, Ranges, Hints); + } + + void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override; + + void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) override; + + void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, + StringRef ModuleName) override; + +private: + void emitFilename(StringRef Filename, const SourceManager &SM); + + void emitSnippetAndCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange> &Ranges, + ArrayRef<FixItHint> Hints); + + void emitSnippet(StringRef SourceLine); + + void emitParseableFixits(ArrayRef<FixItHint> Hints, const SourceManager &SM); +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/TextDiagnosticBuffer.h b/clang-r353983/include/clang/Frontend/TextDiagnosticBuffer.h new file mode 100644 index 00000000..5945caf8 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/TextDiagnosticBuffer.h @@ -0,0 +1,63 @@ +//===- TextDiagnosticBuffer.h - Buffer Text Diagnostics ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is a concrete diagnostic client, which buffers the diagnostic messages. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H +#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include <cstddef> +#include <string> +#include <utility> +#include <vector> + +namespace clang { + +class TextDiagnosticBuffer : public DiagnosticConsumer { +public: + using DiagList = std::vector<std::pair<SourceLocation, std::string>>; + using iterator = DiagList::iterator; + using const_iterator = DiagList::const_iterator; + +private: + DiagList Errors, Warnings, Remarks, Notes; + + /// All - All diagnostics in the order in which they were generated. That + /// order likely doesn't correspond to user input order, but it at least + /// keeps notes in the right places. Each pair in the vector is a diagnostic + /// level and an index into the corresponding DiagList above. + std::vector<std::pair<DiagnosticsEngine::Level, size_t>> All; + +public: + const_iterator err_begin() const { return Errors.begin(); } + const_iterator err_end() const { return Errors.end(); } + + const_iterator warn_begin() const { return Warnings.begin(); } + const_iterator warn_end() const { return Warnings.end(); } + + const_iterator remark_begin() const { return Remarks.begin(); } + const_iterator remark_end() const { return Remarks.end(); } + + const_iterator note_begin() const { return Notes.begin(); } + const_iterator note_end() const { return Notes.end(); } + + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override; + + /// FlushDiagnostics - Flush the buffered diagnostics to an given + /// diagnostic engine. + void FlushDiagnostics(DiagnosticsEngine &Diags) const; +}; + +} // namespace clang + +#endif // LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H diff --git a/clang-r353983/include/clang/Frontend/TextDiagnosticPrinter.h b/clang-r353983/include/clang/Frontend/TextDiagnosticPrinter.h new file mode 100644 index 00000000..ba756fa1 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/TextDiagnosticPrinter.h @@ -0,0 +1,57 @@ +//===--- TextDiagnosticPrinter.h - Text Diagnostic Client -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is a concrete diagnostic client, which prints the diagnostics to +// standard error. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICPRINTER_H +#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICPRINTER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include <memory> + +namespace clang { +class DiagnosticOptions; +class LangOptions; +class TextDiagnostic; + +class TextDiagnosticPrinter : public DiagnosticConsumer { + raw_ostream &OS; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; + + /// Handle to the currently active text diagnostic emitter. + std::unique_ptr<TextDiagnostic> TextDiag; + + /// A string to prefix to error messages. + std::string Prefix; + + unsigned OwnsOutputStream : 1; + +public: + TextDiagnosticPrinter(raw_ostream &os, DiagnosticOptions *diags, + bool OwnsOutputStream = false); + ~TextDiagnosticPrinter() override; + + /// setPrefix - Set the diagnostic printer prefix string, which will be + /// printed at the start of any diagnostics. If empty, no prefix string is + /// used. + void setPrefix(std::string Value) { Prefix = std::move(Value); } + + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override; + void EndSourceFile() override; + void HandleDiagnostic(DiagnosticsEngine::Level Level, + const Diagnostic &Info) override; +}; + +} // end namespace clang + +#endif diff --git a/clang-r353983/include/clang/Frontend/Utils.h b/clang-r353983/include/clang/Frontend/Utils.h new file mode 100644 index 00000000..124d4a99 --- /dev/null +++ b/clang-r353983/include/clang/Frontend/Utils.h @@ -0,0 +1,233 @@ +//===- Utils.h - Misc utilities for the front-end ---------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This header contains miscellaneous utilities for various front-end actions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_UTILS_H +#define LLVM_CLANG_FRONTEND_UTILS_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Option/OptSpecifier.h" +#include "llvm/Support/VirtualFileSystem.h" +#include <cstdint> +#include <memory> +#include <string> +#include <system_error> +#include <utility> +#include <vector> + +namespace llvm { + +class Triple; + +namespace opt { + +class ArgList; + +} // namespace opt + +} // namespace llvm + +namespace clang { + +class ASTReader; +class CompilerInstance; +class CompilerInvocation; +class DependencyOutputOptions; +class DiagnosticsEngine; +class ExternalSemaSource; +class FrontendOptions; +class HeaderSearch; +class HeaderSearchOptions; +class LangOptions; +class PCHContainerReader; +class Preprocessor; +class PreprocessorOptions; +class PreprocessorOutputOptions; + +/// Apply the header search options to get given HeaderSearch object. +void ApplyHeaderSearchOptions(HeaderSearch &HS, + const HeaderSearchOptions &HSOpts, + const LangOptions &Lang, + const llvm::Triple &triple); + +/// InitializePreprocessor - Initialize the preprocessor getting it and the +/// environment ready to process a single file. +void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts, + const PCHContainerReader &PCHContainerRdr, + const FrontendOptions &FEOpts); + +/// DoPrintPreprocessedInput - Implement -E mode. +void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, + const PreprocessorOutputOptions &Opts); + +/// An interface for collecting the dependencies of a compilation. Users should +/// use \c attachToPreprocessor and \c attachToASTReader to get all of the +/// dependencies. +/// FIXME: Migrate DependencyFileGen and DependencyGraphGen to use this +/// interface. +class DependencyCollector { +public: + virtual ~DependencyCollector(); + + virtual void attachToPreprocessor(Preprocessor &PP); + virtual void attachToASTReader(ASTReader &R); + ArrayRef<std::string> getDependencies() const { return Dependencies; } + + /// Called when a new file is seen. Return true if \p Filename should be added + /// to the list of dependencies. + /// + /// The default implementation ignores <built-in> and system files. + virtual bool sawDependency(StringRef Filename, bool FromModule, + bool IsSystem, bool IsModuleFile, bool IsMissing); + + /// Called when the end of the main file is reached. + virtual void finishedMainFile() {} + + /// Return true if system files should be passed to sawDependency(). + virtual bool needSystemDependencies() { return false; } + + // implementation detail + /// Add a dependency \p Filename if it has not been seen before and + /// sawDependency() returns true. + void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, + bool IsModuleFile, bool IsMissing); + +private: + llvm::StringSet<> Seen; + std::vector<std::string> Dependencies; +}; + +/// Builds a depdenency file when attached to a Preprocessor (for includes) and +/// ASTReader (for module imports), and writes it out at the end of processing +/// a source file. Users should attach to the ast reader whenever a module is +/// loaded. +class DependencyFileGenerator { + void *Impl; // Opaque implementation + + DependencyFileGenerator(void *Impl); + +public: + static DependencyFileGenerator *CreateAndAttachToPreprocessor( + Preprocessor &PP, const DependencyOutputOptions &Opts); + + void AttachToASTReader(ASTReader &R); +}; + +/// Collects the dependencies for imported modules into a directory. Users +/// should attach to the AST reader whenever a module is loaded. +class ModuleDependencyCollector : public DependencyCollector { + std::string DestDir; + bool HasErrors = false; + llvm::StringSet<> Seen; + llvm::vfs::YAMLVFSWriter VFSWriter; + llvm::StringMap<std::string> SymLinkMap; + + bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result); + std::error_code copyToRoot(StringRef Src, StringRef Dst = {}); + +public: + ModuleDependencyCollector(std::string DestDir) + : DestDir(std::move(DestDir)) {} + ~ModuleDependencyCollector() override { writeFileMap(); } + + StringRef getDest() { return DestDir; } + virtual bool insertSeen(StringRef Filename) { return Seen.insert(Filename).second; } + virtual void addFile(StringRef Filename, StringRef FileDst = {}); + + virtual void addFileMapping(StringRef VPath, StringRef RPath) { + VFSWriter.addFileMapping(VPath, RPath); + } + + void attachToPreprocessor(Preprocessor &PP) override; + void attachToASTReader(ASTReader &R) override; + + virtual void writeFileMap(); + virtual bool hasErrors() { return HasErrors; } +}; + +/// AttachDependencyGraphGen - Create a dependency graph generator, and attach +/// it to the given preprocessor. +void AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile, + StringRef SysRoot); + +/// AttachHeaderIncludeGen - Create a header include list generator, and attach +/// it to the given preprocessor. +/// +/// \param DepOpts - Options controlling the output. +/// \param ShowAllHeaders - If true, show all header information instead of just +/// headers following the predefines buffer. This is useful for making sure +/// includes mentioned on the command line are also reported, but differs from +/// the default behavior used by -H. +/// \param OutputPath - If non-empty, a path to write the header include +/// information to, instead of writing to stderr. +/// \param ShowDepth - Whether to indent to show the nesting of the includes. +/// \param MSStyle - Whether to print in cl.exe /showIncludes style. +void AttachHeaderIncludeGen(Preprocessor &PP, + const DependencyOutputOptions &DepOpts, + bool ShowAllHeaders = false, + StringRef OutputPath = {}, + bool ShowDepth = true, bool MSStyle = false); + +/// The ChainedIncludesSource class converts headers to chained PCHs in +/// memory, mainly for testing. +IntrusiveRefCntPtr<ExternalSemaSource> +createChainedIncludesSource(CompilerInstance &CI, + IntrusiveRefCntPtr<ExternalSemaSource> &Reader); + +/// createInvocationFromCommandLine - Construct a compiler invocation object for +/// a command line argument vector. +/// +/// \return A CompilerInvocation, or 0 if none was built for the given +/// argument vector. +std::unique_ptr<CompilerInvocation> createInvocationFromCommandLine( + ArrayRef<const char *> Args, + IntrusiveRefCntPtr<DiagnosticsEngine> Diags = + IntrusiveRefCntPtr<DiagnosticsEngine>(), + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr); + +/// Return the value of the last argument as an integer, or a default. If Diags +/// is non-null, emits an error if the argument is given, but non-integral. +int getLastArgIntValue(const llvm::opt::ArgList &Args, + llvm::opt::OptSpecifier Id, int Default, + DiagnosticsEngine *Diags = nullptr); + +inline int getLastArgIntValue(const llvm::opt::ArgList &Args, + llvm::opt::OptSpecifier Id, int Default, + DiagnosticsEngine &Diags) { + return getLastArgIntValue(Args, Id, Default, &Diags); +} + +uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args, + llvm::opt::OptSpecifier Id, uint64_t Default, + DiagnosticsEngine *Diags = nullptr); + +inline uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args, + llvm::opt::OptSpecifier Id, + uint64_t Default, + DiagnosticsEngine &Diags) { + return getLastArgUInt64Value(Args, Id, Default, &Diags); +} + +// Frontend timing utils + +/// If the user specifies the -ftime-report argument on an Clang command line +/// then the value of this boolean will be true, otherwise false. +extern bool FrontendTimesIsEnabled; + +} // namespace clang + +#endif // LLVM_CLANG_FRONTEND_UTILS_H diff --git a/clang-r353983/include/clang/Frontend/VerifyDiagnosticConsumer.h b/clang-r353983/include/clang/Frontend/VerifyDiagnosticConsumer.h new file mode 100644 index 00000000..955eaebf --- /dev/null +++ b/clang-r353983/include/clang/Frontend/VerifyDiagnosticConsumer.h @@ -0,0 +1,286 @@ +//===- VerifyDiagnosticConsumer.h - Verifying Diagnostic Client -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H +#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringRef.h" +#include <cassert> +#include <limits> +#include <memory> +#include <string> +#include <vector> + +namespace clang { + +class FileEntry; +class LangOptions; +class SourceManager; +class TextDiagnosticBuffer; + +/// VerifyDiagnosticConsumer - Create a diagnostic client which will use +/// markers in the input source to check that all the emitted diagnostics match +/// those expected. +/// +/// USING THE DIAGNOSTIC CHECKER: +/// +/// Indicating that a line expects an error or a warning is simple. Put a +/// comment on the line that has the diagnostic, use: +/// +/// \code +/// expected-{error,warning,remark,note} +/// \endcode +/// +/// to tag if it's an expected error, remark or warning, and place the expected +/// text between {{ and }} markers. The full text doesn't have to be included, +/// only enough to ensure that the correct diagnostic was emitted. +/// +/// Here's an example: +/// +/// \code +/// int A = B; // expected-error {{use of undeclared identifier 'B'}} +/// \endcode +/// +/// You can place as many diagnostics on one line as you wish. To make the code +/// more readable, you can use slash-newline to separate out the diagnostics. +/// +/// Alternatively, it is possible to specify the line on which the diagnostic +/// should appear by appending "@<line>" to "expected-<type>", for example: +/// +/// \code +/// #warning some text +/// // expected-warning@10 {{some text}} +/// \endcode +/// +/// The line number may be absolute (as above), or relative to the current +/// line by prefixing the number with either '+' or '-'. +/// +/// If the diagnostic is generated in a separate file, for example in a shared +/// header file, it may be beneficial to be able to declare the file in which +/// the diagnostic will appear, rather than placing the expected-* directive in +/// the actual file itself. This can be done using the following syntax: +/// +/// \code +/// // expected-error@path/include.h:15 {{error message}} +/// \endcode +/// +/// The path can be absolute or relative and the same search paths will be used +/// as for #include directives. The line number in an external file may be +/// substituted with '*' meaning that any line number will match (useful where +/// the included file is, for example, a system header where the actual line +/// number may change and is not critical). +/// +/// The simple syntax above allows each specification to match exactly one +/// error. You can use the extended syntax to customize this. The extended +/// syntax is "expected-<type> <n> {{diag text}}", where \<type> is one of +/// "error", "warning" or "note", and \<n> is a positive integer. This allows +/// the diagnostic to appear as many times as specified. Example: +/// +/// \code +/// void f(); // expected-note 2 {{previous declaration is here}} +/// \endcode +/// +/// Where the diagnostic is expected to occur a minimum number of times, this +/// can be specified by appending a '+' to the number. Example: +/// +/// \code +/// void f(); // expected-note 0+ {{previous declaration is here}} +/// void g(); // expected-note 1+ {{previous declaration is here}} +/// \endcode +/// +/// In the first example, the diagnostic becomes optional, i.e. it will be +/// swallowed if it occurs, but will not generate an error if it does not +/// occur. In the second example, the diagnostic must occur at least once. +/// As a short-hand, "one or more" can be specified simply by '+'. Example: +/// +/// \code +/// void g(); // expected-note + {{previous declaration is here}} +/// \endcode +/// +/// A range can also be specified by "<n>-<m>". Example: +/// +/// \code +/// void f(); // expected-note 0-1 {{previous declaration is here}} +/// \endcode +/// +/// In this example, the diagnostic may appear only once, if at all. +/// +/// Regex matching mode may be selected by appending '-re' to type and +/// including regexes wrapped in double curly braces in the directive, such as: +/// +/// \code +/// expected-error-re {{format specifies type 'wchar_t **' (aka '{{.+}}')}} +/// \endcode +/// +/// Examples matching error: "variable has incomplete type 'struct s'" +/// +/// \code +/// // expected-error {{variable has incomplete type 'struct s'}} +/// // expected-error {{variable has incomplete type}} +/// +/// // expected-error-re {{variable has type 'struct {{.}}'}} +/// // expected-error-re {{variable has type 'struct {{.*}}'}} +/// // expected-error-re {{variable has type 'struct {{(.*)}}'}} +/// // expected-error-re {{variable has type 'struct{{[[:space:]](.*)}}'}} +/// \endcode +/// +/// VerifyDiagnosticConsumer expects at least one expected-* directive to +/// be found inside the source code. If no diagnostics are expected the +/// following directive can be used to indicate this: +/// +/// \code +/// // expected-no-diagnostics +/// \endcode +/// +class VerifyDiagnosticConsumer: public DiagnosticConsumer, + public CommentHandler { +public: + /// Directive - Abstract class representing a parsed verify directive. + /// + class Directive { + public: + static std::unique_ptr<Directive> create(bool RegexKind, + SourceLocation DirectiveLoc, + SourceLocation DiagnosticLoc, + bool MatchAnyLine, StringRef Text, + unsigned Min, unsigned Max); + + public: + /// Constant representing n or more matches. + static const unsigned MaxCount = std::numeric_limits<unsigned>::max(); + + SourceLocation DirectiveLoc; + SourceLocation DiagnosticLoc; + const std::string Text; + unsigned Min, Max; + bool MatchAnyLine; + + Directive(const Directive &) = delete; + Directive &operator=(const Directive &) = delete; + virtual ~Directive() = default; + + // Returns true if directive text is valid. + // Otherwise returns false and populates E. + virtual bool isValid(std::string &Error) = 0; + + // Returns true on match. + virtual bool match(StringRef S) = 0; + + protected: + Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, + bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max) + : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc), + Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) { + assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!"); + assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) && + "DiagnosticLoc is invalid!"); + } + }; + + using DirectiveList = std::vector<std::unique_ptr<Directive>>; + + /// ExpectedData - owns directive objects and deletes on destructor. + struct ExpectedData { + DirectiveList Errors; + DirectiveList Warnings; + DirectiveList Remarks; + DirectiveList Notes; + + void Reset() { + Errors.clear(); + Warnings.clear(); + Remarks.clear(); + Notes.clear(); + } + }; + + enum DirectiveStatus { + HasNoDirectives, + HasNoDirectivesReported, + HasExpectedNoDiagnostics, + HasOtherExpectedDirectives + }; + +private: + DiagnosticsEngine &Diags; + DiagnosticConsumer *PrimaryClient; + std::unique_ptr<DiagnosticConsumer> PrimaryClientOwner; + std::unique_ptr<TextDiagnosticBuffer> Buffer; + const Preprocessor *CurrentPreprocessor = nullptr; + const LangOptions *LangOpts = nullptr; + SourceManager *SrcManager = nullptr; + unsigned ActiveSourceFiles = 0; + DirectiveStatus Status; + ExpectedData ED; + + void CheckDiagnostics(); + + void setSourceManager(SourceManager &SM) { + assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!"); + SrcManager = &SM; + } + + // These facilities are used for validation in debug builds. + class UnparsedFileStatus { + llvm::PointerIntPair<const FileEntry *, 1, bool> Data; + + public: + UnparsedFileStatus(const FileEntry *File, bool FoundDirectives) + : Data(File, FoundDirectives) {} + + const FileEntry *getFile() const { return Data.getPointer(); } + bool foundDirectives() const { return Data.getInt(); } + }; + + using ParsedFilesMap = llvm::DenseMap<FileID, const FileEntry *>; + using UnparsedFilesMap = llvm::DenseMap<FileID, UnparsedFileStatus>; + + ParsedFilesMap ParsedFiles; + UnparsedFilesMap UnparsedFiles; + +public: + /// Create a new verifying diagnostic client, which will issue errors to + /// the currently-attached diagnostic client when a diagnostic does not match + /// what is expected (as indicated in the source file). + VerifyDiagnosticConsumer(DiagnosticsEngine &Diags); + ~VerifyDiagnosticConsumer() override; + + void BeginSourceFile(const LangOptions &LangOpts, + const Preprocessor *PP) override; + + void EndSourceFile() override; + + enum ParsedStatus { + /// File has been processed via HandleComment. + IsParsed, + + /// File has diagnostics and may have directives. + IsUnparsed, + + /// File has diagnostics but guaranteed no directives. + IsUnparsedNoDirectives + }; + + /// Update lists of parsed and unparsed files. + void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS); + + bool HandleComment(Preprocessor &PP, SourceRange Comment) override; + + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override; +}; + +} // namespace clang + +#endif // LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H |
