spyffe updated this revision to Diff 93721.
spyffe added a comment.

• Removed namespace qualification of `cast` across the board.
• Standardized on `SmallVector`
• Factored out the filtering of forward declarations
• Fixed a loop as requested.
• Made a Origin<> wrapper for arbitrary AST objects that makes it clear where 
they live, so importation and searching gets a little clearer.


Repository:
  rL LLVM

https://reviews.llvm.org/D30435

Files:
  test/Import/forward-declared-struct/Inputs/S1.c
  test/Import/forward-declared-struct/Inputs/S2.c
  test/Import/forward-declared-struct/test.c
  test/Import/member-in-struct/Inputs/S.c
  test/Import/member-in-struct/test.c
  test/Import/multiple-forward-declarations/Inputs/S1.c
  test/Import/multiple-forward-declarations/Inputs/S2.c
  test/Import/multiple-forward-declarations/test.c
  test/Import/overloaded-function/Inputs/F1.c
  test/Import/overloaded-function/Inputs/F2.c
  test/Import/overloaded-function/test.c
  test/Import/struct-in-namespace/Inputs/N1.cpp
  test/Import/struct-in-namespace/Inputs/N2.cpp
  test/Import/struct-in-namespace/Inputs/N3.cpp
  test/Import/struct-in-namespace/test.cpp
  test/Import/template-specialization/Inputs/T.cpp
  test/Import/template-specialization/test.cpp
  tools/clang-import-test/clang-import-test.cpp

Index: tools/clang-import-test/clang-import-test.cpp
===================================================================
--- tools/clang-import-test/clang-import-test.cpp
+++ tools/clang-import-test/clang-import-test.cpp
@@ -9,6 +9,7 @@
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTImporter.h"
+#include "clang/AST/DeclObjC.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceLocation.h"
@@ -189,19 +190,90 @@
 } // end namespace
 
 namespace {
+
+template <typename T> struct Source {
+  T t;
+  Source(T &&t) : t(std::move(t)) {}
+  operator T() { return t; }
+  template <typename U = T> U &get() { return t; }
+  template <typename U = T> const U &get() const { return t; }
+  template <typename U> operator Source<U>() { return Source<U>(t); }
+};
+
+typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
+
+class TestASTImporter : public ASTImporter {
+public:
+  TestASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
+                  ASTContext &FromContext, FileManager &FromFileManager,
+                  bool MinimalImport)
+      : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
+                    MinimalImport) {}
+  Decl *Imported(Decl *From, Decl *To) override {
+    if (auto ToTag = dyn_cast<TagDecl>(To)) {
+      ToTag->setHasExternalLexicalStorage();
+    } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) {
+      ToNamespace->setHasExternalVisibleStorage();
+    }
+    return ASTImporter::Imported(From, To);
+  }
+};
+
+Source<const DeclContext *>
+LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
+                  ASTImporter &ReverseImporter) {
+  if (DC->isTranslationUnit()) {
+    return SourceTU;
+  }
+  Source<const DeclContext *> SourceParentDC =
+      LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
+  if (!SourceParentDC) {
+    // If we couldn't find the parent DC in this TranslationUnit, give up.
+    return nullptr;
+  }
+  auto ND = cast<NamedDecl>(DC);
+  DeclarationName Name = ND->getDeclName();
+  Source<DeclarationName> SourceName = ReverseImporter.Import(Name);
+  DeclContext::lookup_result SearchResult =
+      SourceParentDC.get()->lookup(SourceName.get());
+  size_t SearchResultSize = SearchResult.size();
+  // Handle multiple candidates once we have a test for it.
+  // This may turn up when we import template specializations correctly.
+  assert(SearchResultSize < 2);
+  if (SearchResultSize == 0) {
+    // couldn't find the name, so we have to give up
+    return nullptr;
+  } else {
+    NamedDecl *SearchResultDecl = SearchResult[0];
+    return dyn_cast<DeclContext>(SearchResultDecl);
+  }
+}
+
+bool IsForwardDeclaration(Decl *D) {
+  assert(!isa<ObjCInterfaceDecl>(D)); // TODO handle this case
+  if (auto TD = dyn_cast<TagDecl>(D)) {
+    return !TD->isThisDeclarationADefinition();
+  } else if (auto FD = dyn_cast<FunctionDecl>(D)) {
+    return !FD->isThisDeclarationADefinition();
+  } else {
+    return false;
+  }
+}
+
 class TestExternalASTSource : public ExternalASTSource {
 private:
   llvm::ArrayRef<std::unique_ptr<CompilerInstance>> ImportCIs;
-  std::map<CompilerInstance *, std::unique_ptr<ASTImporter>> ForwardImporters;
+  std::map<CompilerInstance *, std::unique_ptr<TestASTImporter>>
+      ForwardImporters;
   std::map<CompilerInstance *, std::unique_ptr<ASTImporter>> ReverseImporters;
 
 public:
   TestExternalASTSource(
       CompilerInstance &ExpressionCI,
       llvm::ArrayRef<std::unique_ptr<CompilerInstance>> ImportCIs)
       : ImportCIs(ImportCIs) {
     for (const std::unique_ptr<CompilerInstance> &ImportCI : ImportCIs) {
-      ForwardImporters[ImportCI.get()] = llvm::make_unique<ASTImporter>(
+      ForwardImporters[ImportCI.get()] = llvm::make_unique<TestASTImporter>(
           ExpressionCI.getASTContext(), ExpressionCI.getFileManager(),
           ImportCI->getASTContext(), ImportCI->getFileManager(),
           /*MinimalImport=*/true);
@@ -212,29 +284,93 @@
     }
   }
 
+  void
+  ForEachMatchingDC(const DeclContext *DC,
+                    std::function<void(ASTImporter &ForwardImporter,
+                                       ASTImporter &ReverseImporter,
+                                       Source<const DeclContext *> SourceDC)>
+                        Callback) {
+    for (const std::unique_ptr<CompilerInstance> &I : ImportCIs) {
+      Source<TranslationUnitDecl *> SourceTU(
+          I->getASTContext().getTranslationUnitDecl());
+      ASTImporter &ForwardImporter = *ForwardImporters[I.get()];
+      ASTImporter &ReverseImporter = *ReverseImporters[I.get()];
+      Source<const DeclContext *> SourceDC =
+          LookupSameContext(SourceTU, DC, ReverseImporter);
+      if (SourceDC.get()) {
+        Callback(ForwardImporter, ReverseImporter, SourceDC);
+      }
+    }
+  }
+
+  static bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls,
+                                const Candidate &C) {
+    return std::any_of(Decls.begin(), Decls.end(), [&C](const Candidate &D) {
+      return C.first.get()->getKind() == D.first.get()->getKind();
+    });
+  }
+
   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
                                       DeclarationName Name) override {
     llvm::SmallVector<NamedDecl *, 1> Decls;
+    llvm::SmallVector<Candidate, 4> CompleteDecls;
+    llvm::SmallVector<Candidate, 4> ForwardDecls;
 
-    if (isa<TranslationUnitDecl>(DC)) {
-      for (const std::unique_ptr<CompilerInstance> &I : ImportCIs) {
-        DeclarationName FromName = ReverseImporters[I.get()]->Import(Name);
-        DeclContextLookupResult Result =
-            I->getASTContext().getTranslationUnitDecl()->lookup(FromName);
-        for (NamedDecl *FromD : Result) {
-          NamedDecl *D =
-              llvm::cast<NamedDecl>(ForwardImporters[I.get()]->Import(FromD));
-          Decls.push_back(D);
+    auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) {
+      if (IsForwardDeclaration(C.first.get())) {
+        if (!HasDeclOfSameType(ForwardDecls, C)) {
+          ForwardDecls.push_back(C);
         }
+      } else {
+        CompleteDecls.push_back(C);
       }
-    }
-    if (Decls.empty()) {
+    };
+
+    ForEachMatchingDC(
+        DC, [Name, &FilterFoundDecl](ASTImporter &ForwardImporter,
+                                     ASTImporter &ReverseImporter,
+                                     Source<const DeclContext *> SourceDC) {
+          DeclarationName FromName = ReverseImporter.Import(Name);
+          DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
+          for (NamedDecl *FromD : Result) {
+            FilterFoundDecl(std::make_pair(FromD, &ForwardImporter));
+          }
+        });
+
+    llvm::ArrayRef<Candidate> DeclsToReport =
+        CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
+
+    if (DeclsToReport.empty()) {
       return false;
-    } else {
-      SetExternalVisibleDeclsForName(DC, Name, Decls);
-      return true;
     }
+
+    Decls.reserve(DeclsToReport.size());
+    for (const Candidate &C : DeclsToReport) {
+      NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get()));
+      assert(d);
+      Decls.push_back(d);
+    }
+    SetExternalVisibleDeclsForName(DC, Name, Decls);
+    return true;
   }
+
+  void
+  FindExternalLexicalDecls(const DeclContext *DC,
+                           llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+                           SmallVectorImpl<Decl *> &Result) override {
+    ForEachMatchingDC(
+        DC, [DC, IsKindWeWant](ASTImporter &ForwardImporter,
+                               ASTImporter &ReverseImporter,
+                               Source<const DeclContext *> SourceDC) {
+          for (Source<const Decl *> SourceDecl : SourceDC.get()->decls()) {
+            if (IsKindWeWant(SourceDecl.get()->getKind())) {
+              Decl *ImportedDecl =
+                  ForwardImporter.Import(const_cast<Decl *>(SourceDecl.get()));
+              assert(ImportedDecl->getDeclContext() == DC);
+            }
+          }
+        });
+  }
 };
 
 void AddExternalSource(
Index: test/Import/template-specialization/test.cpp
===================================================================
--- test/Import/template-specialization/test.cpp
+++ test/Import/template-specialization/test.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-import-test -import %S/Inputs/T.cpp -expression %s
+// XFAIL: *
+void expr() {
+  A<int>::B b1;
+  A<bool>::B b2;
+  b1.f + b2.g;
+}
Index: test/Import/template-specialization/Inputs/T.cpp
===================================================================
--- test/Import/template-specialization/Inputs/T.cpp
+++ test/Import/template-specialization/Inputs/T.cpp
@@ -0,0 +1,14 @@
+template <typename T> struct A {
+};
+
+template <> struct A<int> {
+  struct B {
+    int f;
+  };
+};
+
+template <> struct A<bool> {
+  struct B {
+    int g;
+  };
+};
Index: test/Import/struct-in-namespace/test.cpp
===================================================================
--- test/Import/struct-in-namespace/test.cpp
+++ test/Import/struct-in-namespace/test.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-import-test -import %S/Inputs/N1.cpp -import %S/Inputs/N2.cpp -import %S/Inputs/N3.cpp -expression %s
+void expr() {
+  N::S s;
+  N::T t;
+  N::U u;
+  int d = s.a + t.b + u.c;
+}
Index: test/Import/struct-in-namespace/Inputs/N3.cpp
===================================================================
--- test/Import/struct-in-namespace/Inputs/N3.cpp
+++ test/Import/struct-in-namespace/Inputs/N3.cpp
@@ -0,0 +1,5 @@
+namespace M {
+  struct V {
+    int d;
+  };
+}
Index: test/Import/struct-in-namespace/Inputs/N2.cpp
===================================================================
--- test/Import/struct-in-namespace/Inputs/N2.cpp
+++ test/Import/struct-in-namespace/Inputs/N2.cpp
@@ -0,0 +1,5 @@
+namespace N {
+  struct U {
+    int c;
+  };
+}
Index: test/Import/struct-in-namespace/Inputs/N1.cpp
===================================================================
--- test/Import/struct-in-namespace/Inputs/N1.cpp
+++ test/Import/struct-in-namespace/Inputs/N1.cpp
@@ -0,0 +1,11 @@
+namespace N {
+  struct S {
+    int a;
+  };
+}
+
+namespace N {
+  struct T {
+    int b;
+  };
+}
Index: test/Import/overloaded-function/test.c
===================================================================
--- test/Import/overloaded-function/test.c
+++ test/Import/overloaded-function/test.c
@@ -0,0 +1,7 @@
+// RUN: clang-import-test -import %S/Inputs/F1.c -import %S/Inputs/F2.c -expression %s
+void expr() {
+  f(2);
+  f("world");
+  S s;
+  f(s);
+}
Index: test/Import/overloaded-function/Inputs/F2.c
===================================================================
--- test/Import/overloaded-function/Inputs/F2.c
+++ test/Import/overloaded-function/Inputs/F2.c
@@ -0,0 +1,4 @@
+struct S { int a; };
+
+void f(const char *arg) { }
+void f(S arg) { }
Index: test/Import/overloaded-function/Inputs/F1.c
===================================================================
--- test/Import/overloaded-function/Inputs/F1.c
+++ test/Import/overloaded-function/Inputs/F1.c
@@ -0,0 +1 @@
+void f(int arg) { }
Index: test/Import/multiple-forward-declarations/test.c
===================================================================
--- test/Import/multiple-forward-declarations/test.c
+++ test/Import/multiple-forward-declarations/test.c
@@ -0,0 +1,4 @@
+// RUN: clang-import-test -import %S/Inputs/S1.c --import %S/Inputs/S2.c -expression %s
+void expr() {
+  struct S *MySPtr;
+}
Index: test/Import/multiple-forward-declarations/Inputs/S2.c
===================================================================
--- test/Import/multiple-forward-declarations/Inputs/S2.c
+++ test/Import/multiple-forward-declarations/Inputs/S2.c
@@ -0,0 +1 @@
+struct S;
Index: test/Import/multiple-forward-declarations/Inputs/S1.c
===================================================================
--- test/Import/multiple-forward-declarations/Inputs/S1.c
+++ test/Import/multiple-forward-declarations/Inputs/S1.c
@@ -0,0 +1 @@
+struct S;
Index: test/Import/member-in-struct/test.c
===================================================================
--- test/Import/member-in-struct/test.c
+++ test/Import/member-in-struct/test.c
@@ -0,0 +1,5 @@
+// RUN: clang-import-test -import %S/Inputs/S.c -expression %s
+void expr() {
+  struct S MyS;
+  MyS.a = 3;
+}
Index: test/Import/member-in-struct/Inputs/S.c
===================================================================
--- test/Import/member-in-struct/Inputs/S.c
+++ test/Import/member-in-struct/Inputs/S.c
@@ -0,0 +1,3 @@
+struct S {
+  int a;
+};
Index: test/Import/forward-declared-struct/test.c
===================================================================
--- test/Import/forward-declared-struct/test.c
+++ test/Import/forward-declared-struct/test.c
@@ -0,0 +1,5 @@
+// RUN: clang-import-test -import %S/Inputs/S1.c --import %S/Inputs/S2.c -expression %s
+void expr() {
+  struct S MyS;
+  MyS.a = 3;
+}
Index: test/Import/forward-declared-struct/Inputs/S2.c
===================================================================
--- test/Import/forward-declared-struct/Inputs/S2.c
+++ test/Import/forward-declared-struct/Inputs/S2.c
@@ -0,0 +1,3 @@
+struct S {
+  int a;
+};
Index: test/Import/forward-declared-struct/Inputs/S1.c
===================================================================
--- test/Import/forward-declared-struct/Inputs/S1.c
+++ test/Import/forward-declared-struct/Inputs/S1.c
@@ -0,0 +1 @@
+struct S;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to