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 41 Token(unsigned Offset, unsigned Length, tok::TokenKind Kind, 42 unsigned short Flags) 43 : Offset(Offset), Length(Length), Kind(Kind), Flags(Flags) {} 44 45 unsigned getEnd() const { return Offset + Length; } 46 47 bool is(tok::TokenKind K) const { return Kind == K; } 48 bool isNot(tok::TokenKind K) const { return Kind != K; } 49 bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const { 50 return is(K1) || is(K2); 51 } 52 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 pp_eof, 86 }; 87 88 /// Represents a directive that's lexed as part of the dependency directives 89 /// scanning. It's used to track various preprocessor directives that could 90 /// potentially have an effect on the depedencies. 91 struct Directive { 92 ArrayRef<Token> Tokens; 93 94 /// The kind of token. 95 DirectiveKind Kind = pp_none; 96 97 Directive() = default; 98 Directive(DirectiveKind K, ArrayRef<Token> Tokens) 99 : Tokens(Tokens), Kind(K) {} 100 }; 101 102 } // end namespace dependency_directives_scan 103 104 /// Scan the input for the preprocessor directives that might have 105 /// an effect on the dependencies for a compilation unit. 106 /// 107 /// This function ignores all non-preprocessor code and anything that 108 /// can't affect what gets included. 109 /// 110 /// \returns false on success, true on error. If the diagnostic engine is not 111 /// null, an appropriate error is reported using the given input location 112 /// with the offset that corresponds to the \p Input buffer offset. 113 bool scanSourceForDependencyDirectives( 114 StringRef Input, SmallVectorImpl<dependency_directives_scan::Token> &Tokens, 115 SmallVectorImpl<dependency_directives_scan::Directive> &Directives, 116 DiagnosticsEngine *Diags = nullptr, 117 SourceLocation InputSourceLoc = SourceLocation()); 118 119 /// Print the previously scanned dependency directives as minimized source text. 120 /// 121 /// \param Source The original source text that the dependency directives were 122 /// scanned from. 123 /// \param Directives The previously scanned dependency 124 /// directives. 125 /// \param OS the stream to print the dependency directives on. 126 /// 127 /// This is used primarily for testing purposes, during dependency scanning the 128 /// \p Lexer uses the tokens directly, not their printed version. 129 void printDependencyDirectivesAsSource( 130 StringRef Source, 131 ArrayRef<dependency_directives_scan::Directive> Directives, 132 llvm::raw_ostream &OS); 133 134 } // end namespace clang 135 136 #endif // LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H 137