xref: /llvm-project/clang/lib/Lex/DependencyDirectivesScanner.cpp (revision d19e71db8a3de65de5da5d5bc4e1f9c1020c574c)
1b58a420fSArgyrios Kyrtzidis //===- DependencyDirectivesScanner.cpp ------------------------------------===//
2b58a420fSArgyrios Kyrtzidis //
3b58a420fSArgyrios Kyrtzidis // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b58a420fSArgyrios Kyrtzidis // See https://llvm.org/LICENSE.txt for license information.
5b58a420fSArgyrios Kyrtzidis // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b58a420fSArgyrios Kyrtzidis //
7b58a420fSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
8b58a420fSArgyrios Kyrtzidis ///
9b58a420fSArgyrios Kyrtzidis /// \file
10b58a420fSArgyrios Kyrtzidis /// This is the interface for scanning header and source files to get the
11b58a420fSArgyrios Kyrtzidis /// minimum necessary preprocessor directives for evaluating includes. It
12b58a420fSArgyrios Kyrtzidis /// reduces the source down to #define, #include, #import, @import, and any
13b58a420fSArgyrios Kyrtzidis /// conditional preprocessor logic that contains one of those.
14b58a420fSArgyrios Kyrtzidis ///
15b58a420fSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
16b58a420fSArgyrios Kyrtzidis 
17b58a420fSArgyrios Kyrtzidis #include "clang/Lex/DependencyDirectivesScanner.h"
18b58a420fSArgyrios Kyrtzidis #include "clang/Basic/CharInfo.h"
19b58a420fSArgyrios Kyrtzidis #include "clang/Basic/Diagnostic.h"
20b58a420fSArgyrios Kyrtzidis #include "clang/Lex/LexDiagnostic.h"
21b4c83a13SArgyrios Kyrtzidis #include "clang/Lex/Lexer.h"
22ee8ed0b3SBen Langmuir #include "clang/Lex/Pragma.h"
23b4c83a13SArgyrios Kyrtzidis #include "llvm/ADT/ScopeExit.h"
24b4c83a13SArgyrios Kyrtzidis #include "llvm/ADT/SmallString.h"
25b58a420fSArgyrios Kyrtzidis #include "llvm/ADT/StringMap.h"
26b58a420fSArgyrios Kyrtzidis #include "llvm/ADT/StringSwitch.h"
27a1580d7bSKazu Hirata #include <optional>
28b58a420fSArgyrios Kyrtzidis 
29b58a420fSArgyrios Kyrtzidis using namespace clang;
30b58a420fSArgyrios Kyrtzidis using namespace clang::dependency_directives_scan;
31b4c83a13SArgyrios Kyrtzidis using namespace llvm;
32b58a420fSArgyrios Kyrtzidis 
33b58a420fSArgyrios Kyrtzidis namespace {
34b58a420fSArgyrios Kyrtzidis 
35b4c83a13SArgyrios Kyrtzidis struct DirectiveWithTokens {
36b4c83a13SArgyrios Kyrtzidis   DirectiveKind Kind;
37b4c83a13SArgyrios Kyrtzidis   unsigned NumTokens;
38b58a420fSArgyrios Kyrtzidis 
39b4c83a13SArgyrios Kyrtzidis   DirectiveWithTokens(DirectiveKind Kind, unsigned NumTokens)
40b4c83a13SArgyrios Kyrtzidis       : Kind(Kind), NumTokens(NumTokens) {}
41b4c83a13SArgyrios Kyrtzidis };
42b4c83a13SArgyrios Kyrtzidis 
43b4c83a13SArgyrios Kyrtzidis /// Does an efficient "scan" of the sources to detect the presence of
44b4c83a13SArgyrios Kyrtzidis /// preprocessor (or module import) directives and collects the raw lexed tokens
45b4c83a13SArgyrios Kyrtzidis /// for those directives so that the \p Lexer can "replay" them when the file is
46b4c83a13SArgyrios Kyrtzidis /// included.
47b4c83a13SArgyrios Kyrtzidis ///
48b4c83a13SArgyrios Kyrtzidis /// Note that the behavior of the raw lexer is affected by the language mode,
49b4c83a13SArgyrios Kyrtzidis /// while at this point we want to do a scan and collect tokens once,
50b4c83a13SArgyrios Kyrtzidis /// irrespective of the language mode that the file will get included in. To
51b4c83a13SArgyrios Kyrtzidis /// compensate for that the \p Lexer, while "replaying", will adjust a token
52b4c83a13SArgyrios Kyrtzidis /// where appropriate, when it could affect the preprocessor's state.
53b4c83a13SArgyrios Kyrtzidis /// For example in a directive like
54b4c83a13SArgyrios Kyrtzidis ///
55b4c83a13SArgyrios Kyrtzidis /// \code
56b4c83a13SArgyrios Kyrtzidis ///   #if __has_cpp_attribute(clang::fallthrough)
57b4c83a13SArgyrios Kyrtzidis /// \endcode
58b4c83a13SArgyrios Kyrtzidis ///
59b4c83a13SArgyrios Kyrtzidis /// The preprocessor needs to see '::' as 'tok::coloncolon' instead of 2
60b4c83a13SArgyrios Kyrtzidis /// 'tok::colon'. The \p Lexer will adjust if it sees consecutive 'tok::colon'
61b4c83a13SArgyrios Kyrtzidis /// while in C++ mode.
62b4c83a13SArgyrios Kyrtzidis struct Scanner {
63b4c83a13SArgyrios Kyrtzidis   Scanner(StringRef Input,
64b4c83a13SArgyrios Kyrtzidis           SmallVectorImpl<dependency_directives_scan::Token> &Tokens,
650559eaffSNishith Kumar M Shah           DiagnosticsEngine *Diags, SourceLocation InputSourceLoc)
66b4c83a13SArgyrios Kyrtzidis       : Input(Input), Tokens(Tokens), Diags(Diags),
670559eaffSNishith Kumar M Shah         InputSourceLoc(InputSourceLoc), LangOpts(getLangOptsForDepScanning()),
680559eaffSNishith Kumar M Shah         TheLexer(InputSourceLoc, LangOpts, Input.begin(), Input.begin(),
69b4c83a13SArgyrios Kyrtzidis                  Input.end()) {}
70b4c83a13SArgyrios Kyrtzidis 
710559eaffSNishith Kumar M Shah   static LangOptions getLangOptsForDepScanning() {
720559eaffSNishith Kumar M Shah     LangOptions LangOpts;
73b4c83a13SArgyrios Kyrtzidis     // Set the lexer to use 'tok::at' for '@', instead of 'tok::unknown'.
74b4c83a13SArgyrios Kyrtzidis     LangOpts.ObjC = true;
75b4c83a13SArgyrios Kyrtzidis     LangOpts.LineComment = true;
76e4646840SSirraide     LangOpts.RawStringLiterals = true;
77e4646840SSirraide     // FIXME: we do not enable C11 or C++11, so we are missing u/u8/U"".
78b4c83a13SArgyrios Kyrtzidis     return LangOpts;
79b4c83a13SArgyrios Kyrtzidis   }
80b58a420fSArgyrios Kyrtzidis 
81b58a420fSArgyrios Kyrtzidis   /// Lex the provided source and emit the directive tokens.
82b58a420fSArgyrios Kyrtzidis   ///
83b58a420fSArgyrios Kyrtzidis   /// \returns True on error.
84b4c83a13SArgyrios Kyrtzidis   bool scan(SmallVectorImpl<Directive> &Directives);
85b58a420fSArgyrios Kyrtzidis 
86b58a420fSArgyrios Kyrtzidis private:
87b4c83a13SArgyrios Kyrtzidis   /// Lexes next token and advances \p First and the \p Lexer.
8832197830SFangrui Song   [[nodiscard]] dependency_directives_scan::Token &
89b4c83a13SArgyrios Kyrtzidis   lexToken(const char *&First, const char *const End);
90b58a420fSArgyrios Kyrtzidis 
9134ab8558SCyndy Ishida   [[nodiscard]] dependency_directives_scan::Token &
9234ab8558SCyndy Ishida   lexIncludeFilename(const char *&First, const char *const End);
93b4c83a13SArgyrios Kyrtzidis 
94aa484c90SArgyrios Kyrtzidis   void skipLine(const char *&First, const char *const End);
95aa484c90SArgyrios Kyrtzidis   void skipDirective(StringRef Name, const char *&First, const char *const End);
96aa484c90SArgyrios Kyrtzidis 
97ee8ed0b3SBen Langmuir   /// Returns the spelling of a string literal or identifier after performing
98ee8ed0b3SBen Langmuir   /// any processing needed to handle \c clang::Token::NeedsCleaning.
99ee8ed0b3SBen Langmuir   StringRef cleanStringIfNeeded(const dependency_directives_scan::Token &Tok);
100ee8ed0b3SBen Langmuir 
101b4c83a13SArgyrios Kyrtzidis   /// Lexes next token and if it is identifier returns its string, otherwise
10237a3e98cSKazu Hirata   /// it skips the current line and returns \p std::nullopt.
103b4c83a13SArgyrios Kyrtzidis   ///
104b4c83a13SArgyrios Kyrtzidis   /// In any case (whatever the token kind) \p First and the \p Lexer will
105b4c83a13SArgyrios Kyrtzidis   /// advance beyond the token.
1066ad0788cSKazu Hirata   [[nodiscard]] std::optional<StringRef>
107b4c83a13SArgyrios Kyrtzidis   tryLexIdentifierOrSkipLine(const char *&First, const char *const End);
108b4c83a13SArgyrios Kyrtzidis 
109b4c83a13SArgyrios Kyrtzidis   /// Used when it is certain that next token is an identifier.
11032197830SFangrui Song   [[nodiscard]] StringRef lexIdentifier(const char *&First,
111b4c83a13SArgyrios Kyrtzidis                                         const char *const End);
112b4c83a13SArgyrios Kyrtzidis 
113b4c83a13SArgyrios Kyrtzidis   /// Lexes next token and returns true iff it is an identifier that matches \p
114b4c83a13SArgyrios Kyrtzidis   /// Id, otherwise it skips the current line and returns false.
115b4c83a13SArgyrios Kyrtzidis   ///
116b4c83a13SArgyrios Kyrtzidis   /// In any case (whatever the token kind) \p First and the \p Lexer will
117b4c83a13SArgyrios Kyrtzidis   /// advance beyond the token.
11832197830SFangrui Song   [[nodiscard]] bool isNextIdentifierOrSkipLine(StringRef Id,
119b4c83a13SArgyrios Kyrtzidis                                                 const char *&First,
120b4c83a13SArgyrios Kyrtzidis                                                 const char *const End);
121b4c83a13SArgyrios Kyrtzidis 
122ee8ed0b3SBen Langmuir   /// Lexes next token and returns true iff it matches the kind \p K.
123ee8ed0b3SBen Langmuir   /// Otherwise it skips the current line and returns false.
124ee8ed0b3SBen Langmuir   ///
125ee8ed0b3SBen Langmuir   /// In any case (whatever the token kind) \p First and the \p Lexer will
126ee8ed0b3SBen Langmuir   /// advance beyond the token.
127ee8ed0b3SBen Langmuir   [[nodiscard]] bool isNextTokenOrSkipLine(tok::TokenKind K, const char *&First,
128ee8ed0b3SBen Langmuir                                            const char *const End);
129ee8ed0b3SBen Langmuir 
130ee8ed0b3SBen Langmuir   /// Lexes next token and if it is string literal, returns its string.
131ee8ed0b3SBen Langmuir   /// Otherwise, it skips the current line and returns \p std::nullopt.
132ee8ed0b3SBen Langmuir   ///
133ee8ed0b3SBen Langmuir   /// In any case (whatever the token kind) \p First and the \p Lexer will
134ee8ed0b3SBen Langmuir   /// advance beyond the token.
135ee8ed0b3SBen Langmuir   [[nodiscard]] std::optional<StringRef>
136ee8ed0b3SBen Langmuir   tryLexStringLiteralOrSkipLine(const char *&First, const char *const End);
137ee8ed0b3SBen Langmuir 
13832197830SFangrui Song   [[nodiscard]] bool scanImpl(const char *First, const char *const End);
13932197830SFangrui Song   [[nodiscard]] bool lexPPLine(const char *&First, const char *const End);
14032197830SFangrui Song   [[nodiscard]] bool lexAt(const char *&First, const char *const End);
14132197830SFangrui Song   [[nodiscard]] bool lexModule(const char *&First, const char *const End);
14232197830SFangrui Song   [[nodiscard]] bool lexDefine(const char *HashLoc, const char *&First,
143b4c83a13SArgyrios Kyrtzidis                                const char *const End);
14432197830SFangrui Song   [[nodiscard]] bool lexPragma(const char *&First, const char *const End);
145ee8ed0b3SBen Langmuir   [[nodiscard]] bool lex_Pragma(const char *&First, const char *const End);
14632197830SFangrui Song   [[nodiscard]] bool lexEndif(const char *&First, const char *const End);
14732197830SFangrui Song   [[nodiscard]] bool lexDefault(DirectiveKind Kind, const char *&First,
148b4c83a13SArgyrios Kyrtzidis                                 const char *const End);
14932197830SFangrui Song   [[nodiscard]] bool lexModuleDirectiveBody(DirectiveKind Kind,
150b4c83a13SArgyrios Kyrtzidis                                             const char *&First,
151b4c83a13SArgyrios Kyrtzidis                                             const char *const End);
152b4c83a13SArgyrios Kyrtzidis   void lexPPDirectiveBody(const char *&First, const char *const End);
153b4c83a13SArgyrios Kyrtzidis 
154b4c83a13SArgyrios Kyrtzidis   DirectiveWithTokens &pushDirective(DirectiveKind Kind) {
155b4c83a13SArgyrios Kyrtzidis     Tokens.append(CurDirToks);
156b4c83a13SArgyrios Kyrtzidis     DirsWithToks.emplace_back(Kind, CurDirToks.size());
157b4c83a13SArgyrios Kyrtzidis     CurDirToks.clear();
158b4c83a13SArgyrios Kyrtzidis     return DirsWithToks.back();
159b58a420fSArgyrios Kyrtzidis   }
160b58a420fSArgyrios Kyrtzidis   void popDirective() {
161b4c83a13SArgyrios Kyrtzidis     Tokens.pop_back_n(DirsWithToks.pop_back_val().NumTokens);
162b58a420fSArgyrios Kyrtzidis   }
163b58a420fSArgyrios Kyrtzidis   DirectiveKind topDirective() const {
164b4c83a13SArgyrios Kyrtzidis     return DirsWithToks.empty() ? pp_none : DirsWithToks.back().Kind;
165b58a420fSArgyrios Kyrtzidis   }
166b58a420fSArgyrios Kyrtzidis 
167b4c83a13SArgyrios Kyrtzidis   unsigned getOffsetAt(const char *CurPtr) const {
168b4c83a13SArgyrios Kyrtzidis     return CurPtr - Input.data();
169b58a420fSArgyrios Kyrtzidis   }
170b58a420fSArgyrios Kyrtzidis 
171b58a420fSArgyrios Kyrtzidis   /// Reports a diagnostic if the diagnostic engine is provided. Always returns
172b58a420fSArgyrios Kyrtzidis   /// true at the end.
173b58a420fSArgyrios Kyrtzidis   bool reportError(const char *CurPtr, unsigned Err);
174b58a420fSArgyrios Kyrtzidis 
175b58a420fSArgyrios Kyrtzidis   StringMap<char> SplitIds;
176b58a420fSArgyrios Kyrtzidis   StringRef Input;
177b4c83a13SArgyrios Kyrtzidis   SmallVectorImpl<dependency_directives_scan::Token> &Tokens;
178b58a420fSArgyrios Kyrtzidis   DiagnosticsEngine *Diags;
179b58a420fSArgyrios Kyrtzidis   SourceLocation InputSourceLoc;
180b4c83a13SArgyrios Kyrtzidis 
181aa484c90SArgyrios Kyrtzidis   const char *LastTokenPtr = nullptr;
182b4c83a13SArgyrios Kyrtzidis   /// Keeps track of the tokens for the currently lexed directive. Once a
183b4c83a13SArgyrios Kyrtzidis   /// directive is fully lexed and "committed" then the tokens get appended to
184b4c83a13SArgyrios Kyrtzidis   /// \p Tokens and \p CurDirToks is cleared for the next directive.
185b4c83a13SArgyrios Kyrtzidis   SmallVector<dependency_directives_scan::Token, 32> CurDirToks;
186b4c83a13SArgyrios Kyrtzidis   /// The directives that were lexed along with the number of tokens that each
187b4c83a13SArgyrios Kyrtzidis   /// directive contains. The tokens of all the directives are kept in \p Tokens
188b4c83a13SArgyrios Kyrtzidis   /// vector, in the same order as the directives order in \p DirsWithToks.
189b4c83a13SArgyrios Kyrtzidis   SmallVector<DirectiveWithTokens, 64> DirsWithToks;
190b4c83a13SArgyrios Kyrtzidis   LangOptions LangOpts;
191b4c83a13SArgyrios Kyrtzidis   Lexer TheLexer;
192b58a420fSArgyrios Kyrtzidis };
193b58a420fSArgyrios Kyrtzidis 
194b58a420fSArgyrios Kyrtzidis } // end anonymous namespace
195b58a420fSArgyrios Kyrtzidis 
196b58a420fSArgyrios Kyrtzidis bool Scanner::reportError(const char *CurPtr, unsigned Err) {
197b58a420fSArgyrios Kyrtzidis   if (!Diags)
198b58a420fSArgyrios Kyrtzidis     return true;
199b58a420fSArgyrios Kyrtzidis   assert(CurPtr >= Input.data() && "invalid buffer ptr");
200b4c83a13SArgyrios Kyrtzidis   Diags->Report(InputSourceLoc.getLocWithOffset(getOffsetAt(CurPtr)), Err);
201b58a420fSArgyrios Kyrtzidis   return true;
202b58a420fSArgyrios Kyrtzidis }
203b58a420fSArgyrios Kyrtzidis 
204b58a420fSArgyrios Kyrtzidis static void skipOverSpaces(const char *&First, const char *const End) {
205b58a420fSArgyrios Kyrtzidis   while (First != End && isHorizontalWhitespace(*First))
206b58a420fSArgyrios Kyrtzidis     ++First;
207b58a420fSArgyrios Kyrtzidis }
208b58a420fSArgyrios Kyrtzidis 
20932197830SFangrui Song [[nodiscard]] static bool isRawStringLiteral(const char *First,
210b58a420fSArgyrios Kyrtzidis                                              const char *Current) {
211b58a420fSArgyrios Kyrtzidis   assert(First <= Current);
212b58a420fSArgyrios Kyrtzidis 
213b58a420fSArgyrios Kyrtzidis   // Check if we can even back up.
214b58a420fSArgyrios Kyrtzidis   if (*Current != '"' || First == Current)
215b58a420fSArgyrios Kyrtzidis     return false;
216b58a420fSArgyrios Kyrtzidis 
217b58a420fSArgyrios Kyrtzidis   // Check for an "R".
218b58a420fSArgyrios Kyrtzidis   --Current;
219b58a420fSArgyrios Kyrtzidis   if (*Current != 'R')
220b58a420fSArgyrios Kyrtzidis     return false;
221b58a420fSArgyrios Kyrtzidis   if (First == Current || !isAsciiIdentifierContinue(*--Current))
222b58a420fSArgyrios Kyrtzidis     return true;
223b58a420fSArgyrios Kyrtzidis 
224b58a420fSArgyrios Kyrtzidis   // Check for a prefix of "u", "U", or "L".
225b58a420fSArgyrios Kyrtzidis   if (*Current == 'u' || *Current == 'U' || *Current == 'L')
226b58a420fSArgyrios Kyrtzidis     return First == Current || !isAsciiIdentifierContinue(*--Current);
227b58a420fSArgyrios Kyrtzidis 
228b58a420fSArgyrios Kyrtzidis   // Check for a prefix of "u8".
229b58a420fSArgyrios Kyrtzidis   if (*Current != '8' || First == Current || *Current-- != 'u')
230b58a420fSArgyrios Kyrtzidis     return false;
231b58a420fSArgyrios Kyrtzidis   return First == Current || !isAsciiIdentifierContinue(*--Current);
232b58a420fSArgyrios Kyrtzidis }
233b58a420fSArgyrios Kyrtzidis 
234b58a420fSArgyrios Kyrtzidis static void skipRawString(const char *&First, const char *const End) {
235b58a420fSArgyrios Kyrtzidis   assert(First[0] == '"');
236b58a420fSArgyrios Kyrtzidis   assert(First[-1] == 'R');
237b58a420fSArgyrios Kyrtzidis 
238b58a420fSArgyrios Kyrtzidis   const char *Last = ++First;
239b58a420fSArgyrios Kyrtzidis   while (Last != End && *Last != '(')
240b58a420fSArgyrios Kyrtzidis     ++Last;
241b58a420fSArgyrios Kyrtzidis   if (Last == End) {
242b58a420fSArgyrios Kyrtzidis     First = Last; // Hit the end... just give up.
243b58a420fSArgyrios Kyrtzidis     return;
244b58a420fSArgyrios Kyrtzidis   }
245b58a420fSArgyrios Kyrtzidis 
246b58a420fSArgyrios Kyrtzidis   StringRef Terminator(First, Last - First);
247b58a420fSArgyrios Kyrtzidis   for (;;) {
248b58a420fSArgyrios Kyrtzidis     // Move First to just past the next ")".
249b58a420fSArgyrios Kyrtzidis     First = Last;
250b58a420fSArgyrios Kyrtzidis     while (First != End && *First != ')')
251b58a420fSArgyrios Kyrtzidis       ++First;
252b58a420fSArgyrios Kyrtzidis     if (First == End)
253b58a420fSArgyrios Kyrtzidis       return;
254b58a420fSArgyrios Kyrtzidis     ++First;
255b58a420fSArgyrios Kyrtzidis 
256b58a420fSArgyrios Kyrtzidis     // Look ahead for the terminator sequence.
257b58a420fSArgyrios Kyrtzidis     Last = First;
258b58a420fSArgyrios Kyrtzidis     while (Last != End && size_t(Last - First) < Terminator.size() &&
259b58a420fSArgyrios Kyrtzidis            Terminator[Last - First] == *Last)
260b58a420fSArgyrios Kyrtzidis       ++Last;
261b58a420fSArgyrios Kyrtzidis 
262b58a420fSArgyrios Kyrtzidis     // Check if we hit it (or the end of the file).
263b58a420fSArgyrios Kyrtzidis     if (Last == End) {
264b58a420fSArgyrios Kyrtzidis       First = Last;
265b58a420fSArgyrios Kyrtzidis       return;
266b58a420fSArgyrios Kyrtzidis     }
267b58a420fSArgyrios Kyrtzidis     if (size_t(Last - First) < Terminator.size())
268b58a420fSArgyrios Kyrtzidis       continue;
269b58a420fSArgyrios Kyrtzidis     if (*Last != '"')
270b58a420fSArgyrios Kyrtzidis       continue;
271b58a420fSArgyrios Kyrtzidis     First = Last + 1;
272b58a420fSArgyrios Kyrtzidis     return;
273b58a420fSArgyrios Kyrtzidis   }
274b58a420fSArgyrios Kyrtzidis }
275b58a420fSArgyrios Kyrtzidis 
276b58a420fSArgyrios Kyrtzidis // Returns the length of EOL, either 0 (no end-of-line), 1 (\n) or 2 (\r\n)
277b58a420fSArgyrios Kyrtzidis static unsigned isEOL(const char *First, const char *const End) {
278b58a420fSArgyrios Kyrtzidis   if (First == End)
279b58a420fSArgyrios Kyrtzidis     return 0;
280b58a420fSArgyrios Kyrtzidis   if (End - First > 1 && isVerticalWhitespace(First[0]) &&
281b58a420fSArgyrios Kyrtzidis       isVerticalWhitespace(First[1]) && First[0] != First[1])
282b58a420fSArgyrios Kyrtzidis     return 2;
283b58a420fSArgyrios Kyrtzidis   return !!isVerticalWhitespace(First[0]);
284b58a420fSArgyrios Kyrtzidis }
285b58a420fSArgyrios Kyrtzidis 
286b58a420fSArgyrios Kyrtzidis static void skipString(const char *&First, const char *const End) {
287b58a420fSArgyrios Kyrtzidis   assert(*First == '\'' || *First == '"' || *First == '<');
288b58a420fSArgyrios Kyrtzidis   const char Terminator = *First == '<' ? '>' : *First;
289b58a420fSArgyrios Kyrtzidis   for (++First; First != End && *First != Terminator; ++First) {
290b58a420fSArgyrios Kyrtzidis     // String and character literals don't extend past the end of the line.
291b58a420fSArgyrios Kyrtzidis     if (isVerticalWhitespace(*First))
292b58a420fSArgyrios Kyrtzidis       return;
293b58a420fSArgyrios Kyrtzidis     if (*First != '\\')
294b58a420fSArgyrios Kyrtzidis       continue;
295b58a420fSArgyrios Kyrtzidis     // Skip past backslash to the next character. This ensures that the
296b58a420fSArgyrios Kyrtzidis     // character right after it is skipped as well, which matters if it's
297b58a420fSArgyrios Kyrtzidis     // the terminator.
298b58a420fSArgyrios Kyrtzidis     if (++First == End)
299b58a420fSArgyrios Kyrtzidis       return;
300b58a420fSArgyrios Kyrtzidis     if (!isWhitespace(*First))
301b58a420fSArgyrios Kyrtzidis       continue;
302b58a420fSArgyrios Kyrtzidis     // Whitespace after the backslash might indicate a line continuation.
303b58a420fSArgyrios Kyrtzidis     const char *FirstAfterBackslashPastSpace = First;
304b58a420fSArgyrios Kyrtzidis     skipOverSpaces(FirstAfterBackslashPastSpace, End);
305b58a420fSArgyrios Kyrtzidis     if (unsigned NLSize = isEOL(FirstAfterBackslashPastSpace, End)) {
306b58a420fSArgyrios Kyrtzidis       // Advance the character pointer to the next line for the next
307b58a420fSArgyrios Kyrtzidis       // iteration.
308b58a420fSArgyrios Kyrtzidis       First = FirstAfterBackslashPastSpace + NLSize - 1;
309b58a420fSArgyrios Kyrtzidis     }
310b58a420fSArgyrios Kyrtzidis   }
311b58a420fSArgyrios Kyrtzidis   if (First != End)
312b58a420fSArgyrios Kyrtzidis     ++First; // Finish off the string.
313b58a420fSArgyrios Kyrtzidis }
314b58a420fSArgyrios Kyrtzidis 
315b58a420fSArgyrios Kyrtzidis // Returns the length of the skipped newline
316b58a420fSArgyrios Kyrtzidis static unsigned skipNewline(const char *&First, const char *End) {
317b58a420fSArgyrios Kyrtzidis   if (First == End)
318b58a420fSArgyrios Kyrtzidis     return 0;
319b58a420fSArgyrios Kyrtzidis   assert(isVerticalWhitespace(*First));
320b58a420fSArgyrios Kyrtzidis   unsigned Len = isEOL(First, End);
321b58a420fSArgyrios Kyrtzidis   assert(Len && "expected newline");
322b58a420fSArgyrios Kyrtzidis   First += Len;
323b58a420fSArgyrios Kyrtzidis   return Len;
324b58a420fSArgyrios Kyrtzidis }
325b58a420fSArgyrios Kyrtzidis 
326b58a420fSArgyrios Kyrtzidis static bool wasLineContinuation(const char *First, unsigned EOLLen) {
327b58a420fSArgyrios Kyrtzidis   return *(First - (int)EOLLen - 1) == '\\';
328b58a420fSArgyrios Kyrtzidis }
329b58a420fSArgyrios Kyrtzidis 
330b58a420fSArgyrios Kyrtzidis static void skipToNewlineRaw(const char *&First, const char *const End) {
331b58a420fSArgyrios Kyrtzidis   for (;;) {
332b58a420fSArgyrios Kyrtzidis     if (First == End)
333b58a420fSArgyrios Kyrtzidis       return;
334b58a420fSArgyrios Kyrtzidis 
335b58a420fSArgyrios Kyrtzidis     unsigned Len = isEOL(First, End);
336b58a420fSArgyrios Kyrtzidis     if (Len)
337b58a420fSArgyrios Kyrtzidis       return;
338b58a420fSArgyrios Kyrtzidis 
339b58a420fSArgyrios Kyrtzidis     do {
340b58a420fSArgyrios Kyrtzidis       if (++First == End)
341b58a420fSArgyrios Kyrtzidis         return;
342b58a420fSArgyrios Kyrtzidis       Len = isEOL(First, End);
343b58a420fSArgyrios Kyrtzidis     } while (!Len);
344b58a420fSArgyrios Kyrtzidis 
345b58a420fSArgyrios Kyrtzidis     if (First[-1] != '\\')
346b58a420fSArgyrios Kyrtzidis       return;
347b58a420fSArgyrios Kyrtzidis 
348b58a420fSArgyrios Kyrtzidis     First += Len;
349b58a420fSArgyrios Kyrtzidis     // Keep skipping lines...
350b58a420fSArgyrios Kyrtzidis   }
351b58a420fSArgyrios Kyrtzidis }
352b58a420fSArgyrios Kyrtzidis 
353b58a420fSArgyrios Kyrtzidis static void skipLineComment(const char *&First, const char *const End) {
354b58a420fSArgyrios Kyrtzidis   assert(First[0] == '/' && First[1] == '/');
355b58a420fSArgyrios Kyrtzidis   First += 2;
356b58a420fSArgyrios Kyrtzidis   skipToNewlineRaw(First, End);
357b58a420fSArgyrios Kyrtzidis }
358b58a420fSArgyrios Kyrtzidis 
359b58a420fSArgyrios Kyrtzidis static void skipBlockComment(const char *&First, const char *const End) {
360b58a420fSArgyrios Kyrtzidis   assert(First[0] == '/' && First[1] == '*');
361b58a420fSArgyrios Kyrtzidis   if (End - First < 4) {
362b58a420fSArgyrios Kyrtzidis     First = End;
363b58a420fSArgyrios Kyrtzidis     return;
364b58a420fSArgyrios Kyrtzidis   }
365b58a420fSArgyrios Kyrtzidis   for (First += 3; First != End; ++First)
366b58a420fSArgyrios Kyrtzidis     if (First[-1] == '*' && First[0] == '/') {
367b58a420fSArgyrios Kyrtzidis       ++First;
368b58a420fSArgyrios Kyrtzidis       return;
369b58a420fSArgyrios Kyrtzidis     }
370b58a420fSArgyrios Kyrtzidis }
371b58a420fSArgyrios Kyrtzidis 
372b58a420fSArgyrios Kyrtzidis /// \returns True if the current single quotation mark character is a C++14
373b58a420fSArgyrios Kyrtzidis /// digit separator.
374b58a420fSArgyrios Kyrtzidis static bool isQuoteCppDigitSeparator(const char *const Start,
375b58a420fSArgyrios Kyrtzidis                                      const char *const Cur,
376b58a420fSArgyrios Kyrtzidis                                      const char *const End) {
377b58a420fSArgyrios Kyrtzidis   assert(*Cur == '\'' && "expected quotation character");
378b58a420fSArgyrios Kyrtzidis   // skipLine called in places where we don't expect a valid number
379b58a420fSArgyrios Kyrtzidis   // body before `start` on the same line, so always return false at the start.
380b58a420fSArgyrios Kyrtzidis   if (Start == Cur)
381b58a420fSArgyrios Kyrtzidis     return false;
382b58a420fSArgyrios Kyrtzidis   // The previous character must be a valid PP number character.
383b58a420fSArgyrios Kyrtzidis   // Make sure that the L, u, U, u8 prefixes don't get marked as a
384b58a420fSArgyrios Kyrtzidis   // separator though.
385b58a420fSArgyrios Kyrtzidis   char Prev = *(Cur - 1);
386b58a420fSArgyrios Kyrtzidis   if (Prev == 'L' || Prev == 'U' || Prev == 'u')
387b58a420fSArgyrios Kyrtzidis     return false;
388b58a420fSArgyrios Kyrtzidis   if (Prev == '8' && (Cur - 1 != Start) && *(Cur - 2) == 'u')
389b58a420fSArgyrios Kyrtzidis     return false;
390b58a420fSArgyrios Kyrtzidis   if (!isPreprocessingNumberBody(Prev))
391b58a420fSArgyrios Kyrtzidis     return false;
392b58a420fSArgyrios Kyrtzidis   // The next character should be a valid identifier body character.
393b58a420fSArgyrios Kyrtzidis   return (Cur + 1) < End && isAsciiIdentifierContinue(*(Cur + 1));
394b58a420fSArgyrios Kyrtzidis }
395b58a420fSArgyrios Kyrtzidis 
396aa484c90SArgyrios Kyrtzidis void Scanner::skipLine(const char *&First, const char *const End) {
397b58a420fSArgyrios Kyrtzidis   for (;;) {
398b58a420fSArgyrios Kyrtzidis     assert(First <= End);
399b58a420fSArgyrios Kyrtzidis     if (First == End)
400b58a420fSArgyrios Kyrtzidis       return;
401b58a420fSArgyrios Kyrtzidis 
402b58a420fSArgyrios Kyrtzidis     if (isVerticalWhitespace(*First)) {
403b58a420fSArgyrios Kyrtzidis       skipNewline(First, End);
404b58a420fSArgyrios Kyrtzidis       return;
405b58a420fSArgyrios Kyrtzidis     }
406b58a420fSArgyrios Kyrtzidis     const char *Start = First;
407b58a420fSArgyrios Kyrtzidis     while (First != End && !isVerticalWhitespace(*First)) {
408b58a420fSArgyrios Kyrtzidis       // Iterate over strings correctly to avoid comments and newlines.
409b58a420fSArgyrios Kyrtzidis       if (*First == '"' ||
410b58a420fSArgyrios Kyrtzidis           (*First == '\'' && !isQuoteCppDigitSeparator(Start, First, End))) {
411aa484c90SArgyrios Kyrtzidis         LastTokenPtr = First;
412b58a420fSArgyrios Kyrtzidis         if (isRawStringLiteral(Start, First))
413b58a420fSArgyrios Kyrtzidis           skipRawString(First, End);
414b58a420fSArgyrios Kyrtzidis         else
415b58a420fSArgyrios Kyrtzidis           skipString(First, End);
416b58a420fSArgyrios Kyrtzidis         continue;
417b58a420fSArgyrios Kyrtzidis       }
418b58a420fSArgyrios Kyrtzidis 
419b58a420fSArgyrios Kyrtzidis       // Iterate over comments correctly.
420b58a420fSArgyrios Kyrtzidis       if (*First != '/' || End - First < 2) {
421aa484c90SArgyrios Kyrtzidis         LastTokenPtr = First;
422b58a420fSArgyrios Kyrtzidis         ++First;
423b58a420fSArgyrios Kyrtzidis         continue;
424b58a420fSArgyrios Kyrtzidis       }
425b58a420fSArgyrios Kyrtzidis 
426b58a420fSArgyrios Kyrtzidis       if (First[1] == '/') {
427b58a420fSArgyrios Kyrtzidis         // "//...".
428b58a420fSArgyrios Kyrtzidis         skipLineComment(First, End);
429b58a420fSArgyrios Kyrtzidis         continue;
430b58a420fSArgyrios Kyrtzidis       }
431b58a420fSArgyrios Kyrtzidis 
432b58a420fSArgyrios Kyrtzidis       if (First[1] != '*') {
433aa484c90SArgyrios Kyrtzidis         LastTokenPtr = First;
434b58a420fSArgyrios Kyrtzidis         ++First;
435b58a420fSArgyrios Kyrtzidis         continue;
436b58a420fSArgyrios Kyrtzidis       }
437b58a420fSArgyrios Kyrtzidis 
438b58a420fSArgyrios Kyrtzidis       // "/*...*/".
439b58a420fSArgyrios Kyrtzidis       skipBlockComment(First, End);
440b58a420fSArgyrios Kyrtzidis     }
441b58a420fSArgyrios Kyrtzidis     if (First == End)
442b58a420fSArgyrios Kyrtzidis       return;
443b58a420fSArgyrios Kyrtzidis 
444b58a420fSArgyrios Kyrtzidis     // Skip over the newline.
445b58a420fSArgyrios Kyrtzidis     unsigned Len = skipNewline(First, End);
446b58a420fSArgyrios Kyrtzidis     if (!wasLineContinuation(First, Len)) // Continue past line-continuations.
447b58a420fSArgyrios Kyrtzidis       break;
448b58a420fSArgyrios Kyrtzidis   }
449b58a420fSArgyrios Kyrtzidis }
450b58a420fSArgyrios Kyrtzidis 
451aa484c90SArgyrios Kyrtzidis void Scanner::skipDirective(StringRef Name, const char *&First,
452b58a420fSArgyrios Kyrtzidis                             const char *const End) {
453b58a420fSArgyrios Kyrtzidis   if (llvm::StringSwitch<bool>(Name)
454b58a420fSArgyrios Kyrtzidis           .Case("warning", true)
455b58a420fSArgyrios Kyrtzidis           .Case("error", true)
456b58a420fSArgyrios Kyrtzidis           .Default(false))
457b58a420fSArgyrios Kyrtzidis     // Do not process quotes or comments.
458b58a420fSArgyrios Kyrtzidis     skipToNewlineRaw(First, End);
459b58a420fSArgyrios Kyrtzidis   else
460b58a420fSArgyrios Kyrtzidis     skipLine(First, End);
461b58a420fSArgyrios Kyrtzidis }
462b58a420fSArgyrios Kyrtzidis 
463b58a420fSArgyrios Kyrtzidis static void skipWhitespace(const char *&First, const char *const End) {
464b58a420fSArgyrios Kyrtzidis   for (;;) {
465b58a420fSArgyrios Kyrtzidis     assert(First <= End);
466b58a420fSArgyrios Kyrtzidis     skipOverSpaces(First, End);
467b58a420fSArgyrios Kyrtzidis 
468b58a420fSArgyrios Kyrtzidis     if (End - First < 2)
469b58a420fSArgyrios Kyrtzidis       return;
470b58a420fSArgyrios Kyrtzidis 
471b58a420fSArgyrios Kyrtzidis     if (First[0] == '\\' && isVerticalWhitespace(First[1])) {
472b58a420fSArgyrios Kyrtzidis       skipNewline(++First, End);
473b58a420fSArgyrios Kyrtzidis       continue;
474b58a420fSArgyrios Kyrtzidis     }
475b58a420fSArgyrios Kyrtzidis 
476b58a420fSArgyrios Kyrtzidis     // Check for a non-comment character.
477b58a420fSArgyrios Kyrtzidis     if (First[0] != '/')
478b58a420fSArgyrios Kyrtzidis       return;
479b58a420fSArgyrios Kyrtzidis 
480b58a420fSArgyrios Kyrtzidis     // "// ...".
481b58a420fSArgyrios Kyrtzidis     if (First[1] == '/') {
482b58a420fSArgyrios Kyrtzidis       skipLineComment(First, End);
483b58a420fSArgyrios Kyrtzidis       return;
484b58a420fSArgyrios Kyrtzidis     }
485b58a420fSArgyrios Kyrtzidis 
486b58a420fSArgyrios Kyrtzidis     // Cannot be a comment.
487b58a420fSArgyrios Kyrtzidis     if (First[1] != '*')
488b58a420fSArgyrios Kyrtzidis       return;
489b58a420fSArgyrios Kyrtzidis 
490b58a420fSArgyrios Kyrtzidis     // "/*...*/".
491b58a420fSArgyrios Kyrtzidis     skipBlockComment(First, End);
492b58a420fSArgyrios Kyrtzidis   }
493b58a420fSArgyrios Kyrtzidis }
494b58a420fSArgyrios Kyrtzidis 
495b4c83a13SArgyrios Kyrtzidis bool Scanner::lexModuleDirectiveBody(DirectiveKind Kind, const char *&First,
496b58a420fSArgyrios Kyrtzidis                                      const char *const End) {
497b4c83a13SArgyrios Kyrtzidis   const char *DirectiveLoc = Input.data() + CurDirToks.front().Offset;
498b58a420fSArgyrios Kyrtzidis   for (;;) {
499b4c83a13SArgyrios Kyrtzidis     const dependency_directives_scan::Token &Tok = lexToken(First, End);
500b4c83a13SArgyrios Kyrtzidis     if (Tok.is(tok::eof))
501b58a420fSArgyrios Kyrtzidis       return reportError(
502b4c83a13SArgyrios Kyrtzidis           DirectiveLoc,
503b4c83a13SArgyrios Kyrtzidis           diag::err_dep_source_scanner_missing_semi_after_at_import);
504b4c83a13SArgyrios Kyrtzidis     if (Tok.is(tok::semi))
505b4c83a13SArgyrios Kyrtzidis       break;
506b4c83a13SArgyrios Kyrtzidis   }
507b4c83a13SArgyrios Kyrtzidis   pushDirective(Kind);
508b58a420fSArgyrios Kyrtzidis   skipWhitespace(First, End);
509b58a420fSArgyrios Kyrtzidis   if (First == End)
510b58a420fSArgyrios Kyrtzidis     return false;
511b58a420fSArgyrios Kyrtzidis   if (!isVerticalWhitespace(*First))
512b58a420fSArgyrios Kyrtzidis     return reportError(
513b4c83a13SArgyrios Kyrtzidis         DirectiveLoc, diag::err_dep_source_scanner_unexpected_tokens_at_import);
514b58a420fSArgyrios Kyrtzidis   skipNewline(First, End);
515b58a420fSArgyrios Kyrtzidis   return false;
516b58a420fSArgyrios Kyrtzidis }
517b58a420fSArgyrios Kyrtzidis 
518b4c83a13SArgyrios Kyrtzidis dependency_directives_scan::Token &Scanner::lexToken(const char *&First,
519b4c83a13SArgyrios Kyrtzidis                                                      const char *const End) {
520b4c83a13SArgyrios Kyrtzidis   clang::Token Tok;
521b4c83a13SArgyrios Kyrtzidis   TheLexer.LexFromRawLexer(Tok);
522b4c83a13SArgyrios Kyrtzidis   First = Input.data() + TheLexer.getCurrentBufferOffset();
523b4c83a13SArgyrios Kyrtzidis   assert(First <= End);
524b4c83a13SArgyrios Kyrtzidis 
525b4c83a13SArgyrios Kyrtzidis   unsigned Offset = TheLexer.getCurrentBufferOffset() - Tok.getLength();
526b4c83a13SArgyrios Kyrtzidis   CurDirToks.emplace_back(Offset, Tok.getLength(), Tok.getKind(),
527b4c83a13SArgyrios Kyrtzidis                           Tok.getFlags());
528b4c83a13SArgyrios Kyrtzidis   return CurDirToks.back();
529b58a420fSArgyrios Kyrtzidis }
530b58a420fSArgyrios Kyrtzidis 
531b4c83a13SArgyrios Kyrtzidis dependency_directives_scan::Token &
532b4c83a13SArgyrios Kyrtzidis Scanner::lexIncludeFilename(const char *&First, const char *const End) {
533b4c83a13SArgyrios Kyrtzidis   clang::Token Tok;
534b4c83a13SArgyrios Kyrtzidis   TheLexer.LexIncludeFilename(Tok);
535b4c83a13SArgyrios Kyrtzidis   First = Input.data() + TheLexer.getCurrentBufferOffset();
536b4c83a13SArgyrios Kyrtzidis   assert(First <= End);
537b4c83a13SArgyrios Kyrtzidis 
538b4c83a13SArgyrios Kyrtzidis   unsigned Offset = TheLexer.getCurrentBufferOffset() - Tok.getLength();
539b4c83a13SArgyrios Kyrtzidis   CurDirToks.emplace_back(Offset, Tok.getLength(), Tok.getKind(),
540b4c83a13SArgyrios Kyrtzidis                           Tok.getFlags());
541b4c83a13SArgyrios Kyrtzidis   return CurDirToks.back();
542b4c83a13SArgyrios Kyrtzidis }
543b4c83a13SArgyrios Kyrtzidis 
544b4c83a13SArgyrios Kyrtzidis void Scanner::lexPPDirectiveBody(const char *&First, const char *const End) {
545b4c83a13SArgyrios Kyrtzidis   while (true) {
546b4c83a13SArgyrios Kyrtzidis     const dependency_directives_scan::Token &Tok = lexToken(First, End);
54734ab8558SCyndy Ishida     if (Tok.is(tok::eod) || Tok.is(tok::eof))
548b4c83a13SArgyrios Kyrtzidis       break;
549b4c83a13SArgyrios Kyrtzidis   }
550b4c83a13SArgyrios Kyrtzidis }
551b4c83a13SArgyrios Kyrtzidis 
552ee8ed0b3SBen Langmuir StringRef
553ee8ed0b3SBen Langmuir Scanner::cleanStringIfNeeded(const dependency_directives_scan::Token &Tok) {
554b4c83a13SArgyrios Kyrtzidis   bool NeedsCleaning = Tok.Flags & clang::Token::NeedsCleaning;
555b4c83a13SArgyrios Kyrtzidis   if (LLVM_LIKELY(!NeedsCleaning))
556b4c83a13SArgyrios Kyrtzidis     return Input.slice(Tok.Offset, Tok.getEnd());
557b4c83a13SArgyrios Kyrtzidis 
558b4c83a13SArgyrios Kyrtzidis   SmallString<64> Spelling;
559b4c83a13SArgyrios Kyrtzidis   Spelling.resize(Tok.Length);
560b4c83a13SArgyrios Kyrtzidis 
561ee8ed0b3SBen Langmuir   // FIXME: C++11 raw string literals need special handling (see getSpellingSlow
562ee8ed0b3SBen Langmuir   // in the Lexer). Currently we cannot see them due to our LangOpts.
563ee8ed0b3SBen Langmuir 
564b4c83a13SArgyrios Kyrtzidis   unsigned SpellingLength = 0;
565b4c83a13SArgyrios Kyrtzidis   const char *BufPtr = Input.begin() + Tok.Offset;
566b4c83a13SArgyrios Kyrtzidis   const char *AfterIdent = Input.begin() + Tok.getEnd();
567b4c83a13SArgyrios Kyrtzidis   while (BufPtr < AfterIdent) {
5688116b6dcSserge-sans-paille     auto [Char, Size] = Lexer::getCharAndSizeNoWarn(BufPtr, LangOpts);
5698116b6dcSserge-sans-paille     Spelling[SpellingLength++] = Char;
570b4c83a13SArgyrios Kyrtzidis     BufPtr += Size;
571b4c83a13SArgyrios Kyrtzidis   }
572b4c83a13SArgyrios Kyrtzidis 
573b4c83a13SArgyrios Kyrtzidis   return SplitIds.try_emplace(StringRef(Spelling.begin(), SpellingLength), 0)
574b4c83a13SArgyrios Kyrtzidis       .first->first();
575b4c83a13SArgyrios Kyrtzidis }
576b4c83a13SArgyrios Kyrtzidis 
577ee8ed0b3SBen Langmuir std::optional<StringRef>
578ee8ed0b3SBen Langmuir Scanner::tryLexIdentifierOrSkipLine(const char *&First, const char *const End) {
579ee8ed0b3SBen Langmuir   const dependency_directives_scan::Token &Tok = lexToken(First, End);
580ee8ed0b3SBen Langmuir   if (Tok.isNot(tok::raw_identifier)) {
581ee8ed0b3SBen Langmuir     if (!Tok.is(tok::eod))
582ee8ed0b3SBen Langmuir       skipLine(First, End);
583ee8ed0b3SBen Langmuir     return std::nullopt;
584ee8ed0b3SBen Langmuir   }
585ee8ed0b3SBen Langmuir 
586ee8ed0b3SBen Langmuir   return cleanStringIfNeeded(Tok);
587ee8ed0b3SBen Langmuir }
588ee8ed0b3SBen Langmuir 
589b4c83a13SArgyrios Kyrtzidis StringRef Scanner::lexIdentifier(const char *&First, const char *const End) {
5906ad0788cSKazu Hirata   std::optional<StringRef> Id = tryLexIdentifierOrSkipLine(First, End);
59197afce08SKazu Hirata   assert(Id && "expected identifier token");
59253e5cd4dSFangrui Song   return *Id;
593b4c83a13SArgyrios Kyrtzidis }
594b4c83a13SArgyrios Kyrtzidis 
595b4c83a13SArgyrios Kyrtzidis bool Scanner::isNextIdentifierOrSkipLine(StringRef Id, const char *&First,
596b4c83a13SArgyrios Kyrtzidis                                          const char *const End) {
5976ad0788cSKazu Hirata   if (std::optional<StringRef> FoundId =
5986ad0788cSKazu Hirata           tryLexIdentifierOrSkipLine(First, End)) {
599b4c83a13SArgyrios Kyrtzidis     if (*FoundId == Id)
600b4c83a13SArgyrios Kyrtzidis       return true;
601b4c83a13SArgyrios Kyrtzidis     skipLine(First, End);
602b4c83a13SArgyrios Kyrtzidis   }
603b4c83a13SArgyrios Kyrtzidis   return false;
604b4c83a13SArgyrios Kyrtzidis }
605b4c83a13SArgyrios Kyrtzidis 
606ee8ed0b3SBen Langmuir bool Scanner::isNextTokenOrSkipLine(tok::TokenKind K, const char *&First,
607ee8ed0b3SBen Langmuir                                     const char *const End) {
608ee8ed0b3SBen Langmuir   const dependency_directives_scan::Token &Tok = lexToken(First, End);
609ee8ed0b3SBen Langmuir   if (Tok.is(K))
610ee8ed0b3SBen Langmuir     return true;
611ee8ed0b3SBen Langmuir   skipLine(First, End);
612ee8ed0b3SBen Langmuir   return false;
613ee8ed0b3SBen Langmuir }
614ee8ed0b3SBen Langmuir 
615ee8ed0b3SBen Langmuir std::optional<StringRef>
616ee8ed0b3SBen Langmuir Scanner::tryLexStringLiteralOrSkipLine(const char *&First,
617ee8ed0b3SBen Langmuir                                        const char *const End) {
618ee8ed0b3SBen Langmuir   const dependency_directives_scan::Token &Tok = lexToken(First, End);
619ee8ed0b3SBen Langmuir   if (!tok::isStringLiteral(Tok.Kind)) {
620ee8ed0b3SBen Langmuir     if (!Tok.is(tok::eod))
621ee8ed0b3SBen Langmuir       skipLine(First, End);
622ee8ed0b3SBen Langmuir     return std::nullopt;
623ee8ed0b3SBen Langmuir   }
624ee8ed0b3SBen Langmuir 
625ee8ed0b3SBen Langmuir   return cleanStringIfNeeded(Tok);
626ee8ed0b3SBen Langmuir }
627ee8ed0b3SBen Langmuir 
628b4c83a13SArgyrios Kyrtzidis bool Scanner::lexAt(const char *&First, const char *const End) {
629b4c83a13SArgyrios Kyrtzidis   // Handle "@import".
630b4c83a13SArgyrios Kyrtzidis 
631b4c83a13SArgyrios Kyrtzidis   // Lex '@'.
632b4c83a13SArgyrios Kyrtzidis   const dependency_directives_scan::Token &AtTok = lexToken(First, End);
633b4c83a13SArgyrios Kyrtzidis   assert(AtTok.is(tok::at));
634b4c83a13SArgyrios Kyrtzidis   (void)AtTok;
635b4c83a13SArgyrios Kyrtzidis 
636b4c83a13SArgyrios Kyrtzidis   if (!isNextIdentifierOrSkipLine("import", First, End))
637b4c83a13SArgyrios Kyrtzidis     return false;
638b4c83a13SArgyrios Kyrtzidis   return lexModuleDirectiveBody(decl_at_import, First, End);
639b4c83a13SArgyrios Kyrtzidis }
640b4c83a13SArgyrios Kyrtzidis 
641b4c83a13SArgyrios Kyrtzidis bool Scanner::lexModule(const char *&First, const char *const End) {
642b4c83a13SArgyrios Kyrtzidis   StringRef Id = lexIdentifier(First, End);
643b4c83a13SArgyrios Kyrtzidis   bool Export = false;
644b4c83a13SArgyrios Kyrtzidis   if (Id == "export") {
645b4c83a13SArgyrios Kyrtzidis     Export = true;
6466ad0788cSKazu Hirata     std::optional<StringRef> NextId = tryLexIdentifierOrSkipLine(First, End);
647b4c83a13SArgyrios Kyrtzidis     if (!NextId)
648b4c83a13SArgyrios Kyrtzidis       return false;
649b4c83a13SArgyrios Kyrtzidis     Id = *NextId;
650b4c83a13SArgyrios Kyrtzidis   }
651b4c83a13SArgyrios Kyrtzidis 
652b4c83a13SArgyrios Kyrtzidis   if (Id != "module" && Id != "import") {
653b58a420fSArgyrios Kyrtzidis     skipLine(First, End);
654b58a420fSArgyrios Kyrtzidis     return false;
655b58a420fSArgyrios Kyrtzidis   }
656b58a420fSArgyrios Kyrtzidis 
657b58a420fSArgyrios Kyrtzidis   skipWhitespace(First, End);
658b58a420fSArgyrios Kyrtzidis 
659b58a420fSArgyrios Kyrtzidis   // Ignore this as a module directive if the next character can't be part of
660b58a420fSArgyrios Kyrtzidis   // an import.
661b58a420fSArgyrios Kyrtzidis 
662b58a420fSArgyrios Kyrtzidis   switch (*First) {
66342728475SMichael Spencer   case ':': {
66442728475SMichael Spencer     // `module :` is never the start of a valid module declaration.
66542728475SMichael Spencer     if (Id == "module") {
66642728475SMichael Spencer       skipLine(First, End);
66742728475SMichael Spencer       return false;
66842728475SMichael Spencer     }
66942728475SMichael Spencer     // `import:(type)name` is a valid ObjC method decl, so check one more token.
67042728475SMichael Spencer     (void)lexToken(First, End);
67142728475SMichael Spencer     if (!tryLexIdentifierOrSkipLine(First, End))
67242728475SMichael Spencer       return false;
67342728475SMichael Spencer     break;
67442728475SMichael Spencer   }
675b58a420fSArgyrios Kyrtzidis   case '<':
676b58a420fSArgyrios Kyrtzidis   case '"':
677b58a420fSArgyrios Kyrtzidis     break;
678b58a420fSArgyrios Kyrtzidis   default:
679b58a420fSArgyrios Kyrtzidis     if (!isAsciiIdentifierContinue(*First)) {
680b58a420fSArgyrios Kyrtzidis       skipLine(First, End);
681b58a420fSArgyrios Kyrtzidis       return false;
682b58a420fSArgyrios Kyrtzidis     }
683b58a420fSArgyrios Kyrtzidis   }
684b58a420fSArgyrios Kyrtzidis 
685b4c83a13SArgyrios Kyrtzidis   TheLexer.seek(getOffsetAt(First), /*IsAtStartOfLine*/ false);
686b58a420fSArgyrios Kyrtzidis 
687b4c83a13SArgyrios Kyrtzidis   DirectiveKind Kind;
688b4c83a13SArgyrios Kyrtzidis   if (Id == "module")
689b4c83a13SArgyrios Kyrtzidis     Kind = Export ? cxx_export_module_decl : cxx_module_decl;
690b58a420fSArgyrios Kyrtzidis   else
691b4c83a13SArgyrios Kyrtzidis     Kind = Export ? cxx_export_import_decl : cxx_import_decl;
692b58a420fSArgyrios Kyrtzidis 
693b4c83a13SArgyrios Kyrtzidis   return lexModuleDirectiveBody(Kind, First, End);
694b58a420fSArgyrios Kyrtzidis }
695b58a420fSArgyrios Kyrtzidis 
696ee8ed0b3SBen Langmuir bool Scanner::lex_Pragma(const char *&First, const char *const End) {
697ee8ed0b3SBen Langmuir   if (!isNextTokenOrSkipLine(tok::l_paren, First, End))
698ee8ed0b3SBen Langmuir     return false;
699ee8ed0b3SBen Langmuir 
700ee8ed0b3SBen Langmuir   std::optional<StringRef> Str = tryLexStringLiteralOrSkipLine(First, End);
701ee8ed0b3SBen Langmuir 
702ee8ed0b3SBen Langmuir   if (!Str || !isNextTokenOrSkipLine(tok::r_paren, First, End))
703ee8ed0b3SBen Langmuir     return false;
704ee8ed0b3SBen Langmuir 
705ee8ed0b3SBen Langmuir   SmallString<64> Buffer(*Str);
706ee8ed0b3SBen Langmuir   prepare_PragmaString(Buffer);
707ee8ed0b3SBen Langmuir 
708ee8ed0b3SBen Langmuir   // Use a new scanner instance since the tokens will be inside the allocated
709ee8ed0b3SBen Langmuir   // string. We should already have captured all the relevant tokens in the
710ee8ed0b3SBen Langmuir   // current scanner.
711ee8ed0b3SBen Langmuir   SmallVector<dependency_directives_scan::Token> DiscardTokens;
712ee8ed0b3SBen Langmuir   const char *Begin = Buffer.c_str();
713ee8ed0b3SBen Langmuir   Scanner PragmaScanner{StringRef(Begin, Buffer.size()), DiscardTokens, Diags,
7140559eaffSNishith Kumar M Shah                         InputSourceLoc};
715ee8ed0b3SBen Langmuir 
716ee8ed0b3SBen Langmuir   PragmaScanner.TheLexer.setParsingPreprocessorDirective(true);
717ee8ed0b3SBen Langmuir   if (PragmaScanner.lexPragma(Begin, Buffer.end()))
718ee8ed0b3SBen Langmuir     return true;
719ee8ed0b3SBen Langmuir 
720ee8ed0b3SBen Langmuir   DirectiveKind K = PragmaScanner.topDirective();
721ee8ed0b3SBen Langmuir   if (K == pp_none) {
722ee8ed0b3SBen Langmuir     skipLine(First, End);
723ee8ed0b3SBen Langmuir     return false;
724ee8ed0b3SBen Langmuir   }
725ee8ed0b3SBen Langmuir 
726ee8ed0b3SBen Langmuir   assert(Begin == Buffer.end());
727ee8ed0b3SBen Langmuir   pushDirective(K);
728ee8ed0b3SBen Langmuir   return false;
729ee8ed0b3SBen Langmuir }
730ee8ed0b3SBen Langmuir 
731b58a420fSArgyrios Kyrtzidis bool Scanner::lexPragma(const char *&First, const char *const End) {
7326ad0788cSKazu Hirata   std::optional<StringRef> FoundId = tryLexIdentifierOrSkipLine(First, End);
733b4c83a13SArgyrios Kyrtzidis   if (!FoundId)
734b58a420fSArgyrios Kyrtzidis     return false;
735b58a420fSArgyrios Kyrtzidis 
736ca4af13eSKazu Hirata   StringRef Id = *FoundId;
737b4c83a13SArgyrios Kyrtzidis   auto Kind = llvm::StringSwitch<DirectiveKind>(Id)
738b4c83a13SArgyrios Kyrtzidis                   .Case("once", pp_pragma_once)
739b4c83a13SArgyrios Kyrtzidis                   .Case("push_macro", pp_pragma_push_macro)
740b4c83a13SArgyrios Kyrtzidis                   .Case("pop_macro", pp_pragma_pop_macro)
741b4c83a13SArgyrios Kyrtzidis                   .Case("include_alias", pp_pragma_include_alias)
742b4c83a13SArgyrios Kyrtzidis                   .Default(pp_none);
743b4c83a13SArgyrios Kyrtzidis   if (Kind != pp_none) {
744b4c83a13SArgyrios Kyrtzidis     lexPPDirectiveBody(First, End);
745b4c83a13SArgyrios Kyrtzidis     pushDirective(Kind);
746b58a420fSArgyrios Kyrtzidis     return false;
747b58a420fSArgyrios Kyrtzidis   }
748b58a420fSArgyrios Kyrtzidis 
749b4c83a13SArgyrios Kyrtzidis   if (Id != "clang") {
750b58a420fSArgyrios Kyrtzidis     skipLine(First, End);
751b58a420fSArgyrios Kyrtzidis     return false;
752b58a420fSArgyrios Kyrtzidis   }
753b58a420fSArgyrios Kyrtzidis 
7547b492d1bSBen Langmuir   FoundId = tryLexIdentifierOrSkipLine(First, End);
7557b492d1bSBen Langmuir   if (!FoundId)
756b58a420fSArgyrios Kyrtzidis     return false;
7577b492d1bSBen Langmuir   Id = *FoundId;
7587b492d1bSBen Langmuir 
7597b492d1bSBen Langmuir   // #pragma clang system_header
7607b492d1bSBen Langmuir   if (Id == "system_header") {
7617b492d1bSBen Langmuir     lexPPDirectiveBody(First, End);
7627b492d1bSBen Langmuir     pushDirective(pp_pragma_system_header);
7637b492d1bSBen Langmuir     return false;
7647b492d1bSBen Langmuir   }
7657b492d1bSBen Langmuir 
7667b492d1bSBen Langmuir   if (Id != "module") {
7677b492d1bSBen Langmuir     skipLine(First, End);
7687b492d1bSBen Langmuir     return false;
7697b492d1bSBen Langmuir   }
770b58a420fSArgyrios Kyrtzidis 
771b58a420fSArgyrios Kyrtzidis   // #pragma clang module.
772b4c83a13SArgyrios Kyrtzidis   if (!isNextIdentifierOrSkipLine("import", First, End))
773b58a420fSArgyrios Kyrtzidis     return false;
774b58a420fSArgyrios Kyrtzidis 
775b58a420fSArgyrios Kyrtzidis   // #pragma clang module import.
776b4c83a13SArgyrios Kyrtzidis   lexPPDirectiveBody(First, End);
777b58a420fSArgyrios Kyrtzidis   pushDirective(pp_pragma_import);
778b58a420fSArgyrios Kyrtzidis   return false;
779b58a420fSArgyrios Kyrtzidis }
780b58a420fSArgyrios Kyrtzidis 
781b58a420fSArgyrios Kyrtzidis bool Scanner::lexEndif(const char *&First, const char *const End) {
782b58a420fSArgyrios Kyrtzidis   // Strip out "#else" if it's empty.
783b58a420fSArgyrios Kyrtzidis   if (topDirective() == pp_else)
784b58a420fSArgyrios Kyrtzidis     popDirective();
785b58a420fSArgyrios Kyrtzidis 
786b58a420fSArgyrios Kyrtzidis   // If "#ifdef" is empty, strip it and skip the "#endif".
787b58a420fSArgyrios Kyrtzidis   //
788b58a420fSArgyrios Kyrtzidis   // FIXME: Once/if Clang starts disallowing __has_include in macro expansions,
789b58a420fSArgyrios Kyrtzidis   // we can skip empty `#if` and `#elif` blocks as well after scanning for a
790b58a420fSArgyrios Kyrtzidis   // literal __has_include in the condition.  Even without that rule we could
791b58a420fSArgyrios Kyrtzidis   // drop the tokens if we scan for identifiers in the condition and find none.
792b58a420fSArgyrios Kyrtzidis   if (topDirective() == pp_ifdef || topDirective() == pp_ifndef) {
793b58a420fSArgyrios Kyrtzidis     popDirective();
794b58a420fSArgyrios Kyrtzidis     skipLine(First, End);
795b58a420fSArgyrios Kyrtzidis     return false;
796b58a420fSArgyrios Kyrtzidis   }
797b58a420fSArgyrios Kyrtzidis 
798b4c83a13SArgyrios Kyrtzidis   return lexDefault(pp_endif, First, End);
799b58a420fSArgyrios Kyrtzidis }
800b58a420fSArgyrios Kyrtzidis 
801b4c83a13SArgyrios Kyrtzidis bool Scanner::lexDefault(DirectiveKind Kind, const char *&First,
802b4c83a13SArgyrios Kyrtzidis                          const char *const End) {
803b4c83a13SArgyrios Kyrtzidis   lexPPDirectiveBody(First, End);
804b58a420fSArgyrios Kyrtzidis   pushDirective(Kind);
805b58a420fSArgyrios Kyrtzidis   return false;
806b58a420fSArgyrios Kyrtzidis }
807b58a420fSArgyrios Kyrtzidis 
808b58a420fSArgyrios Kyrtzidis static bool isStartOfRelevantLine(char First) {
809b58a420fSArgyrios Kyrtzidis   switch (First) {
810b58a420fSArgyrios Kyrtzidis   case '#':
811b58a420fSArgyrios Kyrtzidis   case '@':
812b58a420fSArgyrios Kyrtzidis   case 'i':
813b58a420fSArgyrios Kyrtzidis   case 'e':
814b58a420fSArgyrios Kyrtzidis   case 'm':
815ee8ed0b3SBen Langmuir   case '_':
816b58a420fSArgyrios Kyrtzidis     return true;
817b58a420fSArgyrios Kyrtzidis   }
818b58a420fSArgyrios Kyrtzidis   return false;
819b58a420fSArgyrios Kyrtzidis }
820b58a420fSArgyrios Kyrtzidis 
821b58a420fSArgyrios Kyrtzidis bool Scanner::lexPPLine(const char *&First, const char *const End) {
822b58a420fSArgyrios Kyrtzidis   assert(First != End);
823b58a420fSArgyrios Kyrtzidis 
824b58a420fSArgyrios Kyrtzidis   skipWhitespace(First, End);
825b58a420fSArgyrios Kyrtzidis   assert(First <= End);
826b58a420fSArgyrios Kyrtzidis   if (First == End)
827b58a420fSArgyrios Kyrtzidis     return false;
828b58a420fSArgyrios Kyrtzidis 
829b58a420fSArgyrios Kyrtzidis   if (!isStartOfRelevantLine(*First)) {
830b58a420fSArgyrios Kyrtzidis     skipLine(First, End);
831b58a420fSArgyrios Kyrtzidis     assert(First <= End);
832b58a420fSArgyrios Kyrtzidis     return false;
833b58a420fSArgyrios Kyrtzidis   }
834b58a420fSArgyrios Kyrtzidis 
835aa484c90SArgyrios Kyrtzidis   LastTokenPtr = First;
836aa484c90SArgyrios Kyrtzidis 
837b4c83a13SArgyrios Kyrtzidis   TheLexer.seek(getOffsetAt(First), /*IsAtStartOfLine*/ true);
838b4c83a13SArgyrios Kyrtzidis 
839b4c83a13SArgyrios Kyrtzidis   auto ScEx1 = make_scope_exit([&]() {
840b4c83a13SArgyrios Kyrtzidis     /// Clear Scanner's CurDirToks before returning, in case we didn't push a
841b4c83a13SArgyrios Kyrtzidis     /// new directive.
842b4c83a13SArgyrios Kyrtzidis     CurDirToks.clear();
843b4c83a13SArgyrios Kyrtzidis   });
844b4c83a13SArgyrios Kyrtzidis 
845b58a420fSArgyrios Kyrtzidis   // Handle "@import".
846b58a420fSArgyrios Kyrtzidis   if (*First == '@')
847b58a420fSArgyrios Kyrtzidis     return lexAt(First, End);
848b58a420fSArgyrios Kyrtzidis 
849b58a420fSArgyrios Kyrtzidis   if (*First == 'i' || *First == 'e' || *First == 'm')
850b58a420fSArgyrios Kyrtzidis     return lexModule(First, End);
851b58a420fSArgyrios Kyrtzidis 
852ee8ed0b3SBen Langmuir   if (*First == '_') {
853ee8ed0b3SBen Langmuir     if (isNextIdentifierOrSkipLine("_Pragma", First, End))
854ee8ed0b3SBen Langmuir       return lex_Pragma(First, End);
855ee8ed0b3SBen Langmuir     return false;
856ee8ed0b3SBen Langmuir   }
857ee8ed0b3SBen Langmuir 
858b58a420fSArgyrios Kyrtzidis   // Handle preprocessing directives.
859b58a420fSArgyrios Kyrtzidis 
860b4c83a13SArgyrios Kyrtzidis   TheLexer.setParsingPreprocessorDirective(true);
861b4c83a13SArgyrios Kyrtzidis   auto ScEx2 = make_scope_exit(
862b4c83a13SArgyrios Kyrtzidis       [&]() { TheLexer.setParsingPreprocessorDirective(false); });
863b58a420fSArgyrios Kyrtzidis 
864b4c83a13SArgyrios Kyrtzidis   // Lex '#'.
865b4c83a13SArgyrios Kyrtzidis   const dependency_directives_scan::Token &HashTok = lexToken(First, End);
866b340c5aeSArgyrios Kyrtzidis   if (HashTok.is(tok::hashhash)) {
867b340c5aeSArgyrios Kyrtzidis     // A \p tok::hashhash at this location is passed by the preprocessor to the
868b340c5aeSArgyrios Kyrtzidis     // parser to interpret, like any other token. So for dependency scanning
869b340c5aeSArgyrios Kyrtzidis     // skip it like a normal token not affecting the preprocessor.
870b340c5aeSArgyrios Kyrtzidis     skipLine(First, End);
871b340c5aeSArgyrios Kyrtzidis     assert(First <= End);
872b340c5aeSArgyrios Kyrtzidis     return false;
873b340c5aeSArgyrios Kyrtzidis   }
874b4c83a13SArgyrios Kyrtzidis   assert(HashTok.is(tok::hash));
875b4c83a13SArgyrios Kyrtzidis   (void)HashTok;
876b4c83a13SArgyrios Kyrtzidis 
8776ad0788cSKazu Hirata   std::optional<StringRef> FoundId = tryLexIdentifierOrSkipLine(First, End);
878b4c83a13SArgyrios Kyrtzidis   if (!FoundId)
879b58a420fSArgyrios Kyrtzidis     return false;
880b58a420fSArgyrios Kyrtzidis 
881ca4af13eSKazu Hirata   StringRef Id = *FoundId;
882b58a420fSArgyrios Kyrtzidis 
883b4c83a13SArgyrios Kyrtzidis   if (Id == "pragma")
884b58a420fSArgyrios Kyrtzidis     return lexPragma(First, End);
885b58a420fSArgyrios Kyrtzidis 
886b4c83a13SArgyrios Kyrtzidis   auto Kind = llvm::StringSwitch<DirectiveKind>(Id)
887b58a420fSArgyrios Kyrtzidis                   .Case("include", pp_include)
888b58a420fSArgyrios Kyrtzidis                   .Case("__include_macros", pp___include_macros)
889b58a420fSArgyrios Kyrtzidis                   .Case("define", pp_define)
890b58a420fSArgyrios Kyrtzidis                   .Case("undef", pp_undef)
891b58a420fSArgyrios Kyrtzidis                   .Case("import", pp_import)
892b58a420fSArgyrios Kyrtzidis                   .Case("include_next", pp_include_next)
893b58a420fSArgyrios Kyrtzidis                   .Case("if", pp_if)
894b58a420fSArgyrios Kyrtzidis                   .Case("ifdef", pp_ifdef)
895b58a420fSArgyrios Kyrtzidis                   .Case("ifndef", pp_ifndef)
896b58a420fSArgyrios Kyrtzidis                   .Case("elif", pp_elif)
897b58a420fSArgyrios Kyrtzidis                   .Case("elifdef", pp_elifdef)
898b58a420fSArgyrios Kyrtzidis                   .Case("elifndef", pp_elifndef)
899b58a420fSArgyrios Kyrtzidis                   .Case("else", pp_else)
900b58a420fSArgyrios Kyrtzidis                   .Case("endif", pp_endif)
901b58a420fSArgyrios Kyrtzidis                   .Default(pp_none);
902b58a420fSArgyrios Kyrtzidis   if (Kind == pp_none) {
903b4c83a13SArgyrios Kyrtzidis     skipDirective(Id, First, End);
904b58a420fSArgyrios Kyrtzidis     return false;
905b58a420fSArgyrios Kyrtzidis   }
906b58a420fSArgyrios Kyrtzidis 
907b58a420fSArgyrios Kyrtzidis   if (Kind == pp_endif)
908b58a420fSArgyrios Kyrtzidis     return lexEndif(First, End);
909b58a420fSArgyrios Kyrtzidis 
910b4c83a13SArgyrios Kyrtzidis   switch (Kind) {
911b4c83a13SArgyrios Kyrtzidis   case pp_include:
912b4c83a13SArgyrios Kyrtzidis   case pp___include_macros:
913b4c83a13SArgyrios Kyrtzidis   case pp_include_next:
914b4c83a13SArgyrios Kyrtzidis   case pp_import:
91534ab8558SCyndy Ishida     // Ignore missing filenames in include or import directives.
91634ab8558SCyndy Ishida     if (lexIncludeFilename(First, End).is(tok::eod)) {
917*d19e71dbSArgyrios Kyrtzidis       return false;
91834ab8558SCyndy Ishida     }
919b4c83a13SArgyrios Kyrtzidis     break;
920b4c83a13SArgyrios Kyrtzidis   default:
921b4c83a13SArgyrios Kyrtzidis     break;
922b4c83a13SArgyrios Kyrtzidis   }
923b58a420fSArgyrios Kyrtzidis 
924b58a420fSArgyrios Kyrtzidis   // Everything else.
925b4c83a13SArgyrios Kyrtzidis   return lexDefault(Kind, First, End);
926b58a420fSArgyrios Kyrtzidis }
927b58a420fSArgyrios Kyrtzidis 
928b58a420fSArgyrios Kyrtzidis static void skipUTF8ByteOrderMark(const char *&First, const char *const End) {
929b58a420fSArgyrios Kyrtzidis   if ((End - First) >= 3 && First[0] == '\xef' && First[1] == '\xbb' &&
930b58a420fSArgyrios Kyrtzidis       First[2] == '\xbf')
931b58a420fSArgyrios Kyrtzidis     First += 3;
932b58a420fSArgyrios Kyrtzidis }
933b58a420fSArgyrios Kyrtzidis 
934b58a420fSArgyrios Kyrtzidis bool Scanner::scanImpl(const char *First, const char *const End) {
935b58a420fSArgyrios Kyrtzidis   skipUTF8ByteOrderMark(First, End);
936b58a420fSArgyrios Kyrtzidis   while (First != End)
937b58a420fSArgyrios Kyrtzidis     if (lexPPLine(First, End))
938b58a420fSArgyrios Kyrtzidis       return true;
939b58a420fSArgyrios Kyrtzidis   return false;
940b58a420fSArgyrios Kyrtzidis }
941b58a420fSArgyrios Kyrtzidis 
942b4c83a13SArgyrios Kyrtzidis bool Scanner::scan(SmallVectorImpl<Directive> &Directives) {
943b58a420fSArgyrios Kyrtzidis   bool Error = scanImpl(Input.begin(), Input.end());
944b58a420fSArgyrios Kyrtzidis 
945b58a420fSArgyrios Kyrtzidis   if (!Error) {
946b4c83a13SArgyrios Kyrtzidis     // Add an EOF on success.
947aa484c90SArgyrios Kyrtzidis     if (LastTokenPtr &&
948aa484c90SArgyrios Kyrtzidis         (Tokens.empty() || LastTokenPtr > Input.begin() + Tokens.back().Offset))
949aa484c90SArgyrios Kyrtzidis       pushDirective(tokens_present_before_eof);
950b58a420fSArgyrios Kyrtzidis     pushDirective(pp_eof);
951b58a420fSArgyrios Kyrtzidis   }
952b58a420fSArgyrios Kyrtzidis 
953b4c83a13SArgyrios Kyrtzidis   ArrayRef<dependency_directives_scan::Token> RemainingTokens = Tokens;
954b4c83a13SArgyrios Kyrtzidis   for (const DirectiveWithTokens &DirWithToks : DirsWithToks) {
955b4c83a13SArgyrios Kyrtzidis     assert(RemainingTokens.size() >= DirWithToks.NumTokens);
956b4c83a13SArgyrios Kyrtzidis     Directives.emplace_back(DirWithToks.Kind,
957b4c83a13SArgyrios Kyrtzidis                             RemainingTokens.take_front(DirWithToks.NumTokens));
958b4c83a13SArgyrios Kyrtzidis     RemainingTokens = RemainingTokens.drop_front(DirWithToks.NumTokens);
959b4c83a13SArgyrios Kyrtzidis   }
960b4c83a13SArgyrios Kyrtzidis   assert(RemainingTokens.empty());
961b4c83a13SArgyrios Kyrtzidis 
962b58a420fSArgyrios Kyrtzidis   return Error;
963b58a420fSArgyrios Kyrtzidis }
964b58a420fSArgyrios Kyrtzidis 
965b58a420fSArgyrios Kyrtzidis bool clang::scanSourceForDependencyDirectives(
966b4c83a13SArgyrios Kyrtzidis     StringRef Input, SmallVectorImpl<dependency_directives_scan::Token> &Tokens,
9670559eaffSNishith Kumar M Shah     SmallVectorImpl<Directive> &Directives, DiagnosticsEngine *Diags,
9680559eaffSNishith Kumar M Shah     SourceLocation InputSourceLoc) {
9690559eaffSNishith Kumar M Shah   return Scanner(Input, Tokens, Diags, InputSourceLoc).scan(Directives);
970b4c83a13SArgyrios Kyrtzidis }
971b4c83a13SArgyrios Kyrtzidis 
972b4c83a13SArgyrios Kyrtzidis void clang::printDependencyDirectivesAsSource(
973b4c83a13SArgyrios Kyrtzidis     StringRef Source,
974b4c83a13SArgyrios Kyrtzidis     ArrayRef<dependency_directives_scan::Directive> Directives,
975b4c83a13SArgyrios Kyrtzidis     llvm::raw_ostream &OS) {
976b4c83a13SArgyrios Kyrtzidis   // Add a space separator where it is convenient for testing purposes.
977b4c83a13SArgyrios Kyrtzidis   auto needsSpaceSeparator =
978b4c83a13SArgyrios Kyrtzidis       [](tok::TokenKind Prev,
979b4c83a13SArgyrios Kyrtzidis          const dependency_directives_scan::Token &Tok) -> bool {
980b4c83a13SArgyrios Kyrtzidis     if (Prev == Tok.Kind)
981b4c83a13SArgyrios Kyrtzidis       return !Tok.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
982b4c83a13SArgyrios Kyrtzidis                           tok::r_square);
983b4c83a13SArgyrios Kyrtzidis     if (Prev == tok::raw_identifier &&
984b4c83a13SArgyrios Kyrtzidis         Tok.isOneOf(tok::hash, tok::numeric_constant, tok::string_literal,
985b4c83a13SArgyrios Kyrtzidis                     tok::char_constant, tok::header_name))
986b4c83a13SArgyrios Kyrtzidis       return true;
987b4c83a13SArgyrios Kyrtzidis     if (Prev == tok::r_paren &&
988b4c83a13SArgyrios Kyrtzidis         Tok.isOneOf(tok::raw_identifier, tok::hash, tok::string_literal,
989b4c83a13SArgyrios Kyrtzidis                     tok::char_constant, tok::unknown))
990b4c83a13SArgyrios Kyrtzidis       return true;
991b4c83a13SArgyrios Kyrtzidis     if (Prev == tok::comma &&
992b4c83a13SArgyrios Kyrtzidis         Tok.isOneOf(tok::l_paren, tok::string_literal, tok::less))
993b4c83a13SArgyrios Kyrtzidis       return true;
994b4c83a13SArgyrios Kyrtzidis     return false;
995b4c83a13SArgyrios Kyrtzidis   };
996b4c83a13SArgyrios Kyrtzidis 
997b4c83a13SArgyrios Kyrtzidis   for (const dependency_directives_scan::Directive &Directive : Directives) {
998aa484c90SArgyrios Kyrtzidis     if (Directive.Kind == tokens_present_before_eof)
999aa484c90SArgyrios Kyrtzidis       OS << "<TokBeforeEOF>";
10006ad0788cSKazu Hirata     std::optional<tok::TokenKind> PrevTokenKind;
1001b4c83a13SArgyrios Kyrtzidis     for (const dependency_directives_scan::Token &Tok : Directive.Tokens) {
1002b4c83a13SArgyrios Kyrtzidis       if (PrevTokenKind && needsSpaceSeparator(*PrevTokenKind, Tok))
1003b4c83a13SArgyrios Kyrtzidis         OS << ' ';
1004b4c83a13SArgyrios Kyrtzidis       PrevTokenKind = Tok.Kind;
1005b4c83a13SArgyrios Kyrtzidis       OS << Source.slice(Tok.Offset, Tok.getEnd());
1006b4c83a13SArgyrios Kyrtzidis     }
1007b4c83a13SArgyrios Kyrtzidis   }
1008b58a420fSArgyrios Kyrtzidis }
1009