Clang Project

clang_source_code/include/clang/Lex/PreprocessorLexer.h
1//===- PreprocessorLexer.h - C Language Family Lexer ------------*- 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/// Defines the PreprocessorLexer interface.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
15#define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
16
17#include "clang/Lex/MultipleIncludeOpt.h"
18#include "clang/Lex/Token.h"
19#include "clang/Basic/SourceLocation.h"
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/SmallVector.h"
22#include <cassert>
23
24namespace clang {
25
26class FileEntry;
27class Preprocessor;
28
29class PreprocessorLexer {
30  virtual void anchor();
31
32protected:
33  friend class Preprocessor;
34
35  // Preprocessor object controlling lexing.
36  Preprocessor *PP = nullptr;
37
38  /// The SourceManager FileID corresponding to the file being lexed.
39  const FileID FID;
40
41  /// Number of SLocEntries before lexing the file.
42  unsigned InitialNumSLocEntries = 0;
43
44  //===--------------------------------------------------------------------===//
45  // Context-specific lexing flags set by the preprocessor.
46  //===--------------------------------------------------------------------===//
47
48  /// True when parsing \#XXX; turns '\\n' into a tok::eod token.
49  bool ParsingPreprocessorDirective = false;
50
51  /// True after \#include; turns \<xx> or "xxx" into a tok::header_name token.
52  bool ParsingFilename = false;
53
54  /// True if in raw mode.
55  ///
56  /// Raw mode disables interpretation of tokens and is a far faster mode to
57  /// lex in than non-raw-mode.  This flag:
58  ///  1. If EOF of the current lexer is found, the include stack isn't popped.
59  ///  2. Identifier information is not looked up for identifier tokens.  As an
60  ///     effect of this, implicit macro expansion is naturally disabled.
61  ///  3. "#" tokens at the start of a line are treated as normal tokens, not
62  ///     implicitly transformed by the lexer.
63  ///  4. All diagnostic messages are disabled.
64  ///  5. No callbacks are made into the preprocessor.
65  ///
66  /// Note that in raw mode that the PP pointer may be null.
67  bool LexingRawMode = false;
68
69  /// A state machine that detects the \#ifndef-wrapping a file
70  /// idiom for the multiple-include optimization.
71  MultipleIncludeOpt MIOpt;
72
73  /// Information about the set of \#if/\#ifdef/\#ifndef blocks
74  /// we are currently in.
75  SmallVector<PPConditionalInfo4ConditionalStack;
76
77  PreprocessorLexer() : FID() {}
78  PreprocessorLexer(Preprocessor *ppFileID fid);
79  virtual ~PreprocessorLexer() = default;
80
81  virtual void IndirectLex(TokenResult) = 0;
82
83  /// Return the source location for the next observable location.
84  virtual SourceLocation getSourceLocation() = 0;
85
86  //===--------------------------------------------------------------------===//
87  // #if directive handling.
88
89  /// pushConditionalLevel - When we enter a \#if directive, this keeps track of
90  /// what we are currently in for diagnostic emission (e.g. \#if with missing
91  /// \#endif).
92  void pushConditionalLevel(SourceLocation DirectiveStartbool WasSkipping,
93                            bool FoundNonSkipbool FoundElse) {
94    PPConditionalInfo CI;
95    CI.IfLoc = DirectiveStart;
96    CI.WasSkipping = WasSkipping;
97    CI.FoundNonSkip = FoundNonSkip;
98    CI.FoundElse = FoundElse;
99    ConditionalStack.push_back(CI);
100  }
101  void pushConditionalLevel(const PPConditionalInfo &CI) {
102    ConditionalStack.push_back(CI);
103  }
104
105  /// popConditionalLevel - Remove an entry off the top of the conditional
106  /// stack, returning information about it.  If the conditional stack is empty,
107  /// this returns true and does not fill in the arguments.
108  bool popConditionalLevel(PPConditionalInfo &CI) {
109    if (ConditionalStack.empty())
110      return true;
111    CI = ConditionalStack.pop_back_val();
112    return false;
113  }
114
115  /// Return the top of the conditional stack.
116  /// \pre This requires that there be a conditional active.
117  PPConditionalInfo &peekConditionalLevel() {
118     (0) . __assert_fail ("!ConditionalStack.empty() && \"No conditionals active!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Lex/PreprocessorLexer.h", 118, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!ConditionalStack.empty() && "No conditionals active!");
119    return ConditionalStack.back();
120  }
121
122  unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
123
124public:
125  PreprocessorLexer(const PreprocessorLexer &) = delete;
126  PreprocessorLexer &operator=(const PreprocessorLexer &) = delete;
127
128  //===--------------------------------------------------------------------===//
129  // Misc. lexing methods.
130
131  /// Lex a token, producing a header-name token if possible.
132  void LexIncludeFilename(Token &FilenameTok);
133
134  /// Inform the lexer whether or not we are currently lexing a
135  /// preprocessor directive.
136  void setParsingPreprocessorDirective(bool f) {
137    ParsingPreprocessorDirective = f;
138  }
139
140  /// Return true if this lexer is in raw mode or not.
141  bool isLexingRawMode() const { return LexingRawMode; }
142
143  /// Return the preprocessor object for this lexer.
144  Preprocessor *getPP() const { return PP; }
145
146  FileID getFileID() const {
147     (0) . __assert_fail ("PP && \"PreprocessorLexer..getFileID() should only be used with a Preprocessor\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Lex/PreprocessorLexer.h", 148, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(PP &&
148 (0) . __assert_fail ("PP && \"PreprocessorLexer..getFileID() should only be used with a Preprocessor\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Lex/PreprocessorLexer.h", 148, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">      "PreprocessorLexer::getFileID() should only be used with a Preprocessor");
149    return FID;
150  }
151
152  /// Number of SLocEntries before lexing the file.
153  unsigned getInitialNumSLocEntries() const {
154    return InitialNumSLocEntries;
155  }
156
157  /// getFileEntry - Return the FileEntry corresponding to this FileID.  Like
158  /// getFileID(), this only works for lexers with attached preprocessors.
159  const FileEntry *getFileEntry() const;
160
161  /// Iterator that traverses the current stack of preprocessor
162  /// conditional directives (\#if/\#ifdef/\#ifndef).
163  using conditional_iterator =
164      SmallVectorImpl<PPConditionalInfo>::const_iterator;
165
166  conditional_iterator conditional_begin() const {
167    return ConditionalStack.begin();
168  }
169
170  conditional_iterator conditional_end() const {
171    return ConditionalStack.end();
172  }
173
174  void setConditionalLevels(ArrayRef<PPConditionalInfoCL) {
175    ConditionalStack.clear();
176    ConditionalStack.append(CL.begin(), CL.end());
177  }
178};
179
180// namespace clang
181
182#endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H
183
clang::PreprocessorLexer::anchor
clang::PreprocessorLexer::PP
clang::PreprocessorLexer::FID
clang::PreprocessorLexer::InitialNumSLocEntries
clang::PreprocessorLexer::ParsingPreprocessorDirective
clang::PreprocessorLexer::ParsingFilename
clang::PreprocessorLexer::LexingRawMode
clang::PreprocessorLexer::MIOpt
clang::PreprocessorLexer::ConditionalStack
clang::PreprocessorLexer::IndirectLex
clang::PreprocessorLexer::getSourceLocation
clang::PreprocessorLexer::pushConditionalLevel
clang::PreprocessorLexer::pushConditionalLevel
clang::PreprocessorLexer::popConditionalLevel
clang::PreprocessorLexer::peekConditionalLevel
clang::PreprocessorLexer::getConditionalStackDepth
clang::PreprocessorLexer::LexIncludeFilename
clang::PreprocessorLexer::setParsingPreprocessorDirective
clang::PreprocessorLexer::isLexingRawMode
clang::PreprocessorLexer::getPP
clang::PreprocessorLexer::getFileID
clang::PreprocessorLexer::getInitialNumSLocEntries
clang::PreprocessorLexer::getFileEntry
clang::PreprocessorLexer::conditional_begin
clang::PreprocessorLexer::conditional_end
clang::PreprocessorLexer::setConditionalLevels