Skip to content

Commit 2f262ca

Browse files
committed
Fix identifiers not being marked as constructor/destructor names if they are qualified by a template type, or have template typename declarations in front of them.
1 parent 155fd97 commit 2f262ca

File tree

2 files changed

+106
-4
lines changed

2 files changed

+106
-4
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3622,6 +3622,29 @@ static unsigned maxNestingDepth(const AnnotatedLine &Line) {
36223622
return Result;
36233623
}
36243624

3625+
static bool startsQualifiedName(const FormatToken *Tok) {
3626+
// Consider: A::B::B()
3627+
// Tok --^
3628+
if (Tok->startsSequence(tok::identifier, tok::coloncolon))
3629+
return true;
3630+
3631+
// Consider: A<float>::B<int>::B()
3632+
// Tok --^
3633+
if (Tok->startsSequence(tok::identifier, TT_TemplateOpener)) {
3634+
Tok = Tok->getNextNonComment();
3635+
assert(Tok);
3636+
assert(Tok->is(TT_TemplateOpener));
3637+
3638+
if (!Tok->MatchingParen)
3639+
return false;
3640+
3641+
return Tok->MatchingParen->startsSequence(TT_TemplateCloser,
3642+
tok::coloncolon);
3643+
}
3644+
3645+
return false;
3646+
}
3647+
36253648
// Returns the name of a function with no return type, e.g. a constructor or
36263649
// destructor.
36273650
static FormatToken *getFunctionName(const AnnotatedLine &Line,
@@ -3651,6 +3674,21 @@ static FormatToken *getFunctionName(const AnnotatedLine &Line,
36513674
continue;
36523675
}
36533676

3677+
// Skip past template typename declarations that may precede the
3678+
// constructor/destructor name
3679+
if (Tok->is(tok::kw_template)) {
3680+
Tok = Tok->getNextNonComment();
3681+
if (!Tok)
3682+
return nullptr;
3683+
3684+
assert(Tok->is(TT_TemplateOpener));
3685+
Tok = Tok->MatchingParen;
3686+
if (!Tok)
3687+
return nullptr;
3688+
3689+
continue;
3690+
}
3691+
36543692
// A qualified name may start from the global namespace.
36553693
if (Tok->is(tok::coloncolon)) {
36563694
Tok = Tok->Next;
@@ -3659,9 +3697,23 @@ static FormatToken *getFunctionName(const AnnotatedLine &Line,
36593697
}
36603698

36613699
// Skip to the unqualified part of the name.
3662-
while (Tok->startsSequence(tok::identifier, tok::coloncolon)) {
3663-
assert(Tok->Next);
3664-
Tok = Tok->Next->Next;
3700+
while (startsQualifiedName(Tok)) {
3701+
Tok = Tok->getNextNonComment();
3702+
if (!Tok)
3703+
return nullptr;
3704+
3705+
// Skip template types if this is a templated type name
3706+
if (Tok->is(TT_TemplateOpener)) {
3707+
Tok = Tok->MatchingParen;
3708+
if (!Tok)
3709+
return nullptr;
3710+
3711+
Tok = Tok->getNextNonComment();
3712+
if (!Tok)
3713+
return nullptr;
3714+
}
3715+
3716+
Tok = Tok->getNextNonComment();
36653717
if (!Tok)
36663718
return nullptr;
36673719
}
@@ -3691,10 +3743,18 @@ static bool isCtorOrDtorName(const FormatToken *Tok) {
36913743
if (Prev && Prev->is(tok::tilde))
36923744
Prev = Prev->Previous;
36933745

3694-
if (!Prev || !Prev->endsSequence(tok::coloncolon, tok::identifier))
3746+
// Consider: A::A() and A<int>::A()
3747+
if (!Prev || (!Prev->endsSequence(tok::coloncolon, tok::identifier) &&
3748+
!Prev->endsSequence(tok::coloncolon, TT_TemplateCloser))) {
36953749
return false;
3750+
}
36963751

36973752
assert(Prev->Previous);
3753+
if (Prev->Previous->is(TT_TemplateCloser) && Prev->Previous->MatchingParen) {
3754+
Prev = Prev->Previous->MatchingParen;
3755+
assert(Prev->Previous);
3756+
}
3757+
36983758
return Prev->Previous->TokenText == Tok->TokenText;
36993759
}
37003760

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,48 @@ TEST_F(TokenAnnotatorTest, UnderstandsCtorAndDtorDeclNames) {
23462346
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_FunctionDeclarationLParen);
23472347
EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_FunctionLBrace);
23482348

2349+
Tokens = annotate("Foo<int>::Foo() {}");
2350+
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
2351+
EXPECT_TOKEN(Tokens[5], tok::identifier, TT_CtorDtorDeclName);
2352+
EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_FunctionDeclarationLParen);
2353+
EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_FunctionLBrace);
2354+
2355+
Tokens = annotate("Foo<int>::~Foo() {}");
2356+
ASSERT_EQ(Tokens.size(), 12u) << Tokens;
2357+
EXPECT_TOKEN(Tokens[6], tok::identifier, TT_CtorDtorDeclName);
2358+
EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_FunctionDeclarationLParen);
2359+
EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_FunctionLBrace);
2360+
2361+
Tokens = annotate("template <typename V> Foo<V>::Foo() {}");
2362+
ASSERT_EQ(Tokens.size(), 16u) << Tokens;
2363+
EXPECT_TOKEN(Tokens[10], tok::identifier, TT_CtorDtorDeclName);
2364+
EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_FunctionDeclarationLParen);
2365+
EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_FunctionLBrace);
2366+
2367+
Tokens = annotate("template <typename V> Foo<V>::~Foo() {}");
2368+
ASSERT_EQ(Tokens.size(), 17u) << Tokens;
2369+
EXPECT_TOKEN(Tokens[11], tok::identifier, TT_CtorDtorDeclName);
2370+
EXPECT_TOKEN(Tokens[12], tok::l_paren, TT_FunctionDeclarationLParen);
2371+
EXPECT_TOKEN(Tokens[14], tok::l_brace, TT_FunctionLBrace);
2372+
2373+
Tokens = annotate("template <typename V, typename U> Foo<V, U>::Foo() {}");
2374+
ASSERT_EQ(Tokens.size(), 21u) << Tokens;
2375+
EXPECT_TOKEN(Tokens[15], tok::identifier, TT_CtorDtorDeclName);
2376+
EXPECT_TOKEN(Tokens[16], tok::l_paren, TT_FunctionDeclarationLParen);
2377+
EXPECT_TOKEN(Tokens[18], tok::l_brace, TT_FunctionLBrace);
2378+
2379+
Tokens = annotate("template <typename V, typename U> Foo<V, U>::~Foo() {}");
2380+
ASSERT_EQ(Tokens.size(), 22u) << Tokens;
2381+
EXPECT_TOKEN(Tokens[16], tok::identifier, TT_CtorDtorDeclName);
2382+
EXPECT_TOKEN(Tokens[17], tok::l_paren, TT_FunctionDeclarationLParen);
2383+
EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_FunctionLBrace);
2384+
2385+
Tokens = annotate("template <typename V> template<typename W> Foo<V>::Foo(W x) {}");
2386+
ASSERT_EQ(Tokens.size(), 23u) << Tokens;
2387+
EXPECT_TOKEN(Tokens[15], tok::identifier, TT_CtorDtorDeclName);
2388+
EXPECT_TOKEN(Tokens[16], tok::l_paren, TT_FunctionDeclarationLParen);
2389+
EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_FunctionLBrace);
2390+
23492391
Tokens = annotate("struct Test {\n"
23502392
" Test()\n"
23512393
" : l([] {\n"

0 commit comments

Comments
 (0)