Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -148,32 +148,20 @@ // Use this to import pointers of specific type. template LLVM_NODISCARD Error importInto(ImportT *&To, ImportT *From) { - auto ToI = Importer.Import(From); - if (!ToI && From) - return make_error(); - To = cast_or_null(ToI); - return Error::success(); - // FIXME: This should be the final code. - //auto ToOrErr = Importer.Import(From); - //if (ToOrErr) { - // To = cast_or_null(*ToOrErr); - //} - //return ToOrErr.takeError(); + auto ToOrErr = Importer.Import_New(From); + if (ToOrErr) + To = cast_or_null(*ToOrErr); + return ToOrErr.takeError(); } // Call the import function of ASTImporter for a baseclass of type `T` and // cast the return value to `T`. template Expected import(T *From) { - auto *To = Importer.Import(From); - if (!To && From) - return make_error(); - return cast_or_null(To); - // FIXME: This should be the final code. - //auto ToOrErr = Importer.Import(From); - //if (!ToOrErr) - // return ToOrErr.takeError(); - //return cast_or_null(*ToOrErr); + auto ToOrErr = Importer.Import_New(From); + if (!ToOrErr) + return ToOrErr.takeError(); + return cast_or_null(*ToOrErr); } template @@ -184,13 +172,7 @@ // Call the import function of ASTImporter for type `T`. template Expected import(const T &From) { - T To = Importer.Import(From); - T DefaultT; - if (To == DefaultT && !(From == DefaultT)) - return make_error(); - return To; - // FIXME: This should be the final code. - //return Importer.Import(From); + return Importer.Import_New(From); } template @@ -282,8 +264,15 @@ void InitializeImportedDecl(Decl *FromD, Decl *ToD) { ToD->IdentifierNamespace = FromD->IdentifierNamespace; if (FromD->hasAttrs()) - for (const Attr *FromAttr : FromD->getAttrs()) - ToD->addAttr(Importer.Import(FromAttr)); + for (const Attr *FromAttr : FromD->getAttrs()) { + // FIXME: Return of the error here is not possible until store of + // import errors is implemented. + auto ToAttrOrErr = import(FromAttr); + if (ToAttrOrErr) + ToD->addAttr(*ToAttrOrErr); + else + llvm::consumeError(ToAttrOrErr.takeError()); + } if (FromD->isUsed()) ToD->setIsUsed(); if (FromD->isImplicit()) @@ -643,15 +632,6 @@ FunctionDecl *FromFD); }; -// FIXME: Temporary until every import returns Expected. -template <> -Expected ASTNodeImporter::import(const TemplateName &From) { - TemplateName To = Importer.Import(From); - if (To.isNull() && !From.isNull()) - return make_error(); - return To; -} - template Error ASTNodeImporter::ImportTemplateArgumentListInfo( SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc, @@ -1692,15 +1672,10 @@ static Error setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To, ASTImporter &Importer) { if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) { - Decl *ToTypedef = Importer.Import(FromTypedef); - if (!ToTypedef) - return make_error(); - To->setTypedefNameForAnonDecl(cast(ToTypedef)); - // FIXME: This should be the final code. - //if (Expected ToTypedefOrErr = Importer.Import(FromTypedef)) - // To->setTypedefNameForAnonDecl(cast(*ToTypedefOrErr)); - //else - // return ToTypedefOrErr.takeError(); + if (ExpectedDecl ToTypedefOrErr = Importer.Import_New(FromTypedef)) + To->setTypedefNameForAnonDecl(cast(*ToTypedefOrErr)); + else + return ToTypedefOrErr.takeError(); } return Error::success(); } @@ -3386,9 +3361,6 @@ // FIXME here we leak `NamedChain` which is allocated before return ToIndirectField; - for (const auto *Attr : D->attrs()) - ToIndirectField->addAttr(Importer.Import(Attr)); - ToIndirectField->setAccess(D->getAccess()); ToIndirectField->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIndirectField); @@ -7814,9 +7786,10 @@ if (!FromDC) return FromDC; - auto *ToDC = cast_or_null(Import(cast(FromDC))); - if (!ToDC) - return nullptr; + ExpectedDecl ToDCOrErr = Import_New(cast(FromDC)); + if (!ToDCOrErr) + return ToDCOrErr.takeError(); + auto *ToDC = cast(*ToDCOrErr); // When we're using a record/enum/Objective-C class/protocol as a context, we // need it to have a definition. @@ -8612,10 +8585,16 @@ bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To, bool Complain) { - llvm::DenseMap::iterator Pos - = ImportedTypes.find(From.getTypePtr()); - if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To)) - return true; + llvm::DenseMap::iterator Pos = + ImportedTypes.find(From.getTypePtr()); + if (Pos != ImportedTypes.end()) { + if (ExpectedType ToFromOrErr = Import_New(From)) { + if (ToContext.hasSameType(*ToFromOrErr, To)) + return true; + } else { + llvm::consumeError(ToFromOrErr.takeError()); + } + } StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls, getStructuralEquivalenceKind(*this), false, Index: lib/AST/ExternalASTMerger.cpp =================================================================== --- lib/AST/ExternalASTMerger.cpp +++ lib/AST/ExternalASTMerger.cpp @@ -56,7 +56,12 @@ } auto *ND = cast(DC); DeclarationName Name = ND->getDeclName(); - Source SourceName = ReverseImporter.Import(Name); + auto SourceNameOrErr = ReverseImporter.Import_New(Name); + if (!SourceNameOrErr) { + llvm::consumeError(SourceNameOrErr.takeError()); + return nullptr; + } + Source SourceName = *SourceNameOrErr; DeclContext::lookup_result SearchResult = SourceParentDC.get()->lookup(SourceName.get()); size_t SearchResultSize = SearchResult.size(); @@ -354,9 +359,13 @@ template static bool importSpecializations(DeclTy *D, ASTImporter *Importer) { - for (auto *Spec : D->specializations()) - if (!Importer->Import(Spec)) + for (auto *Spec : D->specializations()) { + auto ImportedSpecOrError = Importer->Import_New(Spec); + if (!ImportedSpecOrError) { + llvm::consumeError(ImportedSpecOrError.takeError()); return true; + } + } return false; } @@ -383,15 +392,21 @@ Candidates.push_back(C); }; - ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse, - Source SourceDC) -> bool { - DeclarationName FromName = Reverse.Import(Name); - DeclContextLookupResult Result = SourceDC.get()->lookup(FromName); - for (NamedDecl *FromD : Result) { - FilterFoundDecl(std::make_pair(FromD, &Forward)); - } - return false; - }); + ForEachMatchingDC(DC, + [&](ASTImporter &Forward, ASTImporter &Reverse, + Source SourceDC) -> bool { + auto FromNameOrErr = Reverse.Import_New(Name); + if (!FromNameOrErr) { + llvm::consumeError(FromNameOrErr.takeError()); + return false; + } + DeclContextLookupResult Result = + SourceDC.get()->lookup(*FromNameOrErr); + for (NamedDecl *FromD : Result) { + FilterFoundDecl(std::make_pair(FromD, &Forward)); + } + return false; + }); if (Candidates.empty()) return false; @@ -400,7 +415,10 @@ for (const Candidate &C : Candidates) { Decl *LookupRes = C.first.get(); ASTImporter *Importer = C.second; - NamedDecl *ND = cast_or_null(Importer->Import(LookupRes)); + auto NDOrErr = Importer->Import_New(LookupRes); + assert(NDOrErr); + (void)static_cast(NDOrErr); + NamedDecl *ND = cast_or_null(*NDOrErr); assert(ND); // If we don't import specialization, they are not available via lookup // because the lookup result is imported TemplateDecl and it does not @@ -422,9 +440,12 @@ Source SourceDC) -> bool { for (const Decl *SourceDecl : SourceDC.get()->decls()) { if (IsKindWeWant(SourceDecl->getKind())) { - Decl *ImportedDecl = Forward.Import(const_cast(SourceDecl)); - assert(!ImportedDecl || IsSameDC(ImportedDecl->getDeclContext(), DC)); - (void)ImportedDecl; + auto ImportedDeclOrErr = Forward.Import_New(SourceDecl); + if (ImportedDeclOrErr) + assert(!(*ImportedDeclOrErr) || + IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC)); + else + llvm::consumeError(ImportedDeclOrErr.takeError()); } } return false; Index: lib/CrossTU/CrossTranslationUnit.cpp =================================================================== --- lib/CrossTU/CrossTranslationUnit.cpp +++ lib/CrossTU/CrossTranslationUnit.cpp @@ -357,13 +357,28 @@ assert(FD->hasBody() && "Functions to be imported should have body."); ASTImporter &Importer = getOrCreateASTImporter(FD->getASTContext()); - auto *ToDecl = - cast_or_null(Importer.Import(const_cast(FD))); - if (!ToDecl) + auto ToDeclOrError = Importer.Import_New(FD); + if (!ToDeclOrError) { + handleAllErrors(ToDeclOrError.takeError(), + [&](const ImportError &IE) { + switch (IE.Error) { + case ImportError::NameConflict: + // FIXME: Add statistic. + break; + case ImportError::UnsupportedConstruct: + // FIXME: Add statistic. + break; + case ImportError::Unknown: + llvm_unreachable("Unknown import error happened."); + break; + } + }); return llvm::make_error(index_error_code::failed_import); - assert(ToDecl->hasBody()); - assert(FD->hasBody() && "Functions already imported should have body."); + } + auto *ToDecl = cast(*ToDeclOrError); + assert(ToDecl->hasBody() && "Imported function should have body."); ++NumGetCTUSuccess; + return ToDecl; } Index: lib/Frontend/ASTMerge.cpp =================================================================== --- lib/Frontend/ASTMerge.cpp +++ lib/Frontend/ASTMerge.cpp @@ -65,11 +65,13 @@ if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list")) continue; - Decl *ToD = Importer.Import(D); + llvm::Expected ToDOrError = Importer.Import_New(D); - if (ToD) { - DeclGroupRef DGR(ToD); + if (ToDOrError) { + DeclGroupRef DGR(*ToDOrError); CI.getASTConsumer().HandleTopLevelDecl(DGR); + } else { + llvm::consumeError(ToDOrError.takeError()); } } } Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -89,8 +89,8 @@ public ::testing::WithParamInterface { template - NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer, - NodeType Node) { + llvm::Expected importNode(ASTUnit *From, ASTUnit *To, + ASTImporter &Importer, NodeType Node) { ASTContext &ToCtx = To->getASTContext(); // Add 'From' file to virtual file system so importer can 'find' it @@ -100,17 +100,19 @@ createVirtualFileIfNeeded(To, FromFileName, From->getBufferForFile(FromFileName)); - auto Imported = Importer.Import(Node); + auto Imported = Importer.Import_New(Node); - // This should dump source locations and assert if some source locations - // were not imported. - SmallString<1024> ImportChecker; - llvm::raw_svector_ostream ToNothing(ImportChecker); - ToCtx.getTranslationUnitDecl()->print(ToNothing); + if (Imported) { + // This should dump source locations and assert if some source locations + // were not imported. + SmallString<1024> ImportChecker; + llvm::raw_svector_ostream ToNothing(ImportChecker); + ToCtx.getTranslationUnitDecl()->print(ToNothing); - // This traverses the AST to catch certain bugs like poorly or not - // implemented subtrees. - Imported->dump(ToNothing); + // This traverses the AST to catch certain bugs like poorly or not + // implemented subtrees. + (*Imported)->dump(ToNothing); + } return Imported; } @@ -151,11 +153,16 @@ EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher)); auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport); - if (!Imported) - return testing::AssertionFailure() << "Import failed, nullptr returned!"; - + if (!Imported) { + std::string ErrorText; + handleAllErrors( + Imported.takeError(), + [&ErrorText](const ImportError &Err) { ErrorText = Err.message(); }); + return testing::AssertionFailure() + << "Import failed, error: \"" << ErrorText << "\"!"; + } - return Verifier.match(Imported, WrapperMatcher); + return Verifier.match(*Imported, WrapperMatcher); } template @@ -277,7 +284,9 @@ EXPECT_TRUE(FoundDecl.size() == 1); const Decl *ToImport = selectFirst(DeclToImportID, FoundDecl); auto Imported = importNode(From, To, *ImporterRef, ToImport); - EXPECT_TRUE(Imported); + EXPECT_TRUE(static_cast(Imported)); + if (!Imported) + llvm::consumeError(Imported.takeError()); } // Find the declaration and import it. @@ -339,13 +348,23 @@ Decl *import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST, Decl *FromDecl) { lazyInitImporter(LookupTable, ToAST); - return Importer->Import(FromDecl); + if (auto ImportedOrErr = Importer->Import_New(FromDecl)) + return *ImportedOrErr; + else { + llvm::consumeError(ImportedOrErr.takeError()); + return nullptr; + } } QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST, QualType FromType) { lazyInitImporter(LookupTable, ToAST); - return Importer->Import(FromType); + if (auto ImportedOrErr = Importer->Import_New(FromType)) + return *ImportedOrErr; + else { + llvm::consumeError(ImportedOrErr.takeError()); + return QualType{}; + } } };