This is an archive of the discontinued LLVM Phabricator instance.

[clang] Refactor how are doc comments attached to Decls
ClosedPublic

Authored by jkorous on Jul 25 2019, 3:37 PM.

Details

Summary
  • Add ASTContext::searchForDocComments so we don't have to load external comments in Sema::ActOnDocumentableDecls when trying to attach existing doc comments to newly parsed Decls.
  • Keep comments ordered and cache their decomposed locations.

This noticeably improves performance of code completion when using large modules with doc comments.

Diff Detail

Event Timeline

jkorous created this revision.Jul 25 2019, 3:37 PM

Not a complete review, but sending out the comments I have so far.

clang/include/clang/AST/ASTContext.h
806

"attachCommentsToJustParsedDecls"?

clang/include/clang/AST/RawCommentList.h
202–209

"... in case there are no comments in ..."

219

s/FileId hash/FileId/

clang/lib/AST/ASTContext.cpp
268

Please add a blank line between functions.

270

Please un-abbrevieate "search".

Also maybe call it "DeclLoc"?

456

We don't care about VS2015 anymore. https://reviews.llvm.org/D64326

clang/lib/AST/RawCommentList.cpp
289–290

Please move this comment down, right before the if statement that implement this logic.

319–320

No need to parenthesize.

329

I don't understand what you mean by "slow path".

334

No need to parenthesize.

clang/lib/Sema/SemaDecl.cpp
12729–12730

s/D/d/

12731

Also macros. (However I do agree with you that we can ignore this case.)

12737

Would it be better to move this logic into searchForDocComments? It seems like it belongs there. That function already computes CommentsInThisFile etc.

clang/lib/Serialization/ASTReader.cpp
9733

Wouldn't it be faster to directly modify Context.Comments.OrderedComments?

jkorous marked 15 inline comments as done.Aug 5 2019, 3:08 PM
jkorous added inline comments.
clang/include/clang/AST/ASTContext.h
806

Sounds good - let's just finish the discussion about moving the logic from Sema::ActOnDocumentableDecls to this method first.

clang/lib/AST/RawCommentList.cpp
329

The comment is no longer relevant. Thanks!

clang/lib/Sema/SemaDecl.cpp
12731

You're absolutely right! I added a FIXME.

12737

I was asking myself the same thing.

We can move the logic but then we'd have to change semantics of ASTContext::searchForDocComments - essentially documenting that it makes sense to be called only from Sema::ActOnDocumentableDecls context.

I don't have a strong preference but I'm worried that it would be kind of weird interface.

WDYT?

jkorous updated this revision to Diff 213474.Aug 5 2019, 3:10 PM
jkorous marked 2 inline comments as done.

Addressed feedback (comments, naming).

Finished the review. I like this approach a lot.

clang/lib/AST/ASTContext.cpp
448

cacheRawCommentForDecl

We don't know that it is a doc comment (it could be an ordinary comment when ParseAllComments is true), and "data" in the name does not explain anything.

463

Should it be setOriginalDecl(OriginalDeclForComment), like in ASTContext::getRawCommentForAnyRedecl?

Could you also call cacheDocCommentDataForDecl from ASTContext::getRawCommentForAnyRedecl?

468

cacheRawCommentForRedecls

486

Could you call cacheDocCommentDataForRedecls from ASTContext::getRawCommentForAnyRedecl?

clang/lib/Sema/SemaDecl.cpp
12737

I think changing the name and semantics like that would be an improvement in clarity. I don't think it makes sense to call ASTContext::searchForDocComments in any other case anyway -- users who want to retrieve the comment should be calling ASTContext::getRawCommentForAnyRedecl.

jkorous updated this revision to Diff 214026.Aug 7 2019, 4:11 PM
jkorous marked 3 inline comments as done.

Rewrite caching of Decl -> RawComment mapping.

jkorous marked an inline comment as done.Aug 7 2019, 4:16 PM

I still have to do the searchForDocComments -> attachCommentsToJustParsedDecls change.

clang/lib/AST/ASTContext.cpp
463

Well, turned out this was a spot on comment!

I started by explaining the use NoCommentInDecl and why this change is fine and realized we can save some memory and make the code (arguably) simpler. I ended up rewriting the caching completely.

jkorous updated this revision to Diff 214034.Aug 7 2019, 4:42 PM

searchForDocComments() -> attachCommentsToJustParsedDecls()

jkorous marked 4 inline comments as done.Aug 7 2019, 4:44 PM
gribozavr added inline comments.Aug 8 2019, 9:47 AM
clang/lib/AST/ASTContext.cpp
370

Is it possible for D to be a null pointer? adjustDeclToTemplate does a dyn_cast on D, which would crash if D was null.

396

