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_pragma_system_header, 72 pp_include_next, 73 pp_if, 74 pp_ifdef, 75 pp_ifndef, 76 pp_elif, 77 pp_elifdef, 78 pp_elifndef, 79 pp_else, 80 pp_endif, 81 decl_at_import, 82 cxx_module_decl, 83 cxx_import_decl, 84 cxx_export_module_decl, 85 cxx_export_import_decl, 86 /// Indicates that there are tokens present between the last scanned directive 87 /// and eof. The \p Directive::Tokens array will be empty for this kind. 88 tokens_present_before_eof, 89 pp_eof, 90 }; 91 92 /// Represents a directive that's lexed as part of the dependency directives 93 /// scanning. It's used to track various preprocessor directives that could 94 /// potentially have an effect on the dependencies. 95 struct Directive { 96 ArrayRef<Token> Tokens; 97 98 /// The kind of token. 99 DirectiveKind Kind = pp_none; 100 101 Directive() = default; DirectiveDirective102 Directive(DirectiveKind K, ArrayRef<Token> Tokens) 103 : Tokens(Tokens), Kind(K) {} 104 }; 105 106 } // end namespace dependency_directives_scan 107 108 /// Scan the input for the preprocessor directives that might have 109 /// an effect on the dependencies for a compilation unit. 110 /// 111 /// This function ignores all non-preprocessor code and anything that 112 /// can't affect what gets included. 113 /// 114 /// \returns false on success, true on error. If the diagnostic engine is not 115 /// null, an appropriate error is reported using the given input location 116 /// with the offset that corresponds to the \p Input buffer offset. 117 bool scanSourceForDependencyDirectives( 118 StringRef Input, SmallVectorImpl<dependency_directives_scan::Token> &Tokens, 119 SmallVectorImpl<dependency_directives_scan::Directive> &Directives, 120 DiagnosticsEngine *Diags = nullptr, 121 SourceLocation InputSourceLoc = SourceLocation()); 122 123 /// Print the previously scanned dependency directives as minimized source text. 124 /// 125 /// \param Source The original source text that the dependency directives were 126 /// scanned from. 127 /// \param Directives The previously scanned dependency 128 /// directives. 129 /// \param OS the stream to print the dependency directives on. 130 /// 131 /// This is used primarily for testing purposes, during dependency scanning the 132 /// \p Lexer uses the tokens directly, not their printed version. 133 void printDependencyDirectivesAsSource( 134 StringRef Source, 135 ArrayRef<dependency_directives_scan::Directive> Directives, 136 llvm::raw_ostream &OS); 137 138 } // end namespace clang 139 140 #endif // LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H 141