summaryrefslogtreecommitdiff
path: root/clang/lib/Format/TokenAnnotator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Format/TokenAnnotator.cpp')
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp167
1 files changed, 96 insertions, 71 deletions
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 1fe3b61a5a81..89e134144d43 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -127,7 +127,7 @@ public:
SmallVector<ScopeType> &Scopes)
: Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),
IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)),
- Keywords(Keywords), Scopes(Scopes) {
+ Keywords(Keywords), Scopes(Scopes), TemplateDeclarationDepth(0) {
assert(IsCpp == LangOpts.CXXOperatorNames);
Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
resetTokenMetadata();
@@ -647,8 +647,8 @@ private:
return true;
// Limit this to being an access modifier that follows.
- if (AttrTok->isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
- tok::comment, tok::kw_class, tok::kw_static,
+ if (AttrTok->isAccessSpecifierKeyword() ||
+ AttrTok->isOneOf(tok::comment, tok::kw_class, tok::kw_static,
tok::l_square, Keywords.kw_internal)) {
return true;
}
@@ -1266,16 +1266,22 @@ private:
}
bool parseTemplateDeclaration() {
- if (CurrentToken && CurrentToken->is(tok::less)) {
- CurrentToken->setType(TT_TemplateOpener);
- next();
- if (!parseAngle())
- return false;
- if (CurrentToken)
- CurrentToken->Previous->ClosesTemplateDeclaration = true;
- return true;
- }
- return false;
+ if (!CurrentToken || CurrentToken->isNot(tok::less))
+ return false;
+
+ CurrentToken->setType(TT_TemplateOpener);
+ next();
+
+ TemplateDeclarationDepth++;
+ const bool WellFormed = parseAngle();
+ TemplateDeclarationDepth--;
+ if (!WellFormed)
+ return false;
+
+ if (CurrentToken && TemplateDeclarationDepth == 0)
+ CurrentToken->Previous->ClosesTemplateDeclaration = true;
+
+ return true;
}
bool consumeToken() {
@@ -1419,6 +1425,8 @@ private:
Tok->setType(TT_CtorInitializerColon);
} else {
Tok->setType(TT_InheritanceColon);
+ if (Prev->isAccessSpecifierKeyword())
+ Line.Type = LT_AccessModifier;
}
} else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next &&
(Tok->Next->isOneOf(tok::r_paren, tok::comma) ||
@@ -1998,6 +2006,8 @@ public:
if (!consumeToken())
return LT_Invalid;
}
+ if (Line.Type == LT_AccessModifier)
+ return LT_AccessModifier;
if (KeywordVirtualFound)
return LT_VirtualFunctionDecl;
if (ImportStatement)
@@ -2329,7 +2339,7 @@ private:
if (Current.Previous) {
bool IsIdentifier =
Style.isJavaScript()
- ? Keywords.IsJavaScriptIdentifier(
+ ? Keywords.isJavaScriptIdentifier(
*Current.Previous, /* AcceptIdentifierName= */ true)
: Current.Previous->is(tok::identifier);
if (IsIdentifier ||
@@ -2657,18 +2667,27 @@ private:
/// Determine whether ')' is ending a cast.
bool rParenEndsCast(const FormatToken &Tok) {
+ assert(Tok.is(tok::r_paren));
+
+ if (!Tok.MatchingParen || !Tok.Previous)
+ return false;
+
// C-style casts are only used in C++, C# and Java.
- if (!Style.isCSharp() && !IsCpp && Style.Language != FormatStyle::LK_Java)
+ if (!IsCpp && !Style.isCSharp() && Style.Language != FormatStyle::LK_Java)
return false;
+ const auto *LParen = Tok.MatchingParen;
+ const auto *BeforeRParen = Tok.Previous;
+ const auto *AfterRParen = Tok.Next;
+
// Empty parens aren't casts and there are no casts at the end of the line.
- if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen)
+ if (BeforeRParen == LParen || !AfterRParen)
return false;
- if (Tok.MatchingParen->is(TT_OverloadedOperatorLParen))
+ if (LParen->is(TT_OverloadedOperatorLParen))
return false;
- FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
+ auto *LeftOfParens = LParen->getPreviousNonComment();
if (LeftOfParens) {
// If there is a closing parenthesis left of the current
// parentheses, look past it as these might be chained casts.
@@ -2724,37 +2743,38 @@ private:
}
}
- if (Tok.Next->is(tok::question) ||
- (Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(LangOpts))) {
+ if (AfterRParen->is(tok::question) ||
+ (AfterRParen->is(tok::ampamp) && !BeforeRParen->isTypeName(LangOpts))) {
return false;
}
// `foreach((A a, B b) in someList)` should not be seen as a cast.
- if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp())
+ if (AfterRParen->is(Keywords.kw_in) && Style.isCSharp())
return false;
// Functions which end with decorations like volatile, noexcept are unlikely
// to be casts.
- if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
- tok::kw_requires, tok::kw_throw, tok::arrow,
- Keywords.kw_override, Keywords.kw_final) ||
- isCppAttribute(IsCpp, *Tok.Next)) {
+ if (AfterRParen->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
+ tok::kw_requires, tok::kw_throw, tok::arrow,
+ Keywords.kw_override, Keywords.kw_final) ||
+ isCppAttribute(IsCpp, *AfterRParen)) {
return false;
}
// As Java has no function types, a "(" after the ")" likely means that this
// is a cast.
- if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren))
+ if (Style.Language == FormatStyle::LK_Java && AfterRParen->is(tok::l_paren))
return true;
// If a (non-string) literal follows, this is likely a cast.
- if (Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof) ||
- (Tok.Next->Tok.isLiteral() && Tok.Next->isNot(tok::string_literal))) {
+ if (AfterRParen->isOneOf(tok::kw_sizeof, tok::kw_alignof) ||
+ (AfterRParen->Tok.isLiteral() &&
+ AfterRParen->isNot(tok::string_literal))) {
return true;
}
// Heuristically try to determine whether the parentheses contain a type.
- auto IsQualifiedPointerOrReference = [](FormatToken *T,
+ auto IsQualifiedPointerOrReference = [](const FormatToken *T,
const LangOptions &LangOpts) {
// This is used to handle cases such as x = (foo *const)&y;
assert(!T->isTypeName(LangOpts) && "Should have already been checked");
@@ -2787,12 +2807,11 @@ private:
return T && T->is(TT_PointerOrReference);
};
bool ParensAreType =
- !Tok.Previous ||
- Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
- Tok.Previous->isTypeName(LangOpts) ||
- IsQualifiedPointerOrReference(Tok.Previous, LangOpts);
+ BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
+ BeforeRParen->isTypeName(LangOpts) ||
+ IsQualifiedPointerOrReference(BeforeRParen, LangOpts);
bool ParensCouldEndDecl =
- Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
+ AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
if (ParensAreType && !ParensCouldEndDecl)
return true;
@@ -2804,49 +2823,54 @@ private:
// Certain token types inside the parentheses mean that this can't be a
// cast.
- for (const FormatToken *Token = Tok.MatchingParen->Next; Token != &Tok;
- Token = Token->Next) {
+ for (const auto *Token = LParen->Next; Token != &Tok; Token = Token->Next)
if (Token->is(TT_BinaryOperator))
return false;
- }
// If the following token is an identifier or 'this', this is a cast. All
// cases where this can be something else are handled above.
- if (Tok.Next->isOneOf(tok::identifier, tok::kw_this))
+ if (AfterRParen->isOneOf(tok::identifier, tok::kw_this))
return true;
// Look for a cast `( x ) (`.
- if (Tok.Next->is(tok::l_paren) && Tok.Previous && Tok.Previous->Previous) {
- if (Tok.Previous->is(tok::identifier) &&
- Tok.Previous->Previous->is(tok::l_paren)) {
+ if (AfterRParen->is(tok::l_paren) && BeforeRParen->Previous) {
+ if (BeforeRParen->is(tok::identifier) &&
+ BeforeRParen->Previous->is(tok::l_paren)) {
return true;
}
}
- if (!Tok.Next->Next)
+ if (!AfterRParen->Next)
return false;
+ if (AfterRParen->is(tok::l_brace) &&
+ AfterRParen->getBlockKind() == BK_BracedInit) {
+ return true;
+ }
+
// If the next token after the parenthesis is a unary operator, assume
// that this is cast, unless there are unexpected tokens inside the
// parenthesis.
- const bool NextIsAmpOrStar = Tok.Next->isOneOf(tok::amp, tok::star);
- if (!(Tok.Next->isUnaryOperator() || NextIsAmpOrStar) ||
- Tok.Next->is(tok::plus) ||
- !Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant)) {
+ const bool NextIsAmpOrStar = AfterRParen->isOneOf(tok::amp, tok::star);
+ if (!(AfterRParen->isUnaryOperator() || NextIsAmpOrStar) ||
+ AfterRParen->is(tok::plus) ||
+ !AfterRParen->Next->isOneOf(tok::identifier, tok::numeric_constant)) {
return false;
}
+
if (NextIsAmpOrStar &&
- (Tok.Next->Next->is(tok::numeric_constant) || Line.InPPDirective)) {
+ (AfterRParen->Next->is(tok::numeric_constant) || Line.InPPDirective)) {
return false;
}
- if (Line.InPPDirective && Tok.Next->is(tok::minus))
+
+ if (Line.InPPDirective && AfterRParen->is(tok::minus))
return false;
+
// Search for unexpected tokens.
- for (FormatToken *Prev = Tok.Previous; Prev != Tok.MatchingParen;
- Prev = Prev->Previous) {
+ for (auto *Prev = BeforeRParen; Prev != LParen; Prev = Prev->Previous)
if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon))
return false;
- }
+
return true;
}
@@ -3073,6 +3097,8 @@ private:
// same decision irrespective of the decisions for tokens leading up to it.
// Store this information to prevent this from causing exponential runtime.
llvm::SmallPtrSet<FormatToken *, 16> NonTemplateLess;
+
+ int TemplateDeclarationDepth;
};
static const int PrecedenceUnaryOperator = prec::PointerToMember + 1;
@@ -3410,7 +3436,8 @@ private:
} else {
break;
}
- } else if (Tok->is(tok::hash)) {
+ } else if (Tok->is(Keywords.kw_verilogHash)) {
+ // Delay control.
if (Next->is(tok::l_paren))
Next = Next->MatchingParen;
if (Next)
@@ -4944,11 +4971,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// space between method modifier and opening parenthesis of a tuple return
// type
- if (Left.isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
- tok::kw_virtual, tok::kw_extern, tok::kw_static,
- Keywords.kw_internal, Keywords.kw_abstract,
- Keywords.kw_sealed, Keywords.kw_override,
- Keywords.kw_async, Keywords.kw_unsafe) &&
+ if ((Left.isAccessSpecifierKeyword() ||
+ Left.isOneOf(tok::kw_virtual, tok::kw_extern, tok::kw_static,
+ Keywords.kw_internal, Keywords.kw_abstract,
+ Keywords.kw_sealed, Keywords.kw_override,
+ Keywords.kw_async, Keywords.kw_unsafe)) &&
Right.is(tok::l_paren)) {
return true;
}
@@ -4974,7 +5001,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
}
// In tagged template literals ("html`bar baz`"), there is no space between
// the tag identifier and the template string.
- if (Keywords.IsJavaScriptIdentifier(Left,
+ if (Keywords.isJavaScriptIdentifier(Left,
/* AcceptIdentifierName= */ false) &&
Right.is(TT_TemplateString)) {
return false;
@@ -5069,9 +5096,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return Style.SpaceBeforeParensOptions.AfterControlStatements ||
spaceRequiredBeforeParens(Right);
}
- if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private,
- tok::kw_protected) ||
- Left.isOneOf(Keywords.kw_final, Keywords.kw_abstract,
+ if ((Left.isAccessSpecifierKeyword() ||
+ Left.isOneOf(tok::kw_static, Keywords.kw_final, Keywords.kw_abstract,
Keywords.kw_native)) &&
Right.is(TT_TemplateOpener)) {
return true;
@@ -5694,9 +5720,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (isAllmanBrace(Left) || isAllmanBrace(Right)) {
auto *FirstNonComment = Line.getFirstNonComment();
bool AccessSpecifier =
- FirstNonComment &&
- FirstNonComment->isOneOf(Keywords.kw_internal, tok::kw_public,
- tok::kw_private, tok::kw_protected);
+ FirstNonComment && (FirstNonComment->is(Keywords.kw_internal) ||
+ FirstNonComment->isAccessSpecifierKeyword());
if (Style.BraceWrapping.AfterEnum) {
if (Line.startsWith(tok::kw_enum) ||
@@ -5882,13 +5907,13 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
} else if (Style.isJavaScript()) {
const FormatToken *NonComment = Right.getPreviousNonComment();
if (NonComment &&
- NonComment->isOneOf(
- tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,
- tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,
- tok::kw_static, tok::kw_public, tok::kw_private, tok::kw_protected,
- Keywords.kw_readonly, Keywords.kw_override, Keywords.kw_abstract,
- Keywords.kw_get, Keywords.kw_set, Keywords.kw_async,
- Keywords.kw_await)) {
+ (NonComment->isAccessSpecifierKeyword() ||
+ NonComment->isOneOf(
+ tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,
+ tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,
+ tok::kw_static, Keywords.kw_readonly, Keywords.kw_override,
+ Keywords.kw_abstract, Keywords.kw_get, Keywords.kw_set,
+ Keywords.kw_async, Keywords.kw_await))) {
return false; // Otherwise automatic semicolon insertion would trigger.
}
if (Right.NestingLevel == 0 &&