//===--- InclusionRewriter.cpp - Rewrite includes into their expansions ---===// // // 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 code rewrites include invocations into their expansions. This gives you // a file with all included files merged into it. // //===----------------------------------------------------------------------===// #include "clang/Rewrite/Frontend/Rewriters.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/PreprocessorOutputOptions.h" #include "clang/Lex/Pragma.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" #include <optional> usingnamespaceclang; usingnamespacellvm; namespace { class InclusionRewriter : public PPCallbacks { … }; } // end anonymous namespace /// Initializes an InclusionRewriter with a \p PP source and \p OS destination. InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers, bool UseLineDirectives) : … { … } /// Write appropriate line information as either #line directives or GNU line /// markers depending on what mode we're in, including the \p Filename and /// \p Line we are located at, using the specified \p EOL line separator, and /// any \p Extra context specifiers in GNU line directives. void InclusionRewriter::WriteLineInfo(StringRef Filename, int Line, SrcMgr::CharacteristicKind FileType, StringRef Extra) { … } void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod) { … } /// FileChanged - Whenever the preprocessor enters or exits a #include file /// it invokes this handler. void InclusionRewriter::FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind NewFileType, FileID) { … } /// Called whenever an inclusion is skipped due to canonical header protection /// macros. void InclusionRewriter::FileSkipped(const FileEntryRef & /*SkippedFile*/, const Token & /*FilenameTok*/, SrcMgr::CharacteristicKind /*FileType*/) { … } /// This should be called whenever the preprocessor encounters include /// directives. It does not say whether the file has been included, but it /// provides more information about the directive (hash location instead /// of location inside the included file). It is assumed that the matching /// FileChanged() or FileSkipped() is called after this (or neither is /// called if this #include results in an error or does not textually include /// anything). void InclusionRewriter::InclusionDirective( SourceLocation HashLoc, const Token & /*IncludeTok*/, StringRef /*FileName*/, bool /*IsAngled*/, CharSourceRange /*FilenameRange*/, OptionalFileEntryRef /*File*/, StringRef /*SearchPath*/, StringRef /*RelativePath*/, const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) { … } void InclusionRewriter::If(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind ConditionValue) { … } void InclusionRewriter::Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind ConditionValue, SourceLocation IfLoc) { … } /// Simple lookup for a SourceLocation (specifically one denoting the hash in /// an inclusion directive) in the map of inclusion information, FileChanges. const InclusionRewriter::IncludedFile * InclusionRewriter::FindIncludeAtLocation(SourceLocation Loc) const { … } /// Simple lookup for a SourceLocation (specifically one denoting the hash in /// an inclusion directive) in the map of module inclusion information. const Module * InclusionRewriter::FindModuleAtLocation(SourceLocation Loc) const { … } /// Simple lookup for a SourceLocation (specifically one denoting the hash in /// an inclusion directive) in the map of module entry information. const Module * InclusionRewriter::FindEnteredModule(SourceLocation Loc) const { … } bool InclusionRewriter::IsIfAtLocationTrue(SourceLocation Loc) const { … } void InclusionRewriter::detectMainFileEOL() { … } /// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at /// \p WriteTo - 1. void InclusionRewriter::OutputContentUpTo(const MemoryBufferRef &FromFile, unsigned &WriteFrom, unsigned WriteTo, StringRef LocalEOL, int &Line, bool EnsureNewline) { … } StringRef InclusionRewriter::getIncludedFileName(const IncludedFile *Inc) const { … } /// Print characters from \p FromFile starting at \p NextToWrite up until the /// inclusion directive at \p StartToken, then print out the inclusion /// inclusion directive disabled by a #if directive, updating \p NextToWrite /// and \p Line to track the number of source lines visited and the progress /// through the \p FromFile buffer. void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex, const Token &StartToken, const MemoryBufferRef &FromFile, StringRef LocalEOL, unsigned &NextToWrite, int &Line, const IncludedFile *Inc) { … } /// Find the next identifier in the pragma directive specified by \p RawToken. StringRef InclusionRewriter::NextIdentifierName(Lexer &RawLex, Token &RawToken) { … } /// Use a raw lexer to analyze \p FileId, incrementally copying parts of it /// and including content of included files recursively. void InclusionRewriter::Process(FileID FileId, SrcMgr::CharacteristicKind FileType) { … } /// InclusionRewriterInInput - Implement -frewrite-includes mode. void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts) { … }