[PATCH] D11069: Allow any comment to be a trailing comment when -fparse-all-comments is on.
Luke Zarko
zarko at google.com
Thu Jul 9 10:50:26 PDT 2015
zarko created this revision.
zarko added a subscriber: cfe-commits.
This helps with freeform documentation styles, where otherwise code like
```
enum class E {
E1, // D1
E2 // D2
};
```
would result in D1 being associated with E2. To properly associate E1
with D1 and E2 with D2, this patch allows all raw comments C such that
C.isParseAllComments() to participate in trailing comment checks inside
getRawCommentForDeclNoCache. This takes care of linking the intended
documentation with the intended decls. There remains an issue with code
like:
```
foo(); // DN
int x;
```
To prevent DN from being associated with x, this patch adds a new test
on preceding-line comments C (where C.isParseAllComments() and also
C's kind is RCK_OrdinaryBCPL or RCK_OrdinaryC) that checks whether C
is the first non-whitespace thing on C's starting line.
http://reviews.llvm.org/D11069
Files:
lib/AST/ASTContext.cpp
test/Index/parse-all-comments.c
Index: test/Index/parse-all-comments.c
===================================================================
--- test/Index/parse-all-comments.c
+++ test/Index/parse-all-comments.c
@@ -33,6 +33,9 @@
// WITH EMPTY LINE
void multi_line_comment_empty_line(int);
+int notdoxy7; // Not a Doxygen juxtaposed comment. notdoxy7 NOT_DOXYGEN
+int notdoxy8; // Not a Doxygen juxtaposed comment. notdoxy8 NOT_DOXYGEN
+
#endif
// RUN: rm -rf %t
@@ -60,3 +63,5 @@
// CHECK: parse-all-comments.c:22:6: FunctionDecl=isdoxy6:{{.*}} isdoxy6 IS_DOXYGEN_SINGLE
// CHECK: parse-all-comments.c:29:6: FunctionDecl=multi_line_comment_plus_ordinary:{{.*}} BLOCK_ORDINARY_COMMENT {{.*}} ORDINARY COMMENT {{.*}} IS_DOXYGEN_START {{.*}} IS_DOXYGEN_END
// CHECK: parse-all-comments.c:34:6: FunctionDecl=multi_line_comment_empty_line:{{.*}} MULTILINE COMMENT{{.*}}\n{{.*}}\n{{.*}} WITH EMPTY LINE
+// CHECK: parse-all-comments.c:36:5: VarDecl=notdoxy7:{{.*}} notdoxy7 NOT_DOXYGEN
+// CHECK: parse-all-comments.c:37:5: VarDecl=notdoxy8:{{.*}} notdoxy8 NOT_DOXYGEN
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -60,6 +60,33 @@
HalfRank, FloatRank, DoubleRank, LongDoubleRank
};
+/// \brief Determines whether there is only whitespace in `Buffer` between `P`
+/// and the previous line.
+/// \param Buffer The buffer to search in.
+/// \param P The offset from the beginning of `Buffer` to start from.
+/// \return true if all of the characters in `Buffer` ranging from the closest
+/// line-ending character before `P` (or the beginning of `Buffer`) to `P - 1`
+/// are whitespace.
+static bool OnlyWhitespaceOnLineBefore(const char *Buffer, unsigned P) {
+ // Search backwards until we see linefeed or carriage return.
+ for (unsigned I = P; I != 0; --I) {
+ switch (Buffer[I - 1]) {
+ default:
+ return false;
+ case ' ':
+ case '\t':
+ case '\f':
+ case '\v':
+ break;
+ case '\r':
+ case '\n':
+ return true;
+ }
+ }
+ // We hit the beginning of the buffer.
+ return true;
+}
+
RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
if (!CommentsLoaded && ExternalSource) {
ExternalSource->ReadComments();
@@ -203,7 +230,8 @@
// First check whether we have a trailing comment.
if (Comment != RawComments.end() &&
- (*Comment)->isDocumentation() && (*Comment)->isTrailingComment() &&
+ ((*Comment)->isParseAllComments() ||
+ ((*Comment)->isDocumentation() && (*Comment)->isTrailingComment())) &&
(isa<FieldDecl>(D) || isa<EnumConstantDecl>(D) || isa<VarDecl>(D) ||
isa<ObjCMethodDecl>(D) || isa<ObjCPropertyDecl>(D))) {
std::pair<FileID, unsigned> CommentBeginDecomp
@@ -224,6 +252,27 @@
return nullptr;
--Comment;
+ if ((*Comment)->isParseAllComments() &&
+ ((*Comment)->getKind() == RawComment::RCK_OrdinaryBCPL ||
+ (*Comment)->getKind() == RawComment::RCK_OrdinaryC)) {
+ // When we're trying to guess which comments are actually documentation
+ // comments and the previous comment was ordinary, assume that it's
+ // unrelated if it's not the first thing on its starting line. This may
+ // be a comment unrelated to anything, or it might be a trailing comment
+ // for a different Decl.
+ std::pair<FileID, unsigned> CommentBeginDecomp =
+ SourceMgr.getDecomposedLoc((*Comment)->getSourceRange().getBegin());
+ if (CommentBeginDecomp.second != 0) {
+ // We're spuriously OK if this was the first thing in the file.
+ bool Invalid = false;
+ const char *Buffer =
+ SourceMgr.getBufferData(CommentBeginDecomp.first, &Invalid).data();
+ if (Invalid ||
+ !OnlyWhitespaceOnLineBefore(Buffer, CommentBeginDecomp.second))
+ return nullptr;
+ }
+ }
+
// Check that we actually have a non-member Doxygen comment.
if (!(*Comment)->isDocumentation() || (*Comment)->isTrailingComment())
return nullptr;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D11069.29357.patch
Type: text/x-patch
Size: 4025 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150709/c6af569c/attachment.bin>
More information about the cfe-commits
mailing list