aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Format/FormatToken.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Format/FormatToken.h')
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatToken.h954
1 files changed, 873 insertions, 81 deletions
diff --git a/contrib/llvm-project/clang/lib/Format/FormatToken.h b/contrib/llvm-project/clang/lib/Format/FormatToken.h
index 0506cd554bcb..9bfeb2052164 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatToken.h
+++ b/contrib/llvm-project/clang/lib/Format/FormatToken.h
@@ -19,7 +19,6 @@
#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
-#include <memory>
#include <unordered_set>
namespace clang {
@@ -29,29 +28,63 @@ namespace format {
TYPE(ArrayInitializerLSquare) \
TYPE(ArraySubscriptLSquare) \
TYPE(AttributeColon) \
+ TYPE(AttributeLParen) \
TYPE(AttributeMacro) \
- TYPE(AttributeParen) \
+ TYPE(AttributeRParen) \
TYPE(AttributeSquare) \
TYPE(BinaryOperator) \
TYPE(BitFieldColon) \
TYPE(BlockComment) \
+ /* l_brace of a block that is not the body of a (e.g. loop) statement. */ \
+ TYPE(BlockLBrace) \
+ TYPE(BracedListLBrace) \
+ TYPE(CaseLabelArrow) \
+ /* The colon at the end of a case label. */ \
+ TYPE(CaseLabelColon) \
TYPE(CastRParen) \
+ TYPE(ClassLBrace) \
+ TYPE(ClassRBrace) \
+ /* ternary ?: expression */ \
TYPE(ConditionalExpr) \
+ /* the condition in an if statement */ \
+ TYPE(ConditionLParen) \
TYPE(ConflictAlternative) \
TYPE(ConflictEnd) \
TYPE(ConflictStart) \
- TYPE(ConstraintJunctions) \
+ /* l_brace of if/for/while */ \
+ TYPE(ControlStatementLBrace) \
+ TYPE(ControlStatementRBrace) \
+ TYPE(CppCastLParen) \
+ TYPE(CSharpGenericTypeConstraint) \
+ TYPE(CSharpGenericTypeConstraintColon) \
+ TYPE(CSharpGenericTypeConstraintComma) \
+ TYPE(CSharpNamedArgumentColon) \
+ TYPE(CSharpNullable) \
+ TYPE(CSharpNullConditionalLSquare) \
+ TYPE(CSharpStringLiteral) \
TYPE(CtorInitializerColon) \
TYPE(CtorInitializerComma) \
+ TYPE(CtorDtorDeclName) \
TYPE(DesignatedInitializerLSquare) \
TYPE(DesignatedInitializerPeriod) \
TYPE(DictLiteral) \
+ TYPE(DoWhile) \
+ TYPE(ElseLBrace) \
+ TYPE(ElseRBrace) \
+ TYPE(EnumLBrace) \
+ TYPE(EnumRBrace) \
TYPE(FatArrow) \
TYPE(ForEachMacro) \
TYPE(FunctionAnnotationRParen) \
TYPE(FunctionDeclarationName) \
+ TYPE(FunctionDeclarationLParen) \
TYPE(FunctionLBrace) \
+ TYPE(FunctionLikeOrFreestandingMacro) \
TYPE(FunctionTypeLParen) \
+ /* The colons as part of a C11 _Generic selection */ \
+ TYPE(GenericSelectionColon) \
+ /* The colon at the end of a goto label. */ \
+ TYPE(GotoLabelColon) \
TYPE(IfMacro) \
TYPE(ImplicitStringLiteral) \
TYPE(InheritanceColon) \
@@ -60,6 +93,7 @@ namespace format {
TYPE(InlineASMColon) \
TYPE(InlineASMSymbolicNameLSquare) \
TYPE(JavaAnnotation) \
+ TYPE(JsAndAndEqual) \
TYPE(JsComputedPropertyName) \
TYPE(JsExponentiation) \
TYPE(JsExponentiationEqual) \
@@ -68,7 +102,6 @@ namespace format {
TYPE(JsTypeColon) \
TYPE(JsTypeOperator) \
TYPE(JsTypeOptionalQuestion) \
- TYPE(JsAndAndEqual) \
TYPE(LambdaArrow) \
TYPE(LambdaLBrace) \
TYPE(LambdaLSquare) \
@@ -76,7 +109,10 @@ namespace format {
TYPE(LineComment) \
TYPE(MacroBlockBegin) \
TYPE(MacroBlockEnd) \
+ TYPE(ModulePartitionColon) \
+ TYPE(NamespaceLBrace) \
TYPE(NamespaceMacro) \
+ TYPE(NamespaceRBrace) \
TYPE(NonNullAssertion) \
TYPE(NullCoalescingEqual) \
TYPE(NullCoalescingOperator) \
@@ -92,32 +128,84 @@ namespace format {
TYPE(OverloadedOperator) \
TYPE(OverloadedOperatorLParen) \
TYPE(PointerOrReference) \
+ TYPE(ProtoExtensionLSquare) \
TYPE(PureVirtualSpecifier) \
TYPE(RangeBasedForLoopColon) \
+ TYPE(RecordLBrace) \
+ TYPE(RecordRBrace) \
TYPE(RegexLiteral) \
+ TYPE(RequiresClause) \
+ TYPE(RequiresClauseInARequiresExpression) \
+ TYPE(RequiresExpression) \
+ TYPE(RequiresExpressionLBrace) \
+ TYPE(RequiresExpressionLParen) \
TYPE(SelectorName) \
TYPE(StartOfName) \
TYPE(StatementAttributeLikeMacro) \
TYPE(StatementMacro) \
+ /* A string that is part of a string concatenation. For C#, JavaScript, and \
+ * Java, it is used for marking whether a string needs parentheses around it \
+ * if it is to be split into parts joined by `+`. For Verilog, whether \
+ * braces need to be added to split it. Not used for other languages. */ \
+ TYPE(StringInConcatenation) \
+ TYPE(StructLBrace) \
+ TYPE(StructRBrace) \
TYPE(StructuredBindingLSquare) \
+ TYPE(SwitchExpressionLabel) \
+ TYPE(SwitchExpressionLBrace) \
+ TYPE(TableGenBangOperator) \
+ TYPE(TableGenCondOperator) \
+ TYPE(TableGenCondOperatorColon) \
+ TYPE(TableGenCondOperatorComma) \
+ TYPE(TableGenDAGArgCloser) \
+ TYPE(TableGenDAGArgListColon) \
+ TYPE(TableGenDAGArgListColonToAlign) \
+ TYPE(TableGenDAGArgListComma) \
+ TYPE(TableGenDAGArgListCommaToBreak) \
+ TYPE(TableGenDAGArgOpener) \
+ TYPE(TableGenDAGArgOpenerToBreak) \
+ TYPE(TableGenDAGArgOperatorID) \
+ TYPE(TableGenDAGArgOperatorToBreak) \
+ TYPE(TableGenListCloser) \
+ TYPE(TableGenListOpener) \
+ TYPE(TableGenMultiLineString) \
+ TYPE(TableGenTrailingPasteOperator) \
+ TYPE(TableGenValueSuffix) \
TYPE(TemplateCloser) \
TYPE(TemplateOpener) \
TYPE(TemplateString) \
- TYPE(ProtoExtensionLSquare) \
TYPE(TrailingAnnotation) \
TYPE(TrailingReturnArrow) \
TYPE(TrailingUnaryOperator) \
TYPE(TypeDeclarationParen) \
+ TYPE(TypeName) \
TYPE(TypenameMacro) \
TYPE(UnaryOperator) \
+ TYPE(UnionLBrace) \
+ TYPE(UnionRBrace) \
TYPE(UntouchableMacroFunc) \
- TYPE(CSharpStringLiteral) \
- TYPE(CSharpNamedArgumentColon) \
- TYPE(CSharpNullable) \
- TYPE(CSharpNullConditionalLSquare) \
- TYPE(CSharpGenericTypeConstraint) \
- TYPE(CSharpGenericTypeConstraintColon) \
- TYPE(CSharpGenericTypeConstraintComma) \
+ /* Like in 'assign x = 0, y = 1;' . */ \
+ TYPE(VerilogAssignComma) \
+ /* like in begin : block */ \
+ TYPE(VerilogBlockLabelColon) \
+ /* The square bracket for the dimension part of the type name. \
+ * In 'logic [1:0] x[1:0]', only the first '['. This way we can have space \
+ * before the first bracket but not the second. */ \
+ TYPE(VerilogDimensionedTypeName) \
+ /* list of port connections or parameters in a module instantiation */ \
+ TYPE(VerilogInstancePortComma) \
+ TYPE(VerilogInstancePortLParen) \
+ /* A parenthesized list within which line breaks are inserted by the \
+ * formatter, for example the list of ports in a module header. */ \
+ TYPE(VerilogMultiLineListLParen) \
+ /* for the base in a number literal, not including the quote */ \
+ TYPE(VerilogNumberBase) \
+ /* like `(strong1, pull0)` */ \
+ TYPE(VerilogStrength) \
+ /* Things inside the table in user-defined primitives. */ \
+ TYPE(VerilogTableItem) \
+ /* those that separate ports of different types */ \
+ TYPE(VerilogTypeComma) \
TYPE(Unknown)
/// Determines the semantic type of a syntactic token, e.g. whether "<" is a
@@ -210,12 +298,15 @@ class AnnotatedLine;
struct FormatToken {
FormatToken()
: HasUnescapedNewline(false), IsMultiline(false), IsFirst(false),
- MustBreakBefore(false), IsUnterminatedLiteral(false),
- CanBreakBefore(false), ClosesTemplateDeclaration(false),
- StartsBinaryExpression(false), EndsBinaryExpression(false),
- PartOfMultiVariableDeclStmt(false), ContinuesLineCommentSection(false),
- Finalized(false), BlockKind(BK_Unknown), Decision(FD_Unformatted),
- PackingKind(PPK_Inconclusive), Type(TT_Unknown) {}
+ MustBreakBefore(false), MustBreakBeforeFinalized(false),
+ IsUnterminatedLiteral(false), CanBreakBefore(false),
+ ClosesTemplateDeclaration(false), StartsBinaryExpression(false),
+ EndsBinaryExpression(false), PartOfMultiVariableDeclStmt(false),
+ ContinuesLineCommentSection(false), Finalized(false),
+ ClosesRequiresClause(false), EndsCppAttributeGroup(false),
+ BlockKind(BK_Unknown), Decision(FD_Unformatted),
+ PackingKind(PPK_Inconclusive), TypeIsFinalized(false),
+ Type(TT_Unknown) {}
/// The \c Token.
Token Tok;
@@ -251,6 +342,10 @@ struct FormatToken {
/// before the token.
unsigned MustBreakBefore : 1;
+ /// Whether MustBreakBefore is finalized during parsing and must not
+ /// be reset between runs.
+ unsigned MustBreakBeforeFinalized : 1;
+
/// Set to \c true if this token is an unterminated literal.
unsigned IsUnterminatedLiteral : 1;
@@ -281,6 +376,12 @@ struct FormatToken {
/// changes.
unsigned Finalized : 1;
+ /// \c true if this is the last token within requires clause.
+ unsigned ClosesRequiresClause : 1;
+
+ /// \c true if this token ends a group of C++ attributes.
+ unsigned EndsCppAttributeGroup : 1;
+
private:
/// Contains the kind of block if this token is a brace.
unsigned BlockKind : 2;
@@ -321,13 +422,43 @@ public:
}
private:
+ unsigned TypeIsFinalized : 1;
TokenType Type;
public:
/// Returns the token's type, e.g. whether "<" is a template opener or
/// binary operator.
TokenType getType() const { return Type; }
- void setType(TokenType T) { Type = T; }
+ void setType(TokenType T) {
+ // If this token is a macro argument while formatting an unexpanded macro
+ // call, we do not change its type any more - the type was deduced from
+ // formatting the expanded macro stream already.
+ if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)
+ return;
+ assert((!TypeIsFinalized || T == Type) &&
+ "Please use overwriteFixedType to change a fixed type.");
+ Type = T;
+ }
+ /// Sets the type and also the finalized flag. This prevents the type to be
+ /// reset in TokenAnnotator::resetTokenMetadata(). If the type needs to be set
+ /// to another one please use overwriteFixedType, or even better remove the
+ /// need to reassign the type.
+ void setFinalizedType(TokenType T) {
+ if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)
+ return;
+ Type = T;
+ TypeIsFinalized = true;
+ }
+ void overwriteFixedType(TokenType T) {
+ if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg)
+ return;
+ TypeIsFinalized = false;
+ setType(T);
+ }
+ bool isTypeFinalized() const { return TypeIsFinalized; }
+
+ /// Used to set an operator precedence explicitly.
+ prec::Level ForcedPrecedence = prec::Unknown;
/// The number of newlines immediately before the \c Token.
///
@@ -335,6 +466,12 @@ public:
/// and thereby e.g. leave an empty line between two function definitions.
unsigned NewlinesBefore = 0;
+ /// The number of newlines immediately before the \c Token after formatting.
+ ///
+ /// This is used to avoid overlapping whitespace replacements when \c Newlines
+ /// is recomputed for a finalized preprocessor branching directive.
+ int Newlines = -1;
+
/// The offset just past the last '\n' in this token's leading
/// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'.
unsigned LastNewlineOffset = 0;
@@ -441,13 +578,34 @@ public:
/// This starts an array initializer.
bool IsArrayInitializer = false;
+ /// Is optional and can be removed.
+ bool Optional = false;
+
+ /// Might be function declaration open/closing paren.
+ bool MightBeFunctionDeclParen = false;
+
+ /// Number of optional braces to be inserted after this token:
+ /// -1: a single left brace
+ /// 0: no braces
+ /// >0: number of right braces
+ int8_t BraceCount = 0;
+
/// If this token starts a block, this contains all the unwrapped lines
/// in it.
SmallVector<AnnotatedLine *, 1> Children;
// Contains all attributes related to how this token takes part
// in a configured macro expansion.
- llvm::Optional<MacroExpansion> MacroCtx;
+ std::optional<MacroExpansion> MacroCtx;
+
+ /// When macro expansion introduces nodes with children, those are marked as
+ /// \c MacroParent.
+ /// FIXME: The formatting code currently hard-codes the assumption that
+ /// child nodes are introduced by blocks following an opening brace.
+ /// This is deeply baked into the code and disentangling this will require
+ /// signficant refactorings. \c MacroParent allows us to special-case the
+ /// cases in which we treat parents as block-openers for now.
+ bool MacroParent = false;
bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }
bool is(TokenType TT) const { return getType() == TT; }
@@ -503,24 +661,37 @@ public:
bool isStringLiteral() const { return tok::isStringLiteral(Tok.getKind()); }
+ bool isAttribute() const {
+ return isOneOf(tok::kw___attribute, tok::kw___declspec, TT_AttributeMacro);
+ }
+
bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
return Tok.isObjCAtKeyword(Kind);
}
+ bool isAccessSpecifierKeyword() const {
+ return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private);
+ }
+
bool isAccessSpecifier(bool ColonRequired = true) const {
- return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private) &&
- (!ColonRequired || (Next && Next->is(tok::colon)));
+ if (!isAccessSpecifierKeyword())
+ return false;
+ if (!ColonRequired)
+ return true;
+ const auto *NextNonComment = getNextNonComment();
+ return NextNonComment && NextNonComment->is(tok::colon);
}
bool canBePointerOrReferenceQualifier() const {
return isOneOf(tok::kw_const, tok::kw_restrict, tok::kw_volatile,
- tok::kw___attribute, tok::kw__Nonnull, tok::kw__Nullable,
+ tok::kw__Nonnull, tok::kw__Nullable,
tok::kw__Null_unspecified, tok::kw___ptr32, tok::kw___ptr64,
- TT_AttributeMacro);
+ tok::kw___funcref) ||
+ isAttribute();
}
- /// Determine whether the token is a simple-type-specifier.
- bool isSimpleTypeSpecifier() const;
+ [[nodiscard]] bool isTypeName(const LangOptions &LangOpts) const;
+ [[nodiscard]] bool isTypeOrIdentifier(const LangOptions &LangOpts) const;
bool isObjCAccessSpecifier() const {
return is(tok::at) && Next &&
@@ -533,7 +704,7 @@ public:
/// Returns whether \p Tok is ([{ or an opening < of a template or in
/// protos.
bool opensScope() const {
- if (is(TT_TemplateString) && TokenText.endswith("${"))
+ if (is(TT_TemplateString) && TokenText.ends_with("${"))
return true;
if (is(TT_DictLiteral) && is(tok::less))
return true;
@@ -543,7 +714,7 @@ public:
/// Returns whether \p Tok is )]} or a closing > of a template or in
/// protos.
bool closesScope() const {
- if (is(TT_TemplateString) && TokenText.startswith("}"))
+ if (is(TT_TemplateString) && TokenText.starts_with("}"))
return true;
if (is(TT_DictLiteral) && is(tok::greater))
return true;
@@ -558,6 +729,33 @@ public:
TT_LambdaArrow, TT_LeadingJavaAnnotation);
}
+ bool isPointerOrReference() const {
+ return isOneOf(tok::star, tok::amp, tok::ampamp);
+ }
+
+ bool isCppAlternativeOperatorKeyword() const {
+ assert(!TokenText.empty());
+ if (!isalpha(TokenText[0]))
+ return false;
+
+ switch (Tok.getKind()) {
+ case tok::ampamp:
+ case tok::ampequal:
+ case tok::amp:
+ case tok::pipe:
+ case tok::tilde:
+ case tok::exclaim:
+ case tok::exclaimequal:
+ case tok::pipepipe:
+ case tok::pipeequal:
+ case tok::caret:
+ case tok::caretequal:
+ return true;
+ default:
+ return false;
+ }
+ }
+
bool isUnaryOperator() const {
switch (Tok.getKind()) {
case tok::plus:
@@ -587,35 +785,27 @@ public:
/// Returns \c true if this is a keyword that can be used
/// like a function call (e.g. sizeof, typeid, ...).
bool isFunctionLikeKeyword() const {
- switch (Tok.getKind()) {
- case tok::kw_throw:
- case tok::kw_typeid:
- case tok::kw_return:
- case tok::kw_sizeof:
- case tok::kw_alignof:
- case tok::kw_alignas:
- case tok::kw_decltype:
- case tok::kw_noexcept:
- case tok::kw_static_assert:
- case tok::kw__Atomic:
- case tok::kw___attribute:
- case tok::kw___underlying_type:
- case tok::kw_requires:
+ if (isAttribute())
return true;
- default:
- return false;
- }
+
+ return isOneOf(tok::kw_throw, tok::kw_typeid, tok::kw_return,
+ tok::kw_sizeof, tok::kw_alignof, tok::kw_alignas,
+ tok::kw_decltype, tok::kw_noexcept, tok::kw_static_assert,
+ tok::kw__Atomic,
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
+#include "clang/Basic/TransformTypeTraits.def"
+ tok::kw_requires);
}
/// Returns \c true if this is a string literal that's like a label,
/// e.g. ends with "=" or ":".
bool isLabelString() const {
- if (!is(tok::string_literal))
+ if (isNot(tok::string_literal))
return false;
StringRef Content = TokenText;
- if (Content.startswith("\"") || Content.startswith("'"))
+ if (Content.starts_with("\"") || Content.starts_with("'"))
Content = Content.drop_front(1);
- if (Content.endswith("\"") || Content.endswith("'"))
+ if (Content.ends_with("\"") || Content.ends_with("'"))
Content = Content.drop_back(1);
Content = Content.trim();
return Content.size() > 1 &&
@@ -631,13 +821,21 @@ public:
return WhitespaceRange.getEnd();
}
+ /// Returns \c true if the range of whitespace immediately preceding the \c
+ /// Token is not empty.
+ bool hasWhitespaceBefore() const {
+ return WhitespaceRange.getBegin() != WhitespaceRange.getEnd();
+ }
+
prec::Level getPrecedence() const {
+ if (ForcedPrecedence != prec::Unknown)
+ return ForcedPrecedence;
return getBinOpPrecedence(Tok.getKind(), /*GreaterThanIsOperator=*/true,
/*CPlusPlus11=*/true);
}
/// Returns the previous token ignoring comments.
- FormatToken *getPreviousNonComment() const {
+ [[nodiscard]] FormatToken *getPreviousNonComment() const {
FormatToken *Tok = Previous;
while (Tok && Tok->is(tok::comment))
Tok = Tok->Previous;
@@ -645,33 +843,24 @@ public:
}
/// Returns the next token ignoring comments.
- const FormatToken *getNextNonComment() const {
- const FormatToken *Tok = Next;
+ [[nodiscard]] FormatToken *getNextNonComment() const {
+ FormatToken *Tok = Next;
while (Tok && Tok->is(tok::comment))
Tok = Tok->Next;
return Tok;
}
+ /// Returns \c true if this token ends a block indented initializer list.
+ [[nodiscard]] bool isBlockIndentedInitRBrace(const FormatStyle &Style) const;
+
/// Returns \c true if this tokens starts a block-type list, i.e. a
/// list that should be indented with a block indent.
- bool opensBlockOrBlockTypeList(const FormatStyle &Style) const {
- // C# Does not indent object initialisers as continuations.
- if (is(tok::l_brace) && getBlockKind() == BK_BracedInit && Style.isCSharp())
- return true;
- if (is(TT_TemplateString) && opensScope())
- return true;
- return is(TT_ArrayInitializerLSquare) || is(TT_ProtoExtensionLSquare) ||
- (is(tok::l_brace) &&
- (getBlockKind() == BK_Block || is(TT_DictLiteral) ||
- (!Style.Cpp11BracedListStyle && NestingLevel == 0))) ||
- (is(tok::less) && (Style.Language == FormatStyle::LK_Proto ||
- Style.Language == FormatStyle::LK_TextProto));
- }
+ [[nodiscard]] bool opensBlockOrBlockTypeList(const FormatStyle &Style) const;
/// Returns whether the token is the left square bracket of a C++
/// structured binding declaration.
- bool isCppStructuredBinding(const FormatStyle &Style) const {
- if (!Style.isCpp() || isNot(tok::l_square))
+ bool isCppStructuredBinding(bool IsCpp) const {
+ if (!IsCpp || isNot(tok::l_square))
return false;
const FormatToken *T = this;
do {
@@ -849,6 +1038,7 @@ struct AdditionalKeywords {
kw_CF_OPTIONS = &IdentTable.get("CF_OPTIONS");
kw_NS_CLOSED_ENUM = &IdentTable.get("NS_CLOSED_ENUM");
kw_NS_ENUM = &IdentTable.get("NS_ENUM");
+ kw_NS_ERROR_ENUM = &IdentTable.get("NS_ERROR_ENUM");
kw_NS_OPTIONS = &IdentTable.get("NS_OPTIONS");
kw_as = &IdentTable.get("as");
@@ -886,6 +1076,7 @@ struct AdditionalKeywords {
kw___has_include_next = &IdentTable.get("__has_include_next");
kw_mark = &IdentTable.get("mark");
+ kw_region = &IdentTable.get("region");
kw_extend = &IdentTable.get("extend");
kw_option = &IdentTable.get("option");
@@ -899,6 +1090,10 @@ struct AdditionalKeywords {
kw_slots = &IdentTable.get("slots");
kw_qslots = &IdentTable.get("Q_SLOTS");
+ // For internal clang-format use.
+ kw_internal_ident_after_define =
+ &IdentTable.get("__CLANG_FORMAT_INTERNAL_IDENT_AFTER_DEFINE__");
+
// C# keywords
kw_dollar = &IdentTable.get("dollar");
kw_base = &IdentTable.get("base");
@@ -909,6 +1104,7 @@ struct AdditionalKeywords {
kw_event = &IdentTable.get("event");
kw_fixed = &IdentTable.get("fixed");
kw_foreach = &IdentTable.get("foreach");
+ kw_init = &IdentTable.get("init");
kw_implicit = &IdentTable.get("implicit");
kw_internal = &IdentTable.get("internal");
kw_lock = &IdentTable.get("lock");
@@ -929,29 +1125,271 @@ struct AdditionalKeywords {
kw_when = &IdentTable.get("when");
kw_where = &IdentTable.get("where");
+ // Verilog keywords
+ kw_always = &IdentTable.get("always");
+ kw_always_comb = &IdentTable.get("always_comb");
+ kw_always_ff = &IdentTable.get("always_ff");
+ kw_always_latch = &IdentTable.get("always_latch");
+ kw_assign = &IdentTable.get("assign");
+ kw_assume = &IdentTable.get("assume");
+ kw_automatic = &IdentTable.get("automatic");
+ kw_before = &IdentTable.get("before");
+ kw_begin = &IdentTable.get("begin");
+ kw_begin_keywords = &IdentTable.get("begin_keywords");
+ kw_bins = &IdentTable.get("bins");
+ kw_binsof = &IdentTable.get("binsof");
+ kw_casex = &IdentTable.get("casex");
+ kw_casez = &IdentTable.get("casez");
+ kw_celldefine = &IdentTable.get("celldefine");
+ kw_checker = &IdentTable.get("checker");
+ kw_clocking = &IdentTable.get("clocking");
+ kw_constraint = &IdentTable.get("constraint");
+ kw_cover = &IdentTable.get("cover");
+ kw_covergroup = &IdentTable.get("covergroup");
+ kw_coverpoint = &IdentTable.get("coverpoint");
+ kw_default_decay_time = &IdentTable.get("default_decay_time");
+ kw_default_nettype = &IdentTable.get("default_nettype");
+ kw_default_trireg_strength = &IdentTable.get("default_trireg_strength");
+ kw_delay_mode_distributed = &IdentTable.get("delay_mode_distributed");
+ kw_delay_mode_path = &IdentTable.get("delay_mode_path");
+ kw_delay_mode_unit = &IdentTable.get("delay_mode_unit");
+ kw_delay_mode_zero = &IdentTable.get("delay_mode_zero");
+ kw_disable = &IdentTable.get("disable");
+ kw_dist = &IdentTable.get("dist");
+ kw_edge = &IdentTable.get("edge");
+ kw_elsif = &IdentTable.get("elsif");
+ kw_end = &IdentTable.get("end");
+ kw_end_keywords = &IdentTable.get("end_keywords");
+ kw_endcase = &IdentTable.get("endcase");
+ kw_endcelldefine = &IdentTable.get("endcelldefine");
+ kw_endchecker = &IdentTable.get("endchecker");
+ kw_endclass = &IdentTable.get("endclass");
+ kw_endclocking = &IdentTable.get("endclocking");
+ kw_endfunction = &IdentTable.get("endfunction");
+ kw_endgenerate = &IdentTable.get("endgenerate");
+ kw_endgroup = &IdentTable.get("endgroup");
+ kw_endinterface = &IdentTable.get("endinterface");
+ kw_endmodule = &IdentTable.get("endmodule");
+ kw_endpackage = &IdentTable.get("endpackage");
+ kw_endprimitive = &IdentTable.get("endprimitive");
+ kw_endprogram = &IdentTable.get("endprogram");
+ kw_endproperty = &IdentTable.get("endproperty");
+ kw_endsequence = &IdentTable.get("endsequence");
+ kw_endspecify = &IdentTable.get("endspecify");
+ kw_endtable = &IdentTable.get("endtable");
+ kw_endtask = &IdentTable.get("endtask");
+ kw_forever = &IdentTable.get("forever");
+ kw_fork = &IdentTable.get("fork");
+ kw_generate = &IdentTable.get("generate");
+ kw_highz0 = &IdentTable.get("highz0");
+ kw_highz1 = &IdentTable.get("highz1");
+ kw_iff = &IdentTable.get("iff");
+ kw_ifnone = &IdentTable.get("ifnone");
+ kw_ignore_bins = &IdentTable.get("ignore_bins");
+ kw_illegal_bins = &IdentTable.get("illegal_bins");
+ kw_initial = &IdentTable.get("initial");
+ kw_inout = &IdentTable.get("inout");
+ kw_input = &IdentTable.get("input");
+ kw_inside = &IdentTable.get("inside");
+ kw_interconnect = &IdentTable.get("interconnect");
+ kw_intersect = &IdentTable.get("intersect");
+ kw_join = &IdentTable.get("join");
+ kw_join_any = &IdentTable.get("join_any");
+ kw_join_none = &IdentTable.get("join_none");
+ kw_large = &IdentTable.get("large");
+ kw_local = &IdentTable.get("local");
+ kw_localparam = &IdentTable.get("localparam");
+ kw_macromodule = &IdentTable.get("macromodule");
+ kw_matches = &IdentTable.get("matches");
+ kw_medium = &IdentTable.get("medium");
+ kw_negedge = &IdentTable.get("negedge");
+ kw_nounconnected_drive = &IdentTable.get("nounconnected_drive");
+ kw_output = &IdentTable.get("output");
+ kw_packed = &IdentTable.get("packed");
+ kw_parameter = &IdentTable.get("parameter");
+ kw_posedge = &IdentTable.get("posedge");
+ kw_primitive = &IdentTable.get("primitive");
+ kw_priority = &IdentTable.get("priority");
+ kw_program = &IdentTable.get("program");
+ kw_property = &IdentTable.get("property");
+ kw_pull0 = &IdentTable.get("pull0");
+ kw_pull1 = &IdentTable.get("pull1");
+ kw_pure = &IdentTable.get("pure");
+ kw_rand = &IdentTable.get("rand");
+ kw_randc = &IdentTable.get("randc");
+ kw_randcase = &IdentTable.get("randcase");
+ kw_randsequence = &IdentTable.get("randsequence");
+ kw_repeat = &IdentTable.get("repeat");
+ kw_resetall = &IdentTable.get("resetall");
+ kw_sample = &IdentTable.get("sample");
+ kw_scalared = &IdentTable.get("scalared");
+ kw_sequence = &IdentTable.get("sequence");
+ kw_small = &IdentTable.get("small");
+ kw_soft = &IdentTable.get("soft");
+ kw_solve = &IdentTable.get("solve");
+ kw_specify = &IdentTable.get("specify");
+ kw_specparam = &IdentTable.get("specparam");
+ kw_strong0 = &IdentTable.get("strong0");
+ kw_strong1 = &IdentTable.get("strong1");
+ kw_supply0 = &IdentTable.get("supply0");
+ kw_supply1 = &IdentTable.get("supply1");
+ kw_table = &IdentTable.get("table");
+ kw_tagged = &IdentTable.get("tagged");
+ kw_task = &IdentTable.get("task");
+ kw_timescale = &IdentTable.get("timescale");
+ kw_tri = &IdentTable.get("tri");
+ kw_tri0 = &IdentTable.get("tri0");
+ kw_tri1 = &IdentTable.get("tri1");
+ kw_triand = &IdentTable.get("triand");
+ kw_trior = &IdentTable.get("trior");
+ kw_trireg = &IdentTable.get("trireg");
+ kw_unconnected_drive = &IdentTable.get("unconnected_drive");
+ kw_undefineall = &IdentTable.get("undefineall");
+ kw_unique = &IdentTable.get("unique");
+ kw_unique0 = &IdentTable.get("unique0");
+ kw_uwire = &IdentTable.get("uwire");
+ kw_vectored = &IdentTable.get("vectored");
+ kw_wand = &IdentTable.get("wand");
+ kw_weak0 = &IdentTable.get("weak0");
+ kw_weak1 = &IdentTable.get("weak1");
+ kw_wildcard = &IdentTable.get("wildcard");
+ kw_wire = &IdentTable.get("wire");
+ kw_with = &IdentTable.get("with");
+ kw_wor = &IdentTable.get("wor");
+
+ // Symbols that are treated as keywords.
+ kw_verilogHash = &IdentTable.get("#");
+ kw_verilogHashHash = &IdentTable.get("##");
+ kw_apostrophe = &IdentTable.get("\'");
+
+ // TableGen keywords
+ kw_bit = &IdentTable.get("bit");
+ kw_bits = &IdentTable.get("bits");
+ kw_code = &IdentTable.get("code");
+ kw_dag = &IdentTable.get("dag");
+ kw_def = &IdentTable.get("def");
+ kw_defm = &IdentTable.get("defm");
+ kw_defset = &IdentTable.get("defset");
+ kw_defvar = &IdentTable.get("defvar");
+ kw_dump = &IdentTable.get("dump");
+ kw_include = &IdentTable.get("include");
+ kw_list = &IdentTable.get("list");
+ kw_multiclass = &IdentTable.get("multiclass");
+ kw_then = &IdentTable.get("then");
+
// Keep this at the end of the constructor to make sure everything here
// is
// already initialized.
JsExtraKeywords = std::unordered_set<IdentifierInfo *>(
{kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,
- kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly,
- kw_set, kw_type, kw_typeof, kw_var, kw_yield,
+ kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_override,
+ kw_readonly, kw_set, kw_type, kw_typeof, kw_var, kw_yield,
// Keywords from the Java section.
kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});
CSharpExtraKeywords = std::unordered_set<IdentifierInfo *>(
{kw_base, kw_byte, kw_checked, kw_decimal, kw_delegate, kw_event,
- kw_fixed, kw_foreach, kw_implicit, kw_in, kw_interface, kw_internal,
- kw_is, kw_lock, kw_null, kw_object, kw_out, kw_override, kw_params,
- kw_readonly, kw_ref, kw_string, kw_stackalloc, kw_sbyte, kw_sealed,
- kw_uint, kw_ulong, kw_unchecked, kw_unsafe, kw_ushort, kw_when,
- kw_where,
+ kw_fixed, kw_foreach, kw_implicit, kw_in, kw_init, kw_interface,
+ kw_internal, kw_is, kw_lock, kw_null, kw_object, kw_out, kw_override,
+ kw_params, kw_readonly, kw_ref, kw_string, kw_stackalloc, kw_sbyte,
+ kw_sealed, kw_uint, kw_ulong, kw_unchecked, kw_unsafe, kw_ushort,
+ kw_when, kw_where,
// Keywords from the JavaScript section.
kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,
kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly,
kw_set, kw_type, kw_typeof, kw_var, kw_yield,
// Keywords from the Java section.
kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});
+
+ // Some keywords are not included here because they don't need special
+ // treatment like `showcancelled` or they should be treated as identifiers
+ // like `int` and `logic`.
+ VerilogExtraKeywords = std::unordered_set<IdentifierInfo *>(
+ {kw_always, kw_always_comb,
+ kw_always_ff, kw_always_latch,
+ kw_assert, kw_assign,
+ kw_assume, kw_automatic,
+ kw_before, kw_begin,
+ kw_bins, kw_binsof,
+ kw_casex, kw_casez,
+ kw_celldefine, kw_checker,
+ kw_clocking, kw_constraint,
+ kw_cover, kw_covergroup,
+ kw_coverpoint, kw_disable,
+ kw_dist, kw_edge,
+ kw_end, kw_endcase,
+ kw_endchecker, kw_endclass,
+ kw_endclocking, kw_endfunction,
+ kw_endgenerate, kw_endgroup,
+ kw_endinterface, kw_endmodule,
+ kw_endpackage, kw_endprimitive,
+ kw_endprogram, kw_endproperty,
+ kw_endsequence, kw_endspecify,
+ kw_endtable, kw_endtask,
+ kw_extends, kw_final,
+ kw_foreach, kw_forever,
+ kw_fork, kw_function,
+ kw_generate, kw_highz0,
+ kw_highz1, kw_iff,
+ kw_ifnone, kw_ignore_bins,
+ kw_illegal_bins, kw_implements,
+ kw_import, kw_initial,
+ kw_inout, kw_input,
+ kw_inside, kw_interconnect,
+ kw_interface, kw_intersect,
+ kw_join, kw_join_any,
+ kw_join_none, kw_large,
+ kw_let, kw_local,
+ kw_localparam, kw_macromodule,
+ kw_matches, kw_medium,
+ kw_negedge, kw_output,
+ kw_package, kw_packed,
+ kw_parameter, kw_posedge,
+ kw_primitive, kw_priority,
+ kw_program, kw_property,
+ kw_pull0, kw_pull1,
+ kw_pure, kw_rand,
+ kw_randc, kw_randcase,
+ kw_randsequence, kw_ref,
+ kw_repeat, kw_sample,
+ kw_scalared, kw_sequence,
+ kw_small, kw_soft,
+ kw_solve, kw_specify,
+ kw_specparam, kw_strong0,
+ kw_strong1, kw_supply0,
+ kw_supply1, kw_table,
+ kw_tagged, kw_task,
+ kw_tri, kw_tri0,
+ kw_tri1, kw_triand,
+ kw_trior, kw_trireg,
+ kw_unique, kw_unique0,
+ kw_uwire, kw_var,
+ kw_vectored, kw_wand,
+ kw_weak0, kw_weak1,
+ kw_wildcard, kw_wire,
+ kw_with, kw_wor,
+ kw_verilogHash, kw_verilogHashHash});
+
+ TableGenExtraKeywords = std::unordered_set<IdentifierInfo *>({
+ kw_assert,
+ kw_bit,
+ kw_bits,
+ kw_code,
+ kw_dag,
+ kw_def,
+ kw_defm,
+ kw_defset,
+ kw_defvar,
+ kw_dump,
+ kw_foreach,
+ kw_in,
+ kw_include,
+ kw_let,
+ kw_list,
+ kw_multiclass,
+ kw_string,
+ kw_then,
+ });
}
// Context sensitive keywords.
@@ -964,6 +1402,7 @@ struct AdditionalKeywords {
IdentifierInfo *kw_CF_OPTIONS;
IdentifierInfo *kw_NS_CLOSED_ENUM;
IdentifierInfo *kw_NS_ENUM;
+ IdentifierInfo *kw_NS_ERROR_ENUM;
IdentifierInfo *kw_NS_OPTIONS;
IdentifierInfo *kw___except;
IdentifierInfo *kw___has_include;
@@ -1004,6 +1443,7 @@ struct AdditionalKeywords {
// Pragma keywords.
IdentifierInfo *kw_mark;
+ IdentifierInfo *kw_region;
// Proto keywords.
IdentifierInfo *kw_extend;
@@ -1019,6 +1459,9 @@ struct AdditionalKeywords {
IdentifierInfo *kw_slots;
IdentifierInfo *kw_qslots;
+ // For internal use by clang-format.
+ IdentifierInfo *kw_internal_ident_after_define;
+
// C# keywords
IdentifierInfo *kw_dollar;
IdentifierInfo *kw_base;
@@ -1030,6 +1473,7 @@ struct AdditionalKeywords {
IdentifierInfo *kw_fixed;
IdentifierInfo *kw_foreach;
IdentifierInfo *kw_implicit;
+ IdentifierInfo *kw_init;
IdentifierInfo *kw_internal;
IdentifierInfo *kw_lock;
@@ -1052,15 +1496,178 @@ struct AdditionalKeywords {
IdentifierInfo *kw_when;
IdentifierInfo *kw_where;
+ // Verilog keywords
+ IdentifierInfo *kw_always;
+ IdentifierInfo *kw_always_comb;
+ IdentifierInfo *kw_always_ff;
+ IdentifierInfo *kw_always_latch;
+ IdentifierInfo *kw_assign;
+ IdentifierInfo *kw_assume;
+ IdentifierInfo *kw_automatic;
+ IdentifierInfo *kw_before;
+ IdentifierInfo *kw_begin;
+ IdentifierInfo *kw_begin_keywords;
+ IdentifierInfo *kw_bins;
+ IdentifierInfo *kw_binsof;
+ IdentifierInfo *kw_casex;
+ IdentifierInfo *kw_casez;
+ IdentifierInfo *kw_celldefine;
+ IdentifierInfo *kw_checker;
+ IdentifierInfo *kw_clocking;
+ IdentifierInfo *kw_constraint;
+ IdentifierInfo *kw_cover;
+ IdentifierInfo *kw_covergroup;
+ IdentifierInfo *kw_coverpoint;
+ IdentifierInfo *kw_default_decay_time;
+ IdentifierInfo *kw_default_nettype;
+ IdentifierInfo *kw_default_trireg_strength;
+ IdentifierInfo *kw_delay_mode_distributed;
+ IdentifierInfo *kw_delay_mode_path;
+ IdentifierInfo *kw_delay_mode_unit;
+ IdentifierInfo *kw_delay_mode_zero;
+ IdentifierInfo *kw_disable;
+ IdentifierInfo *kw_dist;
+ IdentifierInfo *kw_elsif;
+ IdentifierInfo *kw_edge;
+ IdentifierInfo *kw_end;
+ IdentifierInfo *kw_end_keywords;
+ IdentifierInfo *kw_endcase;
+ IdentifierInfo *kw_endcelldefine;
+ IdentifierInfo *kw_endchecker;
+ IdentifierInfo *kw_endclass;
+ IdentifierInfo *kw_endclocking;
+ IdentifierInfo *kw_endfunction;
+ IdentifierInfo *kw_endgenerate;
+ IdentifierInfo *kw_endgroup;
+ IdentifierInfo *kw_endinterface;
+ IdentifierInfo *kw_endmodule;
+ IdentifierInfo *kw_endpackage;
+ IdentifierInfo *kw_endprimitive;
+ IdentifierInfo *kw_endprogram;
+ IdentifierInfo *kw_endproperty;
+ IdentifierInfo *kw_endsequence;
+ IdentifierInfo *kw_endspecify;
+ IdentifierInfo *kw_endtable;
+ IdentifierInfo *kw_endtask;
+ IdentifierInfo *kw_forever;
+ IdentifierInfo *kw_fork;
+ IdentifierInfo *kw_generate;
+ IdentifierInfo *kw_highz0;
+ IdentifierInfo *kw_highz1;
+ IdentifierInfo *kw_iff;
+ IdentifierInfo *kw_ifnone;
+ IdentifierInfo *kw_ignore_bins;
+ IdentifierInfo *kw_illegal_bins;
+ IdentifierInfo *kw_initial;
+ IdentifierInfo *kw_inout;
+ IdentifierInfo *kw_input;
+ IdentifierInfo *kw_inside;
+ IdentifierInfo *kw_interconnect;
+ IdentifierInfo *kw_intersect;
+ IdentifierInfo *kw_join;
+ IdentifierInfo *kw_join_any;
+ IdentifierInfo *kw_join_none;
+ IdentifierInfo *kw_large;
+ IdentifierInfo *kw_local;
+ IdentifierInfo *kw_localparam;
+ IdentifierInfo *kw_macromodule;
+ IdentifierInfo *kw_matches;
+ IdentifierInfo *kw_medium;
+ IdentifierInfo *kw_negedge;
+ IdentifierInfo *kw_nounconnected_drive;
+ IdentifierInfo *kw_output;
+ IdentifierInfo *kw_packed;
+ IdentifierInfo *kw_parameter;
+ IdentifierInfo *kw_posedge;
+ IdentifierInfo *kw_primitive;
+ IdentifierInfo *kw_priority;
+ IdentifierInfo *kw_program;
+ IdentifierInfo *kw_property;
+ IdentifierInfo *kw_pull0;
+ IdentifierInfo *kw_pull1;
+ IdentifierInfo *kw_pure;
+ IdentifierInfo *kw_rand;
+ IdentifierInfo *kw_randc;
+ IdentifierInfo *kw_randcase;
+ IdentifierInfo *kw_randsequence;
+ IdentifierInfo *kw_repeat;
+ IdentifierInfo *kw_resetall;
+ IdentifierInfo *kw_sample;
+ IdentifierInfo *kw_scalared;
+ IdentifierInfo *kw_sequence;
+ IdentifierInfo *kw_small;
+ IdentifierInfo *kw_soft;
+ IdentifierInfo *kw_solve;
+ IdentifierInfo *kw_specify;
+ IdentifierInfo *kw_specparam;
+ IdentifierInfo *kw_strong0;
+ IdentifierInfo *kw_strong1;
+ IdentifierInfo *kw_supply0;
+ IdentifierInfo *kw_supply1;
+ IdentifierInfo *kw_table;
+ IdentifierInfo *kw_tagged;
+ IdentifierInfo *kw_task;
+ IdentifierInfo *kw_timescale;
+ IdentifierInfo *kw_tri0;
+ IdentifierInfo *kw_tri1;
+ IdentifierInfo *kw_tri;
+ IdentifierInfo *kw_triand;
+ IdentifierInfo *kw_trior;
+ IdentifierInfo *kw_trireg;
+ IdentifierInfo *kw_unconnected_drive;
+ IdentifierInfo *kw_undefineall;
+ IdentifierInfo *kw_unique;
+ IdentifierInfo *kw_unique0;
+ IdentifierInfo *kw_uwire;
+ IdentifierInfo *kw_vectored;
+ IdentifierInfo *kw_wand;
+ IdentifierInfo *kw_weak0;
+ IdentifierInfo *kw_weak1;
+ IdentifierInfo *kw_wildcard;
+ IdentifierInfo *kw_wire;
+ IdentifierInfo *kw_with;
+ IdentifierInfo *kw_wor;
+
+ // Workaround for hashes and backticks in Verilog.
+ IdentifierInfo *kw_verilogHash;
+ IdentifierInfo *kw_verilogHashHash;
+
+ // Symbols in Verilog that don't exist in C++.
+ IdentifierInfo *kw_apostrophe;
+
+ // TableGen keywords
+ IdentifierInfo *kw_bit;
+ IdentifierInfo *kw_bits;
+ IdentifierInfo *kw_code;
+ IdentifierInfo *kw_dag;
+ IdentifierInfo *kw_def;
+ IdentifierInfo *kw_defm;
+ IdentifierInfo *kw_defset;
+ IdentifierInfo *kw_defvar;
+ IdentifierInfo *kw_dump;
+ IdentifierInfo *kw_include;
+ IdentifierInfo *kw_list;
+ IdentifierInfo *kw_multiclass;
+ IdentifierInfo *kw_then;
+
+ /// Returns \c true if \p Tok is a keyword or an identifier.
+ bool isWordLike(const FormatToken &Tok, bool IsVerilog = true) const {
+ // getIdentifierinfo returns non-null for keywords as well as identifiers.
+ return Tok.Tok.getIdentifierInfo() &&
+ (!IsVerilog || !isVerilogKeywordSymbol(Tok));
+ }
+
/// Returns \c true if \p Tok is a true JavaScript identifier, returns
/// \c false if it is a keyword or a pseudo keyword.
/// If \c AcceptIdentifierName is true, returns true not only for keywords,
// but also for IdentifierName tokens (aka pseudo-keywords), such as
// ``yield``.
- bool IsJavaScriptIdentifier(const FormatToken &Tok,
+ bool isJavaScriptIdentifier(const FormatToken &Tok,
bool AcceptIdentifierName = true) const {
// Based on the list of JavaScript & TypeScript keywords here:
- // https://github.com/microsoft/TypeScript/blob/master/src/compiler/scanner.ts#L74
+ // https://github.com/microsoft/TypeScript/blob/main/src/compiler/scanner.ts#L74
+ if (Tok.isAccessSpecifierKeyword())
+ return false;
switch (Tok.Tok.getKind()) {
case tok::kw_break:
case tok::kw_case:
@@ -1080,9 +1687,6 @@ struct AdditionalKeywords {
case tok::kw_import:
case tok::kw_module:
case tok::kw_new:
- case tok::kw_private:
- case tok::kw_protected:
- case tok::kw_public:
case tok::kw_return:
case tok::kw_static:
case tok::kw_switch:
@@ -1125,6 +1729,8 @@ struct AdditionalKeywords {
/// Returns \c true if \p Tok is a C# keyword, returns
/// \c false if it is a anything else.
bool isCSharpKeyword(const FormatToken &Tok) const {
+ if (Tok.isAccessSpecifierKeyword())
+ return true;
switch (Tok.Tok.getKind()) {
case tok::kw_bool:
case tok::kw_break:
@@ -1151,9 +1757,6 @@ struct AdditionalKeywords {
case tok::kw_namespace:
case tok::kw_new:
case tok::kw_operator:
- case tok::kw_private:
- case tok::kw_protected:
- case tok::kw_public:
case tok::kw_return:
case tok::kw_short:
case tok::kw_sizeof:
@@ -1178,14 +1781,203 @@ struct AdditionalKeywords {
}
}
+ bool isVerilogKeywordSymbol(const FormatToken &Tok) const {
+ return Tok.isOneOf(kw_verilogHash, kw_verilogHashHash, kw_apostrophe);
+ }
+
+ bool isVerilogWordOperator(const FormatToken &Tok) const {
+ return Tok.isOneOf(kw_before, kw_intersect, kw_dist, kw_iff, kw_inside,
+ kw_with);
+ }
+
+ bool isVerilogIdentifier(const FormatToken &Tok) const {
+ switch (Tok.Tok.getKind()) {
+ case tok::kw_case:
+ case tok::kw_class:
+ case tok::kw_const:
+ case tok::kw_continue:
+ case tok::kw_default:
+ case tok::kw_do:
+ case tok::kw_extern:
+ case tok::kw_else:
+ case tok::kw_enum:
+ case tok::kw_for:
+ case tok::kw_if:
+ case tok::kw_restrict:
+ case tok::kw_signed:
+ case tok::kw_static:
+ case tok::kw_struct:
+ case tok::kw_typedef:
+ case tok::kw_union:
+ case tok::kw_unsigned:
+ case tok::kw_virtual:
+ case tok::kw_while:
+ return false;
+ case tok::identifier:
+ return isWordLike(Tok) &&
+ VerilogExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==
+ VerilogExtraKeywords.end();
+ default:
+ // getIdentifierInfo returns non-null for both identifiers and keywords.
+ return Tok.Tok.getIdentifierInfo();
+ }
+ }
+
+ /// Returns whether \p Tok is a Verilog preprocessor directive. This is
+ /// needed because macro expansions start with a backtick as well and they
+ /// need to be treated differently.
+ bool isVerilogPPDirective(const FormatToken &Tok) const {
+ auto Info = Tok.Tok.getIdentifierInfo();
+ if (!Info)
+ return false;
+ switch (Info->getPPKeywordID()) {
+ case tok::pp_define:
+ case tok::pp_else:
+ case tok::pp_endif:
+ case tok::pp_ifdef:
+ case tok::pp_ifndef:
+ case tok::pp_include:
+ case tok::pp_line:
+ case tok::pp_pragma:
+ case tok::pp_undef:
+ return true;
+ default:
+ return Tok.isOneOf(kw_begin_keywords, kw_celldefine,
+ kw_default_decay_time, kw_default_nettype,
+ kw_default_trireg_strength, kw_delay_mode_distributed,
+ kw_delay_mode_path, kw_delay_mode_unit,
+ kw_delay_mode_zero, kw_elsif, kw_end_keywords,
+ kw_endcelldefine, kw_nounconnected_drive, kw_resetall,
+ kw_timescale, kw_unconnected_drive, kw_undefineall);
+ }
+ }
+
+ /// Returns whether \p Tok is a Verilog keyword that opens a block.
+ bool isVerilogBegin(const FormatToken &Tok) const {
+ // `table` is not included since it needs to be treated specially.
+ return !Tok.endsSequence(kw_fork, kw_disable) &&
+ Tok.isOneOf(kw_begin, kw_fork, kw_generate, kw_specify);
+ }
+
+ /// Returns whether \p Tok is a Verilog keyword that closes a block.
+ bool isVerilogEnd(const FormatToken &Tok) const {
+ return !Tok.endsSequence(kw_join, kw_rand) &&
+ Tok.isOneOf(TT_MacroBlockEnd, kw_end, kw_endcase, kw_endclass,
+ kw_endclocking, kw_endchecker, kw_endfunction,
+ kw_endgenerate, kw_endgroup, kw_endinterface,
+ kw_endmodule, kw_endpackage, kw_endprimitive,
+ kw_endprogram, kw_endproperty, kw_endsequence,
+ kw_endspecify, kw_endtable, kw_endtask, kw_join,
+ kw_join_any, kw_join_none);
+ }
+
+ /// Returns whether \p Tok is a Verilog keyword that opens a module, etc.
+ bool isVerilogHierarchy(const FormatToken &Tok) const {
+ if (Tok.endsSequence(kw_function, kw_with))
+ return false;
+ if (Tok.is(kw_property)) {
+ const FormatToken *Prev = Tok.getPreviousNonComment();
+ return !(Prev &&
+ Prev->isOneOf(tok::kw_restrict, kw_assert, kw_assume, kw_cover));
+ }
+ return Tok.isOneOf(tok::kw_case, tok::kw_class, kw_function, kw_module,
+ kw_interface, kw_package, kw_casex, kw_casez, kw_checker,
+ kw_clocking, kw_covergroup, kw_macromodule, kw_primitive,
+ kw_program, kw_property, kw_randcase, kw_randsequence,
+ kw_task);
+ }
+
+ bool isVerilogEndOfLabel(const FormatToken &Tok) const {
+ const FormatToken *Next = Tok.getNextNonComment();
+ // In Verilog the colon in a default label is optional.
+ return Tok.is(TT_CaseLabelColon) ||
+ (Tok.is(tok::kw_default) &&
+ !(Next && Next->isOneOf(tok::colon, tok::semi, kw_clocking, kw_iff,
+ kw_input, kw_output, kw_sequence)));
+ }
+
+ /// Returns whether \p Tok is a Verilog keyword that starts a
+ /// structured procedure like 'always'.
+ bool isVerilogStructuredProcedure(const FormatToken &Tok) const {
+ return Tok.isOneOf(kw_always, kw_always_comb, kw_always_ff, kw_always_latch,
+ kw_final, kw_forever, kw_initial);
+ }
+
+ bool isVerilogQualifier(const FormatToken &Tok) const {
+ switch (Tok.Tok.getKind()) {
+ case tok::kw_extern:
+ case tok::kw_signed:
+ case tok::kw_static:
+ case tok::kw_unsigned:
+ case tok::kw_virtual:
+ return true;
+ case tok::identifier:
+ return Tok.isOneOf(
+ kw_let, kw_var, kw_ref, kw_automatic, kw_bins, kw_coverpoint,
+ kw_ignore_bins, kw_illegal_bins, kw_inout, kw_input, kw_interconnect,
+ kw_local, kw_localparam, kw_output, kw_parameter, kw_pure, kw_rand,
+ kw_randc, kw_scalared, kw_specparam, kw_tri, kw_tri0, kw_tri1,
+ kw_triand, kw_trior, kw_trireg, kw_uwire, kw_vectored, kw_wand,
+ kw_wildcard, kw_wire, kw_wor);
+ default:
+ return false;
+ }
+ }
+
+ bool isTableGenDefinition(const FormatToken &Tok) const {
+ return Tok.isOneOf(kw_def, kw_defm, kw_defset, kw_defvar, kw_multiclass,
+ kw_let, tok::kw_class);
+ }
+
+ bool isTableGenKeyword(const FormatToken &Tok) const {
+ switch (Tok.Tok.getKind()) {
+ case tok::kw_class:
+ case tok::kw_else:
+ case tok::kw_false:
+ case tok::kw_if:
+ case tok::kw_int:
+ case tok::kw_true:
+ return true;
+ default:
+ return Tok.is(tok::identifier) &&
+ TableGenExtraKeywords.find(Tok.Tok.getIdentifierInfo()) !=
+ TableGenExtraKeywords.end();
+ }
+ }
+
private:
/// The JavaScript keywords beyond the C++ keyword set.
std::unordered_set<IdentifierInfo *> JsExtraKeywords;
/// The C# keywords beyond the C++ keyword set
std::unordered_set<IdentifierInfo *> CSharpExtraKeywords;
+
+ /// The Verilog keywords beyond the C++ keyword set.
+ std::unordered_set<IdentifierInfo *> VerilogExtraKeywords;
+
+ /// The TableGen keywords beyond the C++ keyword set.
+ std::unordered_set<IdentifierInfo *> TableGenExtraKeywords;
};
+inline bool isLineComment(const FormatToken &FormatTok) {
+ return FormatTok.is(tok::comment) && !FormatTok.TokenText.starts_with("/*");
+}
+
+// Checks if \p FormatTok is a line comment that continues the line comment
+// \p Previous. The original column of \p MinColumnToken is used to determine
+// whether \p FormatTok is indented enough to the right to continue \p Previous.
+inline bool continuesLineComment(const FormatToken &FormatTok,
+ const FormatToken *Previous,
+ const FormatToken *MinColumnToken) {
+ if (!Previous || !MinColumnToken)
+ return false;
+ unsigned MinContinueColumn =
+ MinColumnToken->OriginalColumn + (isLineComment(*MinColumnToken) ? 0 : 1);
+ return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 &&
+ isLineComment(*Previous) &&
+ FormatTok.OriginalColumn >= MinContinueColumn;
+}
+
} // namespace format
} // namespace clang