This revision was automatically updated to reflect the committed changes.
Closed by commit rL299976: [clang-import-test] Lookup inside contexts (authored 
by spyffe).

Changed prior to commit:
  https://reviews.llvm.org/D30435?vs=93929&id=94875#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D30435

Files:
  cfe/trunk/include/clang/AST/ExternalASTMerger.h
  cfe/trunk/lib/AST/CMakeLists.txt
  cfe/trunk/lib/AST/ExternalASTMerger.cpp
  cfe/trunk/test/Import/forward-declared-struct/Inputs/S1.c
  cfe/trunk/test/Import/forward-declared-struct/Inputs/S2.c
  cfe/trunk/test/Import/forward-declared-struct/test.c
  cfe/trunk/test/Import/member-in-struct/Inputs/S.c
  cfe/trunk/test/Import/member-in-struct/test.c
  cfe/trunk/test/Import/multiple-forward-declarations/Inputs/S1.c
  cfe/trunk/test/Import/multiple-forward-declarations/Inputs/S2.c
  cfe/trunk/test/Import/multiple-forward-declarations/test.c
  cfe/trunk/test/Import/overloaded-function/Inputs/F1.c
  cfe/trunk/test/Import/overloaded-function/Inputs/F2.c
  cfe/trunk/test/Import/overloaded-function/test.c
  cfe/trunk/test/Import/struct-in-namespace/Inputs/N1.cpp
  cfe/trunk/test/Import/struct-in-namespace/Inputs/N2.cpp
  cfe/trunk/test/Import/struct-in-namespace/Inputs/N3.cpp
  cfe/trunk/test/Import/struct-in-namespace/test.cpp
  cfe/trunk/test/Import/template-specialization/Inputs/T.cpp
  cfe/trunk/test/Import/template-specialization/test.cpp
  cfe/trunk/tools/clang-import-test/clang-import-test.cpp

Index: cfe/trunk/test/Import/multiple-forward-declarations/test.c
===================================================================
--- cfe/trunk/test/Import/multiple-forward-declarations/test.c
+++ cfe/trunk/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: cfe/trunk/test/Import/multiple-forward-declarations/Inputs/S2.c
===================================================================
--- cfe/trunk/test/Import/multiple-forward-declarations/Inputs/S2.c
+++ cfe/trunk/test/Import/multiple-forward-declarations/Inputs/S2.c
@@ -0,0 +1 @@
+struct S;
Index: cfe/trunk/test/Import/multiple-forward-declarations/Inputs/S1.c
===================================================================
--- cfe/trunk/test/Import/multiple-forward-declarations/Inputs/S1.c
+++ cfe/trunk/test/Import/multiple-forward-declarations/Inputs/S1.c
@@ -0,0 +1 @@
+struct S;
Index: cfe/trunk/test/Import/struct-in-namespace/Inputs/N3.cpp
===================================================================
--- cfe/trunk/test/Import/struct-in-namespace/Inputs/N3.cpp
+++ cfe/trunk/test/Import/struct-in-namespace/Inputs/N3.cpp
@@ -0,0 +1,5 @@
+namespace M {
+  struct V {
+    int d;
+  };
+}
Index: cfe/trunk/test/Import/struct-in-namespace/Inputs/N2.cpp
===================================================================
--- cfe/trunk/test/Import/struct-in-namespace/Inputs/N2.cpp
+++ cfe/trunk/test/Import/struct-in-namespace/Inputs/N2.cpp
@@ -0,0 +1,5 @@
+namespace N {
+  struct U {
+    int c;
+  };
+}
Index: cfe/trunk/test/Import/struct-in-namespace/Inputs/N1.cpp
===================================================================
--- cfe/trunk/test/Import/struct-in-namespace/Inputs/N1.cpp
+++ cfe/trunk/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: cfe/trunk/test/Import/struct-in-namespace/test.cpp
===================================================================
--- cfe/trunk/test/Import/struct-in-namespace/test.cpp
+++ cfe/trunk/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: cfe/trunk/test/Import/member-in-struct/Inputs/S.c
===================================================================
--- cfe/trunk/test/Import/member-in-struct/Inputs/S.c
+++ cfe/trunk/test/Import/member-in-struct/Inputs/S.c
@@ -0,0 +1,3 @@
+struct S {
+  int a;
+};
Index: cfe/trunk/test/Import/member-in-struct/test.c
===================================================================
--- cfe/trunk/test/Import/member-in-struct/test.c
+++ cfe/trunk/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: cfe/trunk/test/Import/template-specialization/Inputs/T.cpp
===================================================================
--- cfe/trunk/test/Import/template-specialization/Inputs/T.cpp
+++ cfe/trunk/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: cfe/trunk/test/Import/template-specialization/test.cpp
===================================================================
--- cfe/trunk/test/Import/template-specialization/test.cpp
+++ cfe/trunk/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: cfe/trunk/test/Import/overloaded-function/Inputs/F2.c
===================================================================
--- cfe/trunk/test/Import/overloaded-function/Inputs/F2.c
+++ cfe/trunk/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: cfe/trunk/test/Import/overloaded-function/Inputs/F1.c
===================================================================
--- cfe/trunk/test/Import/overloaded-function/Inputs/F1.c
+++ cfe/trunk/test/Import/overloaded-function/Inputs/F1.c
@@ -0,0 +1 @@
+void f(int arg) { }
Index: cfe/trunk/test/Import/overloaded-function/test.c
===================================================================
--- cfe/trunk/test/Import/overloaded-function/test.c
+++ cfe/trunk/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: cfe/trunk/test/Import/forward-declared-struct/test.c
===================================================================
--- cfe/trunk/test/Import/forward-declared-struct/test.c
+++ cfe/trunk/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: cfe/trunk/test/Import/forward-declared-struct/Inputs/S2.c
===================================================================
--- cfe/trunk/test/Import/forward-declared-struct/Inputs/S2.c
+++ cfe/trunk/test/Import/forward-declared-struct/Inputs/S2.c
@@ -0,0 +1,3 @@
+struct S {
+  int a;
+};
Index: cfe/trunk/test/Import/forward-declared-struct/Inputs/S1.c
===================================================================
--- cfe/trunk/test/Import/forward-declared-struct/Inputs/S1.c
+++ cfe/trunk/test/Import/forward-declared-struct/Inputs/S1.c
@@ -0,0 +1 @@
+struct S;
Index: cfe/trunk/lib/AST/CMakeLists.txt
===================================================================
--- cfe/trunk/lib/AST/CMakeLists.txt
+++ cfe/trunk/lib/AST/CMakeLists.txt
@@ -31,6 +31,7 @@
   ExprConstant.cpp
   ExprCXX.cpp
   ExprObjC.cpp
