Skip to content

Commit 61612c5

Browse files
committed
Attach comments to decl even if preproc directives are in between
1 parent db2fb3d commit 61612c5

File tree

5 files changed

+323
-5
lines changed

5 files changed

+323
-5
lines changed

clang/lib/AST/ASTContext.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,10 @@ RawComment *ASTContext::getRawCommentForDeclNoCacheImpl(
282282
StringRef Text(Buffer + CommentEndOffset,
283283
DeclLocDecomp.second - CommentEndOffset);
284284

285-
// There should be no other declarations or preprocessor directives between
286-
// comment and declaration.
287-
if (Text.find_last_of(";{}#@") != StringRef::npos)
285+
// There should be no other declarations between comment and declaration.
286+
// Preprocessor directives are implicitly allowed to be between a comment and
287+
// its associated decl.
288+
if (Text.find_last_of(";{}@") != StringRef::npos)
288289
return nullptr;
289290

290291
return CommentBeforeDecl;

clang/lib/Headers/amxcomplexintrin.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
/// The 2nd source tile. Max size is 1024 Bytes.
6363
#define _tile_cmmimfp16ps(dst, a, b) __builtin_ia32_tcmmimfp16ps(dst, a, b)
6464

65+
;
66+
6567
/// Perform matrix multiplication of two tiles containing complex elements and
6668
/// accumulate the results into a packed single precision tile. Each dword
6769
/// element in input tiles \a a and \a b is interpreted as a complex number
@@ -107,6 +109,8 @@
107109
/// The 2nd source tile. Max size is 1024 Bytes.
108110
#define _tile_cmmrlfp16ps(dst, a, b) __builtin_ia32_tcmmrlfp16ps(dst, a, b)
109111

112+
;
113+
110114
static __inline__ _tile1024i __DEFAULT_FN_ATTRS_COMPLEX
111115
_tile_cmmimfp16ps_internal(unsigned short m, unsigned short n, unsigned short k,
112116
_tile1024i dst, _tile1024i src1, _tile1024i src2) {

clang/lib/Headers/ia32intrin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,8 @@ __rdtscp(unsigned int *__A) {
533533
/// \see __rdpmc
534534
#define _rdpmc(A) __rdpmc(A)
535535

536+
;
537+
536538
static __inline__ void __DEFAULT_FN_ATTRS
537539
_wbinvd(void) {
538540
__builtin_ia32_wbinvd();

clang/test/Index/annotate-comments.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,9 @@ void isdoxy45(void);
204204
/// Ggg. IS_DOXYGEN_END
205205
void isdoxy46(void);
206206

207-
/// IS_DOXYGEN_NOT_ATTACHED
207+
/// isdoxy47 IS_DOXYGEN_SINGLE
208208
#define FOO
209-
void notdoxy47(void);
209+
void isdoxy47(void);
210210

211211
/// IS_DOXYGEN_START Aaa bbb
212212
/// \param ccc
@@ -330,6 +330,7 @@ void isdoxy54(int);
330330
// CHECK: annotate-comments.cpp:185:6: FunctionDecl=isdoxy44:{{.*}} BriefComment=[IS_DOXYGEN_START Aaa bbb ccc.]
331331
// CHECK: annotate-comments.cpp:195:6: FunctionDecl=isdoxy45:{{.*}} BriefComment=[Ddd eee. Fff.]
332332
// CHECK: annotate-comments.cpp:205:6: FunctionDecl=isdoxy46:{{.*}} BriefComment=[Ddd eee. Fff.]
333+
// CHECK: annotate-comments.cpp:209:6: FunctionDecl=isdoxy47:{{.*}} isdoxy47 IS_DOXYGEN_SINGLE
333334
// CHECK: annotate-comments.cpp:214:6: FunctionDecl=isdoxy48:{{.*}} BriefComment=[IS_DOXYGEN_START Aaa bbb]
334335
// CHECK: annotate-comments.cpp:218:6: FunctionDecl=isdoxy49:{{.*}} BriefComment=[IS_DOXYGEN_START Aaa]
335336
// CHECK: annotate-comments.cpp:222:6: FunctionDecl=isdoxy50:{{.*}} BriefComment=[Returns ddd IS_DOXYGEN_END]

clang/unittests/AST/DeclTest.cpp

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,3 +545,313 @@ TEST(Decl, TemplateArgumentDefaulted) {
545545
EXPECT_TRUE(ArgList.get(2).getIsDefaulted());
546546
EXPECT_TRUE(ArgList.get(3).getIsDefaulted());
547547
}
548+
549+
TEST(Decl, CommentsAttachedToDecl1) {
550+
const SmallVector<StringRef> Sources{
551+
R"(
552+
/// Test comment
553+
void f();
554+
)",
555+
556+
R"(
557+
/// Test comment
558+
559+
void f();
560+
)",
561+
562+
R"(
563+
/// Test comment
564+
#if 0
565+
// tralala
566+
#endif
567+
void f();
568+
)",
569+
570+
R"(
571+
/// Test comment
572+
573+
#if 0
574+
// tralala
575+
#endif
576+
577+
void f();
578+
)",
579+
580+
R"(
581+
/// Test comment
582+
#ifdef DOCS
583+
template<typename T>
584+
#endif
585+
void f();
586+
)",
587+
588+
R"(
589+
/// Test comment
590+
591+
#ifdef DOCS
592+
template<typename T>
593+
#endif
594+
595+
void f();
596+
)",
597+
};
598+
599+
for (const auto code : Sources) {
600+
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
601+
ASTContext &Ctx = AST->getASTContext();
602+
603+
auto const *F = selectFirst<FunctionDecl>(
604+
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
605+
ASSERT_NE(F, nullptr);
606+
607+
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
608+
ASSERT_NE(C, nullptr);
609+
EXPECT_EQ(C->getRawText(Ctx.getSourceManager()), "/// Test comment");
610+
}
611+
}
612+
613+
TEST(Decl, CommentsAttachedToDecl2) {
614+
const SmallVector<StringRef> Sources{
615+
R"(
616+
/** Test comment
617+
*/
618+
void f();
619+
)",
620+
621+
R"(
622+
/** Test comment
623+
*/
624+
625+
void f();
626+
)",
627+
628+
R"(
629+
/** Test comment
630+
*/
631+
#if 0
632+
/* tralala */
633+
#endif
634+
void f();
635+
)",
636+
637+
R"(
638+
/** Test comment
639+
*/
640+
641+
#if 0
642+
/* tralala */
643+
#endif
644+
645+
void f();
646+
)",
647+
648+
R"(
649+
/** Test comment
650+
*/
651+
#ifdef DOCS
652+
template<typename T>
653+
#endif
654+
void f();
655+
)",
656+
657+
R"(
658+
/** Test comment
659+
*/
660+
661+
#ifdef DOCS
662+
template<typename T>
663+
#endif
664+
665+
void f();
666+
)",
667+
};
668+
669+
for (const auto code : Sources) {
670+
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
671+
ASTContext &Ctx = AST->getASTContext();
672+
673+
auto const *F = selectFirst<FunctionDecl>(
674+
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
675+
ASSERT_NE(F, nullptr);
676+
677+
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
678+
ASSERT_NE(C, nullptr);
679+
EXPECT_EQ(C->getRawText(Ctx.getSourceManager()),
680+
"/** Test comment\n */");
681+
}
682+
}
683+
684+
TEST(Decl, CommentsAttachedToDecl3) {
685+
const SmallVector<StringRef> Sources{
686+
R"(
687+
/// @brief Test comment
688+
void f();
689+
)",
690+
691+
R"(
692+
/// @brief Test comment
693+
694+
void f();
695+
)",
696+
697+
R"(
698+
/// @brief Test comment
699+
#if 0
700+
// tralala
701+
#endif
702+
void f();
703+
)",
704+
705+
R"(
706+
/// @brief Test comment
707+
708+
#if 0
709+
// tralala
710+
#endif
711+
712+
void f();
713+
)",
714+
715+
R"(
716+
/// @brief Test comment
717+
#ifdef DOCS
718+
template<typename T>
719+
#endif
720+
void f();
721+
)",
722+
723+
R"(
724+
/// @brief Test comment
725+
726+
#ifdef DOCS
727+
template<typename T>
728+
#endif
729+
730+
void f();
731+
)",
732+
};
733+
734+
for (const auto code : Sources) {
735+
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
736+
ASTContext &Ctx = AST->getASTContext();
737+
738+
auto const *F = selectFirst<FunctionDecl>(
739+
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
740+
ASSERT_NE(F, nullptr);
741+
742+
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
743+
ASSERT_NE(C, nullptr);
744+
EXPECT_EQ(C->getRawText(Ctx.getSourceManager()), "/// @brief Test comment");
745+
}
746+
}
747+
748+
TEST(Decl, CommentsAttachedToDecl4) {
749+
const SmallVector<StringRef> Sources{
750+
R"(
751+
/** \brief Test comment
752+
*/
753+
void f();
754+
)",
755+
756+
R"(
757+
/** \brief Test comment
758+
*/
759+
760+
void f();
761+
)",
762+
763+
R"(
764+
/** \brief Test comment
765+
*/
766+
#if 0
767+
/* tralala */
768+
#endif
769+
void f();
770+
)",
771+
772+
R"(
773+
/** \brief Test comment
774+
*/
775+
776+
#if 0
777+
/* tralala */
778+
#endif
779+
780+
void f();
781+
)",
782+
783+
R"(
784+
/** \brief Test comment
785+
*/
786+
#ifdef DOCS
787+
template<typename T>
788+
#endif
789+
void f();
790+
)",
791+
792+
R"(
793+
/** \brief Test comment
794+
*/
795+
796+
#ifdef DOCS
797+
template<typename T>
798+
#endif
799+
800+
void f();
801+
)",
802+
};
803+
804+
for (const auto code : Sources) {
805+
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
806+
ASTContext &Ctx = AST->getASTContext();
807+
808+
auto const *F = selectFirst<FunctionDecl>(
809+
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
810+
ASSERT_NE(F, nullptr);
811+
812+
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
813+
ASSERT_NE(C, nullptr);
814+
EXPECT_EQ(C->getRawText(Ctx.getSourceManager()),
815+
"/** \\brief Test comment\n */");
816+
}
817+
}
818+
819+
/// This example intentionally inserts characters between a doc comment and the
820+
/// associated declaration to verify that the comment does not become associated
821+
/// with the FunctionDecl.
822+
/// By default, Clang does not allow for other declarations (aside from
823+
/// preprocessor directives, as shown above) to be placed between a doc comment
824+
/// and a declaration.
825+
TEST(Decl, CommentsAttachedToDecl5) {
826+
const SmallVector<StringRef> Sources{
827+
R"(
828+
/// Test comment
829+
;
830+
void f();
831+
)",
832+
833+
R"(
834+
/// Test comment
835+
// @
836+
void f();
837+
)",
838+
839+
R"(
840+
/// Test comment
841+
// {}
842+
void f();
843+
)",
844+
};
845+
846+
for (const auto code : Sources) {
847+
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
848+
ASTContext &Ctx = AST->getASTContext();
849+
850+
auto const *F = selectFirst<FunctionDecl>(
851+
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
852+
ASSERT_NE(F, nullptr);
853+
854+
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
855+
ASSERT_EQ(C, nullptr);
856+
}
857+
}

0 commit comments

Comments
 (0)