return DeclRawComments.find(RedeclComment->second)->second; might be slightly better, because it will detect coding errors -- it will catch the case when DeclRawComments does not have an entry for that decl. The square bracket syntax will insert a null entry silently.

430

I like the new approach a lot. The last loop is tricky, but I do think it is an improvement.

439

Why not retrieve the canonical decl inside the cacheRawCommentForDecl from OriginalD?

466

Indentation is off.

505

Are there cases when canonical decl is null?..

clang/lib/Sema/SemaDecl.cpp
12747

I think this FIXME should be sunk down into attachCommentsToJustParsedDecls, because it relates to the implementation of that function.

clang/lib/Serialization/ASTReader.cpp
9733

So what about this point?

jkorous marked 15 inline comments as done.Aug 8 2019, 1:53 PM
jkorous added inline comments.
clang/lib/AST/ASTContext.cpp
370

You're right. I moved the check above the adjustment and changed interface of adjustDeclToTemplate to make it obvious that != NULL is expected of input and guaranteed for output.

396

Good point!

430

I agree. I don't think we're doing any rocket science here so the code should be easy to understand.

439

You are right, this is premature optimization.

//  - The first element is also often called the canonical element. Every
//    element has a pointer to it so that "getCanonical" can be fast.
...
class Redeclarable
505

IIUC correctly there are no such cases at the moment just that the interface doesn't guarantee that. But it seems like we don't expect that possibility anywhere in clang.

clang/lib/Sema/SemaDecl.cpp
12747

I've put it as a requirement to attachCommentsToJustParsedDecls doc comment. Since we're violating it here I'd leave the FIXME also here.

Or did you mean that I shouldn't be expecting that in the first place?

clang/lib/Serialization/ASTReader.cpp
9733

Oh, absolutely. Thanks for reminding me!

jkorous updated this revision to Diff 214226.Aug 8 2019, 1:54 PM
jkorous marked 6 inline comments as done.

Addressed comments & clang-formatted the patch.

gribozavr added inline comments.Aug 8 2019, 11:24 PM
clang/lib/AST/ASTContext.cpp
345

Why add a null check?

352

Why null check?

370

But why even add a null check at all? The contract of this function is that D is never null.

396

No need to. Dereferencing the end iterator is undefined behavior, which is sufficient to find the problem in sanitizer builds.

398

Please don't add code after llvm_unreachable. We don't do defensive programming in LLVM/Clang.

clang/lib/Sema/SemaDecl.cpp
12747

What I meant is that the relevant logic (that is violating the expectation, and should be eventually fixed) is in attachCommentsToJustParsedDecls, therefore, the FIXME belongs there, not in the caller. There isn't much a caller can do about the problem. Also, when the problem will get fixed, I doubt someone will look at the callsite for FIXMEs.

clang/test/Index/comment-redeclarations.cpp
15 ↗(On Diff #214226)

Please add a newline.

jkorous marked 8 inline comments as done.Aug 9 2019, 1:33 PM
jkorous added inline comments.
clang/lib/AST/ASTContext.cpp
345

You're right, nullptr can't be returned here.

352

You're right, nullptr can't be returned here.

370

I am not sure what you mean. "D is never null" isn't explicitly stated in the ASTContext.h header - do you mean that it's implied by the interface & doc comment of ASTContext::getRawCommentForAnyRedecl?

It seems to me that we should either

  • Explicitly mention this in the header file and add an assert here.

or

  • Handle nullptr value here.
396

Arguably debug builds are more common than sanitized builds so I'd rather not rely on sanitizer being used.

clang/lib/Sema/SemaDecl.cpp
12747

Sorry, I don't understand what you mean by:

relevant logic (that is violating the expectation, and should be eventually fixed)

The way I understand it is that attachCommentsToJustParsedDecls states the expectation in its doc comment

/// Requirement: All \p Decls are in the same file.

and it's up to a caller to satisfy it, which isn't something Sema::ActOnDocumentableDecls does.

Are you saying that attachCommentsToJustParsedDecls should pretend it's more generic than that and admit it's cheating by FIXME in its implementation?

jkorous updated this revision to Diff 214443.Aug 9 2019, 1:34 PM
jkorous marked 2 inline comments as done.

Addressed comments

gribozavr accepted this revision.Aug 12 2019, 1:34 AM

Very nice improvement! Thank you!

This revision is now accepted and ready to land.Aug 12 2019, 1:34 AM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptAug 13 2019, 11:10 AM
ivanmurashko added inline comments.
cfe/trunk/lib/Serialization/ASTReader.cpp
9735 ↗(On Diff #214886)

The var has never been used and can be removed

Herald added a project: Restricted Project. · View Herald TranscriptMar 10 2022, 2:32 PM