Skip to content

[clang-format[NFC] Clean up AnnotatingParser::rParenEndsCast() #96128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 46 additions & 37 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2661,18 +2661,27 @@ class AnnotatingParser {

/// 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.
Expand Down Expand Up @@ -2728,37 +2737,38 @@ class AnnotatingParser {
}
}

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");
Expand Down Expand Up @@ -2791,12 +2801,11 @@ class AnnotatingParser {
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;

Expand All @@ -2808,49 +2817,49 @@ class AnnotatingParser {

// 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 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;
}

Expand Down
Loading