r.stahl created this revision.
r.stahl added reviewers: a.sidorin, klimek.
Herald added subscribers: cfe-commits, martong.

If an AST node is imported after a call to getParents in the ToCtx, it was no 
longer possible to retrieve its parents since the old results were cached.

Valid types for getParents:

- Decl, Stmt, NestedNameSpecifier: handled explicitly
- Type: not supported by ast importer
- TypeLoc: not imported
- NestedNameSpecifierLoc: calls import for NNS


Repository:
  rC Clang

https://reviews.llvm.org/D46940

Files:
  include/clang/AST/ASTContext.h
  lib/AST/ASTImporter.cpp
  unittests/AST/ASTImporterTest.cpp

Index: unittests/AST/ASTImporterTest.cpp
===================================================================
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -1431,6 +1431,36 @@
       MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
 }
 
+TEST_P(ASTImporterTestBase, ValidParents) {
+  // Create parent cache in To context.
+  Decl *PreTU = getTuDecl("struct S {};", Lang_CXX, "pre.cc");
+  RecordDecl *FromRD = FirstDeclMatcher<RecordDecl>().match(PreTU, recordDecl());
+  auto ToRD = cast<RecordDecl>(Import(FromRD, Lang_CXX));
+  auto &ToACtx = ToAST->getASTContext();
+  ToACtx.getParents(*ToRD);
+
+  Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
+  CompoundStmt *FromCS = FirstDeclMatcher<CompoundStmt>().match(FromTU,
+                                                                compoundStmt());
+  FunctionDecl *FromFD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
+                                                                functionDecl());
+
+  auto FromPs = FromFD->getASTContext().getParents(*FromCS);
+  ASSERT_TRUE(!FromPs.empty());
+  auto FromP = FromPs[0].get<FunctionDecl>();
+  EXPECT_EQ(FromP, FromFD);
+
+  auto ToFD = cast<FunctionDecl>(Import(FromFD, Lang_CXX));
+
+  Decl *ToTU = ToACtx.getTranslationUnitDecl();
+  auto ToCS = FirstDeclMatcher<CompoundStmt>().match(ToTU, compoundStmt());
+
+  auto ToPs = ToACtx.getParents(*ToCS);
+  ASSERT_TRUE(!ToPs.empty());
+  auto ToP = ToPs[0].get<FunctionDecl>();
+  EXPECT_EQ(ToP, ToFD);
+}
+
 INSTANTIATE_TEST_CASE_P(
     ParameterizedTests, ASTImporterTestBase,
     ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -6751,7 +6751,11 @@
   if (!FromE)
     return nullptr;
 
-  return cast_or_null<Expr>(Import(cast<Stmt>(FromE)));
+  auto ToE = cast_or_null<Expr>(Import(cast<Stmt>(FromE)));
+  if (ToE)
+    ToContext.invalidateParents();
+
+  return ToE;
 }
 
 Stmt *ASTImporter::Import(Stmt *FromS) {
@@ -6762,13 +6766,15 @@
   llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS);
   if (Pos != ImportedStmts.end())
     return Pos->second;
-  
+
   // Import the type
   ASTNodeImporter Importer(*this);
   Stmt *ToS = Importer.Visit(FromS);
   if (!ToS)
     return nullptr;
 
+  ToContext.invalidateParents();
+
   // Record the imported declaration.
   ImportedStmts[FromS] = ToS;
   return ToS;
@@ -6779,52 +6785,60 @@
     return nullptr;
 
   NestedNameSpecifier *prefix = Import(FromNNS->getPrefix());
+  NestedNameSpecifier *ToNNS = nullptr;
 
   switch (FromNNS->getKind()) {
   case NestedNameSpecifier::Identifier:
     if (IdentifierInfo *II = Import(FromNNS->getAsIdentifier())) {
-      return NestedNameSpecifier::Create(ToContext, prefix, II);
+      ToNNS = NestedNameSpecifier::Create(ToContext, prefix, II);
     }
-    return nullptr;
+    break;
 
   case NestedNameSpecifier::Namespace:
     if (auto *NS = 
             cast_or_null<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) {
-      return NestedNameSpecifier::Create(ToContext, prefix, NS);
+      ToNNS = NestedNameSpecifier::Create(ToContext, prefix, NS);
     }
-    return nullptr;
+    break;
 
   case NestedNameSpecifier::NamespaceAlias:
     if (auto *NSAD = 
           cast_or_null<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) {
-      return NestedNameSpecifier::Create(ToContext, prefix, NSAD);
+      ToNNS = NestedNameSpecifier::Create(ToContext, prefix, NSAD);
     }
-    return nullptr;
+    break;
 
   case NestedNameSpecifier::Global:
-    return NestedNameSpecifier::GlobalSpecifier(ToContext);
+    ToNNS = NestedNameSpecifier::GlobalSpecifier(ToContext);
+    break;
 
   case NestedNameSpecifier::Super:
     if (auto *RD =
             cast_or_null<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) {
-      return NestedNameSpecifier::SuperSpecifier(ToContext, RD);
+      ToNNS = NestedNameSpecifier::SuperSpecifier(ToContext, RD);
     }
-    return nullptr;
+    break;
 
   case NestedNameSpecifier::TypeSpec:
   case NestedNameSpecifier::TypeSpecWithTemplate: {
       QualType T = Import(QualType(FromNNS->getAsType(), 0u));
       if (!T.isNull()) {
         bool bTemplate = FromNNS->getKind() == 
                          NestedNameSpecifier::TypeSpecWithTemplate;
-        return NestedNameSpecifier::Create(ToContext, prefix, 
+        ToNNS = NestedNameSpecifier::Create(ToContext, prefix, 
                                            bTemplate, T.getTypePtr());
       }
+      break;
     }
-      return nullptr;
+
+  default:
+    llvm_unreachable("Invalid nested name specifier kind");
   }
 
-  llvm_unreachable("Invalid nested name specifier kind");
+  if (ToNNS)
+    ToContext.invalidateParents();
+
+  return ToNNS;
 }
 
 NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -633,6 +633,11 @@
 
   DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node);
 
+  void invalidateParents() {
+    ReleaseParentMapEntries();
+    PointerParents = nullptr;
+  }
+
   const clang::PrintingPolicy &getPrintingPolicy() const {
     return PrintingPolicy;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to