Revert "[Clang][Comments] Attach comments to decl even if preproc directives are in between (#88367)"

This reverts commit 9f04d75b2bd8ba83863db74ebe1a5c08cfc5815c.

There was post-commit feedback on the direction this PR took.
This commit is contained in:
Aaron Ballman 2024-07-02 14:44:20 -04:00
parent 2f89d4a8c7
commit 072e81db7a
6 changed files with 5 additions and 358 deletions

View File

@ -147,22 +147,6 @@ Clang Frontend Potentially Breaking Changes
- The ``hasTypeLoc`` AST matcher will no longer match a ``classTemplateSpecializationDecl``;
existing uses should switch to ``templateArgumentLoc`` or ``hasAnyTemplateArgumentLoc`` instead.
- The comment parser now matches comments to declarations even if there is a
preprocessor macro in between the comment and declaration. This change is
intended to improve Clang's support for parsing documentation comments and
to better conform to Doxygen's behavior.
This has the potential to cause ``-Wdocumentation`` warnings, especially in
cases where a function-like macro has a documentation comment and is followed
immediately by a normal function. The function-like macro's documentation
comments will be attributed to the subsequent function and may cause
``-Wdocumentation`` warnings such as mismatched parameter names, or invalid
return documentation comments.
In cases where the ``-Wdocumentation`` warnings are thrown, the suggested fix
is to document the declaration following the macro so that the warnings are
fixed.
Clang Python Bindings Potentially Breaking Changes
--------------------------------------------------
- Renamed ``CursorKind`` variant 272 from ``OMP_TEAMS_DISTRIBUTE_DIRECTIVE``

View File