+  ExternalASTMerger.cpp
   ExternalASTSource.cpp
   InheritViz.cpp
   ItaniumCXXABI.cpp
Index: cfe/trunk/lib/AST/ExternalASTMerger.cpp
===================================================================
--- cfe/trunk/lib/AST/ExternalASTMerger.cpp
+++ cfe/trunk/lib/AST/ExternalASTMerger.cpp
@@ -0,0 +1,183 @@
+//===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the ExternalASTMerger, which vends a combination of
+//  ASTs from several different ASTContext/FileManager pairs
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExternalASTMerger.h"
+
+using namespace clang;
+
+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 LazyASTImporter : public ASTImporter {
+public:
+  LazyASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
+                  ASTContext &FromContext, FileManager &FromFileManager)
+      : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
+                    /*MinimalImport=*/true) {}
+  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;
+  }
+}
+
+void ForEachMatchingDC(
+    const DeclContext *DC,
+    llvm::ArrayRef<ExternalASTMerger::ImporterPair> Importers,
+    std::function<void(const ExternalASTMerger::ImporterPair &IP,
+                       Source<const DeclContext *> SourceDC)>
+        Callback) {
+  for (const ExternalASTMerger::ImporterPair &IP : Importers) {
+    Source<TranslationUnitDecl *> SourceTU(
+        IP.Forward->getFromContext().getTranslationUnitDecl());
+    Source<const DeclContext *> SourceDC =
+        LookupSameContext(SourceTU, DC, *IP.Reverse);
+    if (SourceDC.get()) {
+      Callback(IP, SourceDC);
+    }
+  }
+}
+
+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();
+  });
+}
+} // end namespace
+
+ExternalASTMerger::ExternalASTMerger(const ImporterEndpoint &Target,
+                                     llvm::ArrayRef<ImporterEndpoint> Sources) {
+  for (const ImporterEndpoint &S : Sources) {
+    Importers.push_back(
+        {llvm::make_unique<LazyASTImporter>(Target.AST, Target.FM, S.AST, S.FM),
+         llvm::make_unique<ASTImporter>(S.AST, S.FM, Target.AST, Target.FM,
+                                        /*MinimalImport=*/true)});
+  }
+}
+
+bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
+                                                       DeclarationName Name) {
+  llvm::SmallVector<NamedDecl *, 1> Decls;
+  llvm::SmallVector<Candidate, 4> CompleteDecls;
+  llvm::SmallVector<Candidate, 4> ForwardDecls;
+
+  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);
+    }
+  };
+
+  ForEachMatchingDC(DC, Importers, [Name, &FilterFoundDecl](
+                                       const ImporterPair &IP,
+                                       Source<const DeclContext *> SourceDC) {
+    DeclarationName FromName = IP.Reverse->Import(Name);
+    DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
+    for (NamedDecl *FromD : Result) {
+      FilterFoundDecl(std::make_pair(FromD, IP.Forward.get()));
+    }
+  });
+
+  llvm::ArrayRef<Candidate> DeclsToReport =
+      CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
+
+  if (DeclsToReport.empty()) {
+    return false;
+  }
+
+  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 ExternalASTMerger::FindExternalLexicalDecls(
+    const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+    SmallVectorImpl<Decl *> &Result) {
+  ForEachMatchingDC(
+      DC, Importers, [DC, IsKindWeWant](const ImporterPair &IP,
+                                        Source<const DeclContext *> SourceDC) {
+        for (Source<const Decl *> SourceDecl : SourceDC.get()->decls()) {
+          if (IsKindWeWant(SourceDecl.get()->getKind())) {
+            Decl *ImportedDecl =
+                IP.Forward->Import(const_cast<Decl *>(SourceDecl.get()));
+            assert(ImportedDecl->getDeclContext() == DC);
+          }
+        }
+      });
+}
Index: cfe/trunk/tools/clang-import-test/clang-import-test.cpp
===================================================================
--- cfe/trunk/tools/clang-import-test/clang-import-test.cpp
+++ cfe/trunk/tools/clang-import-test/clang-import-test.cpp
@@ -9,6 +9,8 @@
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTImporter.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExternalASTMerger.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceLocation.h"
@@ -189,61 +191,18 @@
 } // end namespace
 
 namespace {
-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<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>(
-          ExpressionCI.getASTContext(), ExpressionCI.getFileManager(),
-          ImportCI->getASTContext(), ImportCI->getFileManager(),
-          /*MinimalImport=*/true);
-      ReverseImporters[ImportCI.get()] = llvm::make_unique<ASTImporter>(
-          ImportCI->getASTContext(), ImportCI->getFileManager(),
-          ExpressionCI.getASTContext(), ExpressionCI.getFileManager(),
-          /*MinimalImport=*/true);
-    }
-  }
-
-  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);
-        }
-      }
-    }
-    if (Decls.empty()) {
-      return false;
-    } else {
-      SetExternalVisibleDeclsForName(DC, Name, Decls);
-      return true;
-    }
-  }
-};
-
+ 
 void AddExternalSource(
     CompilerInstance &CI,
     llvm::ArrayRef<std::unique_ptr<CompilerInstance>> Imports) {
-  ASTContext &AST = CI.getASTContext();
-  auto ES = llvm::make_unique<TestExternalASTSource>(CI, Imports);
-  AST.setExternalSource(ES.release());
-  AST.getTranslationUnitDecl()->setHasExternalVisibleStorage();
+  ExternalASTMerger::ImporterEndpoint Target({CI.getASTContext(), CI.getFileManager()});
+  llvm::SmallVector<ExternalASTMerger::ImporterEndpoint, 3> Sources;
+  for (const std::unique_ptr<CompilerInstance> &CI : Imports) {
+    Sources.push_back({CI->getASTContext(), CI->getFileManager()});
+  }
+  auto ES = llvm::make_unique<ExternalASTMerger>(Target, Sources);
+  CI.getASTContext().setExternalSource(ES.release());
+  CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage();
 }
 
 llvm::Error ParseSource(const std::string &Path, CompilerInstance &CI,
@@ -292,6 +251,7 @@
     return std::move(CI);
   }
 }
