1 //===- clang/Lex/DependencyDirectivesScanner.h ---------------------*- C++ -*-// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This is the interface for scanning header and source files to get the 11 /// minimum necessary preprocessor directives for evaluating includes. It 12 /// reduces the source down to #define, #include, #import, @import, and any 13 /// conditional preprocessor logic that contains one of those. 14 /// 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H 18 #define LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H 19 20 #include "clang/Basic/SourceLocation.h" 21 #include "llvm/ADT/ArrayRef.h" 22 23 namespace clang { 24 25 namespace tok { 26 enum TokenKind : unsigned short; 27 } 28 29 class DiagnosticsEngine; 30 31 namespace dependency_directives_scan { 32 33 /// Token lexed as part of dependency directive scanning. 34 struct Token { 35 /// Offset into the original source input. 36 unsigned Offset; 37 unsigned Length; 38 tok::TokenKind Kind; 39 unsigned short Flags; 40 TokenToken41 Token(unsigned Offset, unsigned Length, tok::TokenKind Kind, 42 unsigned short Flags) 43 : Offset(Offset), Length(Length), Kind(Kind), Flags(Flags) {} 44 getEndToken45 unsigned getEnd() const { return Offset + Length; } 46 isToken47 bool is(tok::TokenKind K) const { return Kind == K; } isNotToken48 bool isNot(tok::TokenKind K) const { return Kind != K; } isOneOfToken49 bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const { 50 return is(K1) || is(K2); 51 } isOneOfToken52 template <typename... Ts> bool isOneOf(tok::TokenKind K1, Ts... Ks) const { 53 return is(K1) || isOneOf(Ks...); 54 } 55 }; 56 57 /// Represents the kind of preprocessor directive or a module declaration that 58 /// is tracked by the scanner in its token output. 59 enum DirectiveKind : uint8_t { 60 pp_none, 61 pp_include, 62 pp___include_macros, 63 pp_define, 64 pp_undef, 65 pp_import, 66 pp_pragma_import, 67 pp_pragma_once, 68 pp_pragma_push_macro, 69 pp_pragma_pop_macro, 70 pp_pragma_include_alias, 71 pp_include_next, 72 pp_if, 73 pp_ifdef, 74 pp_ifndef, 75 pp_elif, 76 pp_elifdef, 77 pp_elifndef, 78 pp_else, 79 pp_endif, 80 decl_at_import, 81 cxx_module_decl, 82 cxx_import_decl, 83 cxx_export_module_decl, 84 cxx_export_import_decl, 85 /// Indicates that there are tokens present between the last scanned directive 86 /// and eof. The \p Directive::Tokens array will be empty for this kind. 87 tokens_present_before_eof, 88 pp_eof, 89 }; 90 91 /// Represents a directive that's lexed as part of the dependency directives 92 /// scanning. It's used to track various preprocessor directives that could 93 /// potentially have an effect on the dependencies. 94 struct Directive { 95 ArrayRef<Token> Tokens; 96 97 /// The kind of token. 98 DirectiveKind Kind = pp_none; 99 100 Directive() = default; DirectiveDirective101 Directive(DirectiveKind K, ArrayRef<Token> Tokens) 102 : Tokens(Tokens), Kind(K) {} 103 }; 104 105 } // end namespace dependency_directives_scan 106 107 /// Scan the input for the preprocessor directives that might have 108 /// an effect on the dependencies for a compilation unit. 109 /// 110 /// This function ignores all non-preprocessor code and anything that 111 /// can't affect what gets included. 112 /// 113 /// \returns false on success, true on error. If the diagnostic engine is not 114 /// null, an appropriate error is reported using the given input location 115 /// with the offset that corresponds to the \p Input buffer offset. 116 bool scanSourceForDependencyDirectives( 117 StringRef Input, SmallVectorImpl<dependency_directives_scan::Token> &Tokens, 118 SmallVectorImpl<dependency_directives_scan::Directive> &Directives, 119 DiagnosticsEngine *Diags = nullptr, 120 SourceLocation InputSourceLoc = SourceLocation()); 121 122 /// Print the previously scanned dependency directives as minimized source text. 123 /// 124 /// \param Source The original source text that the dependency directives were 125 /// scanned from. 126 /// \param Directives The previously scanned dependency 127 /// directives. 128 /// \param OS the stream to print the dependency directives on. 129 /// 130 /// This is used primarily for testing purposes, during dependency scanning the 131 /// \p Lexer uses the tokens directly, not their printed version. 132 void printDependencyDirectivesAsSource( 133 StringRef Source, 134 ArrayRef<dependency_directives_scan::Directive> Directives, 135 llvm::raw_ostream &OS); 136 137 } // end namespace clang 138 139 #endif // LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H 140