@ -284,10 +284,9 @@ RawComment *ASTContext::getRawCommentForDeclNoCacheImpl(
StringRef Text(Buffer + CommentEndOffset,
DeclLocDecomp.second - CommentEndOffset);
// There should be no other declarations between comment and declaration.
// Preprocessor directives are implicitly allowed to be between a comment and
// its associated decl.
if (Text.find_last_of(";{}@") != StringRef::npos)
// There should be no other declarations or preprocessor directives between
// comment and declaration.
if (Text.find_last_of(";{}#@") != StringRef::npos)
return nullptr;
return CommentBeforeDecl;

View File

@ -107,24 +107,6 @@
/// The 2nd source tile. Max size is 1024 Bytes.
#define _tile_cmmrlfp16ps(dst, a, b) __builtin_ia32_tcmmrlfp16ps(dst, a, b)
/// Perform matrix multiplication of two tiles containing complex elements and
/// accumulate the results into a packed single precision tile.
///
/// \param m
/// The number of rows in the first tile and the number of rows in the result
/// tile.
/// \param n
/// The number of columns in the second tile and the number of columns in the
/// result tile.
/// \param k
/// The number of columns in the first tile and the number of rows in the
/// second tile.
/// \param dst
/// Pointer to the destination tile where the result will be stored.
/// \param src1
/// Pointer to the first source tile.
/// \param src2
/// Pointer to the second source tile.
static __inline__ _tile1024i __DEFAULT_FN_ATTRS_COMPLEX
_tile_cmmimfp16ps_internal(unsigned short m, unsigned short n, unsigned short k,
_tile1024i dst, _tile1024i src1, _tile1024i src2) {

View File

@ -533,13 +533,6 @@ __rdtscp(unsigned int *__A) {
/// \see __rdpmc
#define _rdpmc(A) __rdpmc(A)
/// Invalidates the contents of the processor's internal caches.
/// This function writes back and invalidates all modified cache lines in
/// the processor.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the \c WBINVD instruction.
static __inline__ void __DEFAULT_FN_ATTRS
_wbinvd(void) {
__builtin_ia32_wbinvd();

View File

@ -204,9 +204,9 @@ void isdoxy45(void);
/// Ggg. IS_DOXYGEN_END
void isdoxy46(void);
/// isdoxy47 IS_DOXYGEN_SINGLE
/// IS_DOXYGEN_NOT_ATTACHED
#define FOO
void isdoxy47(void);
void notdoxy47(void);
/// IS_DOXYGEN_START Aaa bbb
/// \param ccc
@ -330,7 +330,6 @@ void isdoxy54(int);
// CHECK: annotate-comments.cpp:185:6: FunctionDecl=isdoxy44:{{.*}} BriefComment=[IS_DOXYGEN_START Aaa bbb ccc.]
// CHECK: annotate-comments.cpp:195:6: FunctionDecl=isdoxy45:{{.*}} BriefComment=[Ddd eee. Fff.]
// CHECK: annotate-comments.cpp:205:6: FunctionDecl=isdoxy46:{{.*}} BriefComment=[Ddd eee. Fff.]
// CHECK: annotate-comments.cpp:209:6: FunctionDecl=isdoxy47:{{.*}} isdoxy47 IS_DOXYGEN_SINGLE
// CHECK: annotate-comments.cpp:214:6: FunctionDecl=isdoxy48:{{.*}} BriefComment=[IS_DOXYGEN_START Aaa bbb]
// CHECK: annotate-comments.cpp:218:6: FunctionDecl=isdoxy49:{{.*}} BriefComment=[IS_DOXYGEN_START Aaa]
// CHECK: annotate-comments.cpp:222:6: FunctionDecl=isdoxy50:{{.*}} BriefComment=[Returns ddd IS_DOXYGEN_END]

View File

@ -576,313 +576,3 @@ void instantiate_template() {
EXPECT_EQ(GetNameInfoRange(Matches[1]), "<input.cc:6:14, col:15>");
EXPECT_EQ(GetNameInfoRange(Matches[2]), "<input.cc:6:14, col:15>");
}
TEST(Decl, CommentsAttachedToDecl1) {
const SmallVector<StringRef> Sources{
R"(
/// Test comment
void f();
)",
R"(
/// Test comment
void f();
)",
R"(
/// Test comment
#if 0
// tralala
#endif
void f();
)",
R"(
/// Test comment
#if 0
// tralala
#endif
void f();
)",
R"(
/// Test comment
#ifdef DOCS
template<typename T>
#endif
void f();
)",
R"(
/// Test comment
#ifdef DOCS
template<typename T>
#endif
void f();
)",
};
for (const auto code : Sources) {
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
ASTContext &Ctx = AST->getASTContext();
auto const *F = selectFirst<FunctionDecl>(
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
ASSERT_NE(F, nullptr);
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
ASSERT_NE(C, nullptr);
EXPECT_EQ(C->getRawText(Ctx.getSourceManager()), "/// Test comment");
}
}
TEST(Decl, CommentsAttachedToDecl2) {
const SmallVector<StringRef> Sources{
R"(
/** Test comment
*/
void f();
)",
R"(
/** Test comment
*/
void f();
)",
R"(
/** Test comment
*/
#if 0
/* tralala */
#endif
void f();
)",
R"(
/** Test comment
*/
#if 0
/* tralala */
#endif
void f();
)",
R"(
/** Test comment
*/
#ifdef DOCS
template<typename T>
#endif
void f();
)",
R"(
/** Test comment
*/
#ifdef DOCS
template<typename T>
#endif
void f();
)",
};
for (const auto code : Sources) {
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
ASTContext &Ctx = AST->getASTContext();
auto const *F = selectFirst<FunctionDecl>(
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
ASSERT_NE(F, nullptr);
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
ASSERT_NE(C, nullptr);
EXPECT_EQ(C->getRawText(Ctx.getSourceManager()),
"/** Test comment\n */");
}
}
TEST(Decl, CommentsAttachedToDecl3) {
const SmallVector<StringRef> Sources{
R"(
/// @brief Test comment
void f();
)",
R"(
/// @brief Test comment
void f();
)",
R"(
/// @brief Test comment
#if 0
// tralala
#endif
void f();
)",
R"(
/// @brief Test comment
#if 0
// tralala
#endif
void f();
)",
R"(
/// @brief Test comment
#ifdef DOCS
template<typename T>
#endif
void f();
)",
R"(
/// @brief Test comment
#ifdef DOCS
template<typename T>
#endif
void f();
)",
};
for (const auto code : Sources) {
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
ASTContext &Ctx = AST->getASTContext();
auto const *F = selectFirst<FunctionDecl>(
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
ASSERT_NE(F, nullptr);
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
ASSERT_NE(C, nullptr);
EXPECT_EQ(C->getRawText(Ctx.getSourceManager()), "/// @brief Test comment");
}
}
TEST(Decl, CommentsAttachedToDecl4) {
const SmallVector<StringRef> Sources{
R"(
/** \brief Test comment
*/
void f();
)",
R"(
/** \brief Test comment
*/
void f();
)",
R"(
/** \brief Test comment
*/
#if 0
/* tralala */
#endif
void f();
)",
R"(
/** \brief Test comment
*/
#if 0
/* tralala */
#endif
void f();
)",
R"(
/** \brief Test comment
*/
#ifdef DOCS
template<typename T>
#endif
void f();
)",
R"(
/** \brief Test comment
*/
#ifdef DOCS
template<typename T>
#endif
void f();
)",
};
for (const auto code : Sources) {
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
ASTContext &Ctx = AST->getASTContext();
auto const *F = selectFirst<FunctionDecl>(
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
ASSERT_NE(F, nullptr);
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
ASSERT_NE(C, nullptr);
EXPECT_EQ(C->getRawText(Ctx.getSourceManager()),
"/** \\brief Test comment\n */");
}
}
/// This example intentionally inserts characters between a doc comment and the
/// associated declaration to verify that the comment does not become associated
/// with the FunctionDecl.
/// By default, Clang does not allow for other declarations (aside from
/// preprocessor directives, as shown above) to be placed between a doc comment
/// and a declaration.
TEST(Decl, CommentsAttachedToDecl5) {
const SmallVector<StringRef> Sources{
R"(
/// Test comment
;
void f();
)",
R"(
/// Test comment
// @
void f();
)",
R"(
/// Test comment
// {}
void f();
)",
};
for (const auto code : Sources) {
auto AST = tooling::buildASTFromCodeWithArgs(code, /*Args=*/{"-std=c++20"});
ASTContext &Ctx = AST->getASTContext();
auto const *F = selectFirst<FunctionDecl>(
"id", match(functionDecl(hasName("f")).bind("id"), Ctx));
ASSERT_NE(F, nullptr);
auto const *C = Ctx.getRawCommentForDeclNoCache(F);
ASSERT_EQ(C, nullptr);
}
}