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