+
 } // end namespace
 
 int main(int argc, const char **argv) {
Index: cfe/trunk/include/clang/AST/ExternalASTMerger.h
===================================================================
--- cfe/trunk/include/clang/AST/ExternalASTMerger.h
+++ cfe/trunk/include/clang/AST/ExternalASTMerger.h
@@ -0,0 +1,51 @@
+//===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file declares the ExternalASTMerger, which vends a combination of ASTs
+//  from several different ASTContext/FileManager pairs
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
+#define LLVM_CLANG_AST_EXTERNALASTMERGER_H
+
+#include "clang/AST/ASTImporter.h"
+#include "clang/AST/ExternalASTSource.h"
+
+namespace clang {
+
+class ExternalASTMerger : public ExternalASTSource {
+public:
+  struct ImporterPair {
+    std::unique_ptr<ASTImporter> Forward;
+    std::unique_ptr<ASTImporter> Reverse;
+  };
+
+private:
+  std::vector<ImporterPair> Importers;
+
+public:
+  struct ImporterEndpoint {
+    ASTContext &AST;
+    FileManager &FM;
+  };
+  ExternalASTMerger(const ImporterEndpoint &Target,
+                    llvm::ArrayRef<ImporterEndpoint> Sources);
+
+  bool FindExternalVisibleDeclsByName(const DeclContext *DC,
+                                      DeclarationName Name) override;
+
+  void
+  FindExternalLexicalDecls(const DeclContext *DC,
+                           llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+                           SmallVectorImpl<Decl *> &Result) override;
+};
+
+} // end namespace clang
+
+#endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to