clang 24.0.0git
UnwrappedLineParser.h
Go to the documentation of this file.
1//===--- UnwrappedLineParser.h - Format C++ code ----------------*- 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 file contains the declaration of the UnwrappedLineParser,
11/// which turns a stream of tokens into UnwrappedLines.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
16#define LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
17
18#include "Macros.h"
19#include "llvm/ADT/SmallPtrSet.h"
20#include <stack>
21
22namespace clang {
23namespace format {
24
26
27/// An unwrapped line is a sequence of \c Token, that we would like to
28/// put on a single line if there was no column limit.
29///
30/// This is used as a main interface between the \c UnwrappedLineParser and the
31/// \c UnwrappedLineFormatter. The key property is that changing the formatting
32/// within an unwrapped line does not affect any other unwrapped lines.
34 UnwrappedLine() = default;
35
36 /// The \c Tokens comprising this \c UnwrappedLine.
37 std::list<UnwrappedLineNode> Tokens;
38
39 /// The indent level of the \c UnwrappedLine.
40 unsigned Level = 0;
41
42 /// The \c PPState::BranchLevel (adjusted for header guards) if this line is a
43 /// \c InMacroBody line, and 0 otherwise.
44 unsigned PPLevel = 0;
45
46 /// Whether this \c UnwrappedLine is part of a preprocessor directive.
47 bool InPPDirective = false;
48 /// Whether this \c UnwrappedLine is part of a pramga directive.
49 bool InPragmaDirective = false;
50 /// Whether it is part of a macro body.
51 bool InMacroBody = false;
52 /// Whether this \c UnwrappedLine is part of the first pass of a multi-pass
53 /// macro expansion run.
54 bool InMacroExpansion = false;
55
56 /// Nesting level of unbraced body of a control statement.
57 unsigned UnbracedBodyLevel = 0;
58
59 bool MustBeDeclaration = false;
60
61 /// Whether the parser has seen \c decltype(auto) in this line.
62 bool SeenDecltypeAuto = false;
63
64 /// \c True if this line should be indented by ContinuationIndent in
65 /// addition to the normal indention level.
66 bool IsContinuation = false;
67
68 /// Whether it is a C++20 module/import declaration.
70
71 /// If this \c UnwrappedLine closes a block in a sequence of lines,
72 /// \c MatchingOpeningBlockLineIndex stores the index of the corresponding
73 /// opening line. Otherwise, \c MatchingOpeningBlockLineIndex must be
74 /// \c kInvalidIndex.
76
77 /// If this \c UnwrappedLine opens a block, stores the index of the
78 /// line with the corresponding closing brace.
80
81 static const size_t kInvalidIndex = -1;
82
83 unsigned FirstStartColumn = 0;
84};
85
86/// Interface for users of the UnwrappedLineParser to receive the parsed lines.
87/// Parsing a single snippet of code can lead to multiple runs, where each
88/// run is a coherent view of the file.
89///
90/// For example, different runs are generated:
91/// - for different combinations of #if blocks
92/// - when macros are involved, for the expanded code and the as-written code
93///
94/// Some tokens will only be visible in a subset of the runs.
95/// For each run, \c UnwrappedLineParser will call \c consumeUnwrappedLine
96/// for each parsed unwrapped line, and then \c finishRun to indicate
97/// that the set of unwrapped lines before is one coherent view of the
98/// code snippet to be formatted.
100public:
102 virtual void consumeUnwrappedLine(const UnwrappedLine &Line) = 0;
103 virtual void finishRun() = 0;
104};
105
107
109public:
110 UnwrappedLineParser(SourceManager &SourceMgr, const FormatStyle &Style,
111 const AdditionalKeywords &Keywords,
112 unsigned FirstStartColumn, ArrayRef<FormatToken *> Tokens,
113 UnwrappedLineConsumer &Callback,
114 llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
115 IdentifierTable &IdentTable);
116
117 void parse();
118
119private:
120 enum class IfStmtKind {
121 NotIf, // Not an if statement.
122 IfOnly, // An if statement without the else clause.
123 IfElse, // An if statement followed by else but not else if.
124 IfElseIf // An if statement followed by else if.
125 };
126
127 void reset();
128 void parseFile();
129 bool precededByCommentOrPPDirective() const;
130 bool parseLevel(const FormatToken *OpeningBrace = nullptr,
131 IfStmtKind *IfKind = nullptr,
132 FormatToken **IfLeftBrace = nullptr,
133 bool *SeenExplicitAccessModifier = nullptr);
134 bool mightFitOnOneLine(UnwrappedLine &Line,
135 const FormatToken *OpeningBrace = nullptr) const;
136 FormatToken *parseBlock(bool MustBeDeclaration = false,
137 unsigned AddLevels = 1u, bool MunchSemi = true,
138 bool KeepBraces = true, IfStmtKind *IfKind = nullptr,
139 bool UnindentWhitesmithsBraces = false,
140 bool IndentAfterExplicitAccessModifier = false);
141 void parseChildBlock();
142 void parsePPDirective();
143 void parsePPDefine();
144 void parsePPIf(bool IfDef);
145 void parsePPElse();
146 void parsePPEndIf();
147 void parsePPPragma();
148 void parsePPUnknown();
149 void readTokenWithJavaScriptASI();
150 void parseStructuralElement(const FormatToken *OpeningBrace = nullptr,
151 IfStmtKind *IfKind = nullptr,
152 FormatToken **IfLeftBrace = nullptr,
153 bool *HasDoWhile = nullptr,
154 bool *HasLabel = nullptr);
155 bool tryToParseBracedList();
156 bool parseBracedList(bool IsAngleBracket = false, bool IsEnum = false);
157 bool parseParens(TokenType StarAndAmpTokenType = TT_Unknown,
158 bool InMacroCall = false);
159 // SkipLambda means the square does not begin a lambda expression. The opening
160 // square bracket is assumed to be consumed when it is true.
161 void parseSquare(bool SkipLambda = false);
162 void keepAncestorBraces();
163 void parseUnbracedBody(bool CheckEOF = false);
164 void handleAttributes();
165 bool handleCppAttributes();
166 bool isBlockBegin(const FormatToken &Tok) const;
167 FormatToken *parseIfThenElse(IfStmtKind *IfKind, bool KeepBraces = false,
168 bool IsVerilogAssert = false);
169 void parseTryCatch();
170 void parseLoopBody(bool KeepBraces, bool WrapRightBrace);
171 void parseForOrWhileLoop(bool HasParens = true);
172 void parseDoWhile();
173 void parseLabel(bool IsGotoLabel = false);
174 void parseCaseLabel();
175 void parseSwitch(bool IsExpr);
176 void parseNamespace();
177 bool parseModuleDecl();
178 bool parseImportDecl();
179 void parseNew();
180 void parseAccessSpecifier();
181 bool parseEnum();
182 bool parseStructLike();
183 bool parseRequires(bool SeenEqual);
184 void parseRequiresClause();
185 void parseRequiresExpression();
186 void parseConstraintExpression();
187 void parseCppExportBlock();
188 void parseNamespaceOrExportBlock(unsigned AddLevels);
189 void parseJavaEnumBody();
190 // Parses a record (aka class) as a top level element. If ParseAsExpr is true,
191 // parses the record as a child block, i.e. if the class declaration is an
192 // expression.
193 void parseRecord(bool ParseAsExpr = false, bool IsJavaRecord = false);
194 void parseObjCLightweightGenerics();
195 void parseObjCMethod();
196 void parseObjCProtocolList();
197 void parseObjCUntilAtEnd();
198 void parseObjCInterfaceOrImplementation();
199 bool parseObjCProtocol();
200 void parseJavaScriptEs6ImportExport();
201 void parseStatementMacro();
202 void parseCSharpAttribute();
203 // Parse a C# generic type constraint: `where T : IComparable<T>`.
204 // See:
205 // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
206 void parseCSharpGenericTypeConstraint();
207 bool tryToParseLambda();
208 bool tryToParseChildBlock();
209 bool tryToParseLambdaIntroducer();
210 bool tryToParsePropertyAccessor();
211 void tryToParseJSFunction();
212 bool tryToParseSimpleAttribute();
213 void parseVerilogHierarchyIdentifier();
214 void parseVerilogSensitivityList();
215 // Returns the number of levels of indentation in addition to the normal 1
216 // level for a block, used for indenting case labels.
217 unsigned parseVerilogHierarchyHeader();
218 void parseVerilogTable();
219 void parseVerilogCaseLabel();
220 // For import, export, and extern.
221 void parseVerilogExtern();
222 // Skip things that can precede the keywords like module.
223 void skipVerilogQualifiers();
224 struct PPState;
225 std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
226 parseMacroCall(const PPState &SavedPPState);
227
228 // Used by addUnwrappedLine to denote whether to keep or remove a level
229 // when resetting the line state.
230 enum class LineLevel { Remove, Keep };
231
232 void addUnwrappedLine(LineLevel AdjustLevel = LineLevel::Remove);
233 bool eof() const;
234 // LevelDifference is the difference of levels after and before the current
235 // token. For example:
236 // - if the token is '{' and opens a block, LevelDifference is 1.
237 // - if the token is '}' and closes a block, LevelDifference is -1.
238 void nextToken(int LevelDifference = 0);
239 void readToken(int LevelDifference = 0);
240
241 // Decides which comment tokens should be added to the current line and which
242 // should be added as comments before the next token.
243 //
244 // Comments specifies the sequence of comment tokens to analyze. They get
245 // either pushed to the current line or added to the comments before the next
246 // token.
247 //
248 // NextTok specifies the next token. A null pointer NextTok is supported, and
249 // signifies either the absence of a next token, or that the next token
250 // shouldn't be taken into account for the analysis.
251 void distributeComments(const ArrayRef<FormatToken *> &Comments,
252 const FormatToken *NextTok);
253
254 // Adds the comment preceding the next token to unwrapped lines.
255 void flushComments(bool NewlineBeforeNext);
256 void pushToken(FormatToken *Tok);
257 void calculateBraceTypes(bool ExpectClassBody = false);
258 void setPreviousRBraceType(TokenType Type);
259
260 // Marks a conditional compilation edge (for example, an '#if', '#ifdef',
261 // '#else' or merge conflict marker). If 'Unreachable' is true, assumes
262 // this branch either cannot be taken (for example '#if false'), or should
263 // not be taken in this round.
264 void conditionalCompilationCondition(bool Unreachable);
265 void conditionalCompilationStart(bool Unreachable);
266 void conditionalCompilationAlternative();
267 void conditionalCompilationEnd();
268
269 bool isOnNewLine(const FormatToken &FormatTok);
270
271 // Returns whether there is a macro expansion in the line, i.e. a token that
272 // was expanded from a macro call.
273 bool containsExpansion(const UnwrappedLine &Line) const;
274
275 // Compute hash of the current preprocessor branch.
276 // This is used to identify the different branches, and thus track if block
277 // open and close in the same branch.
278 size_t computePPHash() const;
279
280 bool parsingPPDirective() const { return CurrentLines != &Lines; }
281
282 // FIXME: We are constantly running into bugs where Line.Level is incorrectly
283 // subtracted from beyond 0. Introduce a method to subtract from Line.Level
284 // and use that everywhere in the Parser.
285 std::unique_ptr<UnwrappedLine> Line;
286
287 // Lines that are created by macro expansion.
288 // When formatting code containing macro calls, we first format the expanded
289 // lines to set the token types correctly. Afterwards, we format the
290 // reconstructed macro calls, re-using the token types determined in the first
291 // step.
292 // ExpandedLines will be reset every time we create a new LineAndExpansion
293 // instance once a line containing macro calls has been parsed.
294 SmallVector<UnwrappedLine, 8> CurrentExpandedLines;
295
296 // Maps from the first token of a top-level UnwrappedLine that contains
297 // a macro call to the replacement UnwrappedLines expanded from the macro
298 // call.
299 llvm::DenseMap<FormatToken *, SmallVector<UnwrappedLine, 8>> ExpandedLines;
300
301 // Map from the macro identifier to a line containing the full unexpanded
302 // macro call.
303 llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>> Unexpanded;
304
305 // For recursive macro expansions, trigger reconstruction only on the
306 // outermost expansion.
307 bool InExpansion = false;
308
309 // Set while we reconstruct a macro call.
310 // For reconstruction, we feed the expanded lines into the reconstructor
311 // until it is finished.
312 std::optional<MacroCallReconstructor> Reconstruct;
313
314 // Comments are sorted into unwrapped lines by whether they are in the same
315 // line as the previous token, or not. If not, they belong to the next token.
316 // Since the next token might already be in a new unwrapped line, we need to
317 // store the comments belonging to that token.
318 SmallVector<FormatToken *, 1> CommentsBeforeNextToken;
319
320 FormatToken *FormatTok = nullptr;
321
322 // The parsed lines. Only added to through \c CurrentLines.
324
325 // Preprocessor directives are parsed out-of-order from other unwrapped lines.
326 // Thus, we need to keep a list of preprocessor directives to be reported
327 // after an unwrapped line that has been started was finished.
328 SmallVector<UnwrappedLine, 4> PreprocessorDirectives;
329
330 // New unwrapped lines are added via CurrentLines.
331 // Usually points to \c &Lines. While parsing a preprocessor directive when
332 // there is an unfinished previous unwrapped line, will point to
333 // \c &PreprocessorDirectives.
334 SmallVectorImpl<UnwrappedLine> *CurrentLines;
335
336 // We store for each line whether it must be a declaration depending on
337 // whether we are in a compound statement or not.
338 llvm::BitVector DeclarationScopeStack;
339
340 const FormatStyle &Style;
341 bool IsCpp;
342 LangOptions LangOpts;
343 const AdditionalKeywords &Keywords;
344
345 llvm::Regex CommentPragmasRegex;
346
347 FormatTokenSource *Tokens;
348 UnwrappedLineConsumer &Callback;
349
350 ArrayRef<FormatToken *> AllTokens;
351
352 // Keeps a stack of the states of nested control statements (true if the
353 // statement contains more than some predefined number of nested statements).
354 SmallVector<bool, 8> NestedTooDeep;
355
356 // Keeps a stack of the states of nested lambdas (true if the return type of
357 // the lambda is `decltype(auto)`).
358 SmallVector<bool, 4> NestedLambdas;
359
360 // Whether the parser is parsing the body of a function whose return type is
361 // `decltype(auto)`.
362 bool IsDecltypeAutoFunction = false;
363
364 // Represents preprocessor branch type, so we can find matching
365 // #if/#else/#endif directives.
366 enum PPBranchKind {
367 PP_Conditional, // Any #if, #ifdef, #ifndef, #elif, block outside #if 0
368 PP_Unreachable // #if 0 or a conditional preprocessor block inside #if 0
369 };
370
371 struct PPBranch {
372 PPBranch(PPBranchKind Kind, size_t Line) : Kind(Kind), Line(Line) {}
373 PPBranchKind Kind;
374 size_t Line;
375 };
376
377 // Include guard search state. Used to fixup preprocessor indent levels
378 // so that include guards do not participate in indentation.
379 enum IncludeGuardState {
380 IG_Inited, // Search started, looking for #ifndef.
381 IG_IfNdefed, // #ifndef found, IncludeGuardToken points to condition.
382 IG_Defined, // Matching #define found, checking other requirements.
383 IG_Found, // All requirements met, need to fix indents.
384 IG_Rejected, // Search failed or never started.
385 };
386
387 IncludeGuardState
388 getIncludeGuardState(FormatStyle::PPDirectiveIndentStyle Style) const {
389 return Style == FormatStyle::PPDIS_None || Style == FormatStyle::PPDIS_Leave
390 ? IG_Rejected
391 : IG_Inited;
392 }
393
394 // The preprocessor bookkeeping that is rolled back when the token stream is
395 // rewound over preprocessor directives, which happens if the speculatively
396 // parsed arguments of a macro call are discarded. See readToken().
397 struct PPState {
398 explicit PPState(IncludeGuardState IncludeGuard)
399 : IncludeGuard(IncludeGuard) {}
400
401 // Keeps a stack of currently active preprocessor branching directives.
403
404 // The \c UnwrappedLineParser re-parses the code for each combination
405 // of preprocessor branches that can be taken.
406 // To that end, we take the same branch (#if, #else, or one of the #elif
407 // branches) for each nesting level of preprocessor branches.
408 // \c BranchLevel stores the current nesting level of preprocessor
409 // branches during one pass over the code.
410 int BranchLevel = -1;
411
412 // Contains the current branch (#if, #else or one of the #elif branches)
413 // for each nesting level.
414 SmallVector<int, 8> LevelBranchIndex;
415
416 // Contains the maximum number of branches at each nesting level.
417 SmallVector<int, 8> LevelBranchCount;
418
419 // Contains the number of branches per nesting level we are currently
420 // in while parsing a preprocessor branch sequence.
421 // This is used to update LevelBranchCount at the end of a branch
422 // sequence.
423 std::stack<int> ChainBranchIndex;
424
425 // Current state of include guard search.
426 IncludeGuardState IncludeGuard;
427
428 // Points to the #ifndef condition for a potential include guard. Null
429 // unless IncludeGuardState == IG_IfNdefed.
430 FormatToken *IncludeGuardToken = nullptr;
431
432 // Has just finished parsing a preprocessor line.
433 bool AtEndOfPPLine = false;
434 } PP;
435
436 // The hash tokens of the parsed preprocessor directives. The lines of a
437 // directive are kept when the token stream is rewound over it, so it is then
438 // parsed again only for its effect on the preprocessor bookkeeping. See
439 // readToken().
441
442 // Contains the first start column where the source begins. This is zero for
443 // normal source code and may be nonzero when formatting a code fragment that
444 // does not start at the beginning of the file.
445 unsigned FirstStartColumn;
446
447 MacroExpander Macros;
448
449 friend class ScopedLineState;
451};
452
462
463std::ostream &operator<<(std::ostream &Stream, const UnwrappedLine &Line);
464
465} // end namespace format
466} // end namespace clang
467
468#endif
Token Tok
The Token.
SmallVector< AnnotatedLine *, 1 > Children
If this token starts a block, this contains all the unwrapped lines in it.
This file contains the main building blocks of macro support in clang-format.
Implements an efficient mapping from strings to IdentifierInfo nodes.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
This class handles loading and caching of source files into memory.
The base class of the type hierarchy.
Definition TypeBase.h:1879
Takes a set of macro definitions as strings and allows expanding calls to those macros.
Definition Macros.h:80
Interface for users of the UnwrappedLineParser to receive the parsed lines.
virtual void consumeUnwrappedLine(const UnwrappedLine &Line)=0
UnwrappedLineParser(SourceManager &SourceMgr, const FormatStyle &Style, const AdditionalKeywords &Keywords, unsigned FirstStartColumn, ArrayRef< FormatToken * > Tokens, UnwrappedLineConsumer &Callback, llvm::SpecificBumpPtrAllocator< FormatToken > &Allocator, IdentifierTable &IdentTable)
std::ostream & operator<<(std::ostream &Stream, const UnwrappedLine &Line)
TokenType
Determines the semantic type of a syntactic token, e.g.
Top level wrappers for InstallAPI frontend operations.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
Encapsulates keywords that are context sensitive or for languages not properly supported by Clang's l...
The FormatStyle is used to configure the formatting to follow specific guidelines.
Definition Format.h:51
PPDirectiveIndentStyle
Options for indenting preprocessor directives.
Definition Format.h:3396
@ PPDIS_Leave
Leaves indentation of directives as-is.
Definition Format.h:3435
@ PPDIS_None
Does not indent any directives.
Definition Format.h:3405
A wrapper around a Token storing information about the whitespace characters preceding it.
SmallVector< UnwrappedLine, 0 > Children
UnwrappedLineNode(FormatToken *Tok, llvm::ArrayRef< UnwrappedLine > Children={})
An unwrapped line is a sequence of Token, that we would like to put on a single line if there was no ...
unsigned PPLevel
The PPState::BranchLevel (adjusted for header guards) if this line is a InMacroBody line,...
bool InMacroBody
Whether it is part of a macro body.
std::list< UnwrappedLineNode > Tokens
The Tokens comprising this UnwrappedLine.
bool IsContinuation
True if this line should be indented by ContinuationIndent in addition to the normal indention level.
unsigned Level
The indent level of the UnwrappedLine.
bool InMacroExpansion
Whether this UnwrappedLine is part of the first pass of a multi-pass macro expansion run.
unsigned UnbracedBodyLevel
Nesting level of unbraced body of a control statement.
bool InPragmaDirective
Whether this UnwrappedLine is part of a pramga directive.
bool IsModuleOrImportDecl
Whether it is a C++20 module/import declaration.
bool InPPDirective
Whether this UnwrappedLine is part of a preprocessor directive.
bool SeenDecltypeAuto
Whether the parser has seen decltype(auto) in this line.
size_t MatchingClosingBlockLineIndex
If this UnwrappedLine opens a block, stores the index of the line with the corresponding closing brac...
size_t MatchingOpeningBlockLineIndex
If this UnwrappedLine closes a block in a sequence of lines, MatchingOpeningBlockLineIndex stores the...