Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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 | /// 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; |
||
101 | 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 |