This is an archive of the discontinued LLVM Phabricator instance.

[clang][CrossTU] Invalidate parent map after get cross TU definition.
ClosedPublic

Authored by balazske on Jun 25 2020, 8:49 AM.

Details

Summary

Parent map of ASTContext is built once. If this happens and later
the TU is modified by getCrossTUDefinition the parent map does not
contain the newly imported objects and has to be re-created.

Invalidation of the parent map is added to the CrossTranslationUnitContext.
It could be added to ASTImporter as well but for now this task remains the
responsibility of the user of ASTImporter. Reason for this is mostly that
ASTImporter calls itself recursively.

Diff Detail

Event Timeline

balazske created this revision.Jun 25 2020, 8:49 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 25 2020, 8:49 AM
gamesh411 accepted this revision.Jun 26 2020, 11:44 AM

I have found this in ASTContext.h:

// A traversal scope limits the parts of the AST visible to certain analyses.
   // RecursiveASTVisitor::TraverseAST will only visit reachable nodes, and
   // getParents() will only observe reachable parent edges.
   //
   // The scope is defined by a set of "top-level" declarations.
   // Initially, it is the entire TU: {getTranslationUnitDecl()}.
   // Changing the scope clears the parent cache, which is expensive to rebuild.
   std::vector<Decl *> getTraversalScope() const { return TraversalScope; }

The setTraversalScope resets the parentmap in ASTContext.cpp:

void ASTContext::setTraversalScope(const std::vector<Decl *> &TopLevelDecls) {
   TraversalScope = TopLevelDecls;
   getParentMapContext().clear();
 }

It seems to me that not resetting this cache could very well cause a bad AST being available.
Just curious: Is there an example that you are aware of, where this caused an actual problem?

This revision is now accepted and ready to land.Jun 26 2020, 11:44 AM

I did not found problems related to traversal scope. At AST import Decl's are added only, but the existing ones should remain valid. So the top-level decls in TraversalScope should remain valid after import.

martong added inline comments.Jun 30 2020, 4:48 AM
clang/lib/CrossTU/CrossTranslationUnit.cpp
723

... the TU is modified by getCrossTUDefinition the parent map does not

contain the newly imported objects and has to be re-created.

I see we clear it here, but when/where will be the parent map re-created?

balazske marked an inline comment as done.Jun 30 2020, 7:20 AM
balazske added inline comments.
clang/lib/CrossTU/CrossTranslationUnit.cpp
723

It should be created at any access to it. (Actually I did not check how this works after the test showed that the fix works.)

balazske marked an inline comment as done.Jun 30 2020, 7:23 AM
balazske added inline comments.
clang/lib/CrossTU/CrossTranslationUnit.cpp
723

ASTContext::getParentMapContext does the job.

martong accepted this revision.Jun 30 2020, 12:01 PM

Ok, I checked and it seems the parent map context is used only by the AST matchers, and this is okay because it looks like there is not any storing or caching of the parent map objects (the type is never copied).

This revision was automatically updated to reflect the committed changes.
balazske marked an inline comment as done.Jul 1 2020, 6:38 AM
balazske added inline comments.
clang/lib/CrossTU/CrossTranslationUnit.cpp
723

More precisely, ParentMapContext::getParents re-creates the parent map after it was cleared. The parent maps in the ParentMapContext are cleared, not the parent map pointer in ASTContext.