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(K: K1) || is(K: K2); |
51 | } |
52 | template <typename... Ts> bool isOneOf(tok::TokenKind K1, Ts... Ks) const { |
53 | return is(K: 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 | , |
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; |
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. |
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 | |