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