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

• Applied Adrian's suggestion to move comments before the line they apply to.
• Got to 100% coverage by changing a test and making an assert for something I 
couldn't make happen in a test.

I did not take Adrian's suggestion to remove braces around a single-statement 
`if` because (as far as I can tell) the LLVM coding standard is silent on the 
topic and I prefer to have the braces there.


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,77 @@
 } // end namespace
 
 namespace {
+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 = llvm::dyn_cast<TagDecl>(To)) {
+      ToTag->setHasExternalLexicalStorage();
+    } else if (auto ToNamespace = llvm::dyn_cast<NamespaceDecl>(To)) {
+      ToNamespace->setHasExternalVisibleStorage();
+    }
+    return ASTImporter::Imported(From, To);
+  }
+};
+
+const DeclContext *LookupSameContext(const TranslationUnitDecl *SearchTU,
+                                     const DeclContext *SourceDC,
+                                     ASTImporter &SourceToSearchImporter) {
+  if (SourceDC->isTranslationUnit()) {
+    return SearchTU;
+  }
+  const DeclContext *SearchParentDC =
+      LookupSameContext(SearchTU, SourceDC->getParent(), SourceToSearchImporter);
+  if (!SearchParentDC) {
+    // If we couldn't find the parent DC in this TranslationUnit, give up.
+    return nullptr;
+  }
+  auto SourceNamedDecl = cast<NamedDecl>(SourceDC);
+  DeclarationName SourceName = SourceNamedDecl->getDeclName();
+  DeclarationName SearchName = SourceToSearchImporter.Import(SourceName);
+  DeclContext::lookup_result SearchResult = SearchParentDC->lookup(SearchName);
+  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 +271,88 @@
     }
   }
 
+  void ForEachMatchingDC(const DeclContext *DC,
+                         std::function<void(ASTImporter &ForwardImporter,
+                                            ASTImporter &ReverseImporter,
+                                            const DeclContext *SearchDC)>
+                             Callback) {
+    for (const std::unique_ptr<CompilerInstance> &I : ImportCIs) {
+      TranslationUnitDecl *SearchTU =
+          I->getASTContext().getTranslationUnitDecl();
+      ASTImporter &ForwardImporter = *ForwardImporters[I.get()];
+      ASTImporter &ReverseImporter = *ReverseImporters[I.get()];
+      const DeclContext *SearchDC =
+          LookupSameContext(SearchTU, DC, ReverseImporter);
+      if (SearchDC) {
+        Callback(ForwardImporter, ReverseImporter, SearchDC);
+      }
+    }
+  }
+
   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
                                       DeclarationName Name) override {
     llvm::SmallVector<NamedDecl *, 1> Decls;
 
-    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);
+    typedef std::pair<NamedDecl *, ASTImporter *> Candidate;
+
+    std::vector<Candidate> CompleteDecls;
+    std::vector<Candidate> ForwardDecls;
+
+    auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) {
+      if (IsForwardDeclaration(C.first)) {
+        if (std::none_of(ForwardDecls.begin(), ForwardDecls.end(),
+                         [&C](Candidate &D) {
+                           return C.first->getKind() == D.first->getKind();
+                         })) {
+          ForwardDecls.push_back(C);
         }
+      } else {
+        CompleteDecls.push_back(C);
       }
-    }
-    if (Decls.empty()) {
+    };
+
+    ForEachMatchingDC(
+        DC, [Name, &FilterFoundDecl](ASTImporter &ForwardImporter,
+                                     ASTImporter &ReverseImporter,
+                                     const DeclContext *SearchDC) {
+          DeclarationName FromName = ReverseImporter.Import(Name);
+          DeclContextLookupResult Result = SearchDC->lookup(FromName);
+          for (NamedDecl *FromD : Result) {
+            FilterFoundDecl(std::make_pair(FromD, &ForwardImporter));
+          }
+        });
+
+    std::vector<Candidate> &DeclsToReport =
+        CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
+
+    if (DeclsToReport.empty()) {
       return false;
-    } else {
-      SetExternalVisibleDeclsForName(DC, Name, Decls);
-      return true;
     }
+
+    Decls.resize(DeclsToReport.size());
+    std::transform(DeclsToReport.begin(), DeclsToReport.end(), Decls.begin(),
+                   [](Candidate &C) {
+                     return llvm::cast<NamedDecl>(C.second->Import(C.first));
+                   });
+    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,
+                                             const DeclContext *SearchDC) {
+      for (Decl *SearchDecl : SearchDC->decls()) {
+        if (IsKindWeWant(SearchDecl->getKind())) {
+          Decl *ImportedDecl = ForwardImporter.Import(SearchDecl);
+          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