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 23namespace clang { 24 25namespace tok { 26enum TokenKind : unsigned short; 27} 28 29class DiagnosticsEngine; 30 31namespace dependency_directives_scan { 32 33/// Token lexed as part of dependency directive scanning. 34struct 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. 59enum 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. 95struct Directive { 96 ArrayRef<Token> Tokens; 97 98 /// The kind of token. 99 DirectiveKind Kind = pp_none; 100 101 Directive() = default; 102 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. 117bool 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. 133void 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