Author: balazske Date: Fri Aug 30 03:12:14 2019 New Revision: 370457 URL: http://llvm.org/viewvc/llvm-project?rev=370457&view=rev Log: [ASTImporter] Propagate errors during import of overridden methods.
Summary: If importing overridden methods fails for a method it can be seen incorrectly as non-virtual. To avoid this inconsistency the method is marked with import error to avoid later use of it. Reviewers: martong, a.sidorin, shafik, a_sidorin Reviewed By: martong, shafik Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66933 Modified: cfe/trunk/lib/AST/ASTImporter.cpp cfe/trunk/unittests/AST/ASTImporterTest.cpp Modified: cfe/trunk/lib/AST/ASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=370457&r1=370456&r2=370457&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp (original) +++ cfe/trunk/lib/AST/ASTImporter.cpp Fri Aug 30 03:12:14 2019 @@ -639,7 +639,8 @@ namespace clang { return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); } - void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); + Error ImportOverriddenMethods(CXXMethodDecl *ToMethod, + CXXMethodDecl *FromMethod); Expected<FunctionDecl *> FindFunctionTemplateSpecialization( FunctionDecl *FromFD); @@ -3370,7 +3371,9 @@ ExpectedDecl ASTNodeImporter::VisitFunct } if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) - ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod); + if (Error Err = ImportOverriddenMethods(cast<CXXMethodDecl>(ToFunction), + FromCXXMethod)) + return std::move(Err); // Import the rest of the chain. I.e. import all subsequent declarations. for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { @@ -7804,15 +7807,18 @@ ExpectedStmt ASTNodeImporter::VisitCXXTy *ToTypeOrErr, *ToExprOperandOrErr, *ToSourceRangeOrErr); } -void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod, - CXXMethodDecl *FromMethod) { +Error ASTNodeImporter::ImportOverriddenMethods(CXXMethodDecl *ToMethod, + CXXMethodDecl *FromMethod) { + Error ImportErrors = Error::success(); for (auto *FromOverriddenMethod : FromMethod->overridden_methods()) { if (auto ImportedOrErr = import(FromOverriddenMethod)) ToMethod->getCanonicalDecl()->addOverriddenMethod(cast<CXXMethodDecl>( (*ImportedOrErr)->getCanonicalDecl())); else - consumeError(ImportedOrErr.takeError()); + ImportErrors = + joinErrors(std::move(ImportErrors), ImportedOrErr.takeError()); } + return ImportErrors; } ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=370457&r1=370456&r2=370457&view=diff ============================================================================== --- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original) +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Fri Aug 30 03:12:14 2019 @@ -5183,6 +5183,50 @@ TEST_P(ErrorHandlingTest, } } +TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) { + auto MatchFooA = + functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("A")))); + auto MatchFooB = + functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("B")))); + auto MatchFooC = + functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("C")))); + + // Provoke import of a method that has overridden methods with import error. + TranslationUnitDecl *FromTU = getTuDecl(std::string(R"( + struct C; + struct A { + virtual void foo(); + void f1(C *); + }; + void A::foo() { + )") + ErroneousStmt + R"( + } + struct B : public A { + void foo() override; + }; + struct C : public B { + void foo() override; + }; + )", + Lang_CXX11); + auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA); + auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB); + auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC); + + EXPECT_FALSE(Import(FromFooA, Lang_CXX11)); + ASTImporter *Importer = findFromTU(FromFooA)->Importer.get(); + auto CheckError = [&Importer](Decl *FromD) { + Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromD); + ASSERT_TRUE(OptErr); + EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); + }; + CheckError(FromFooA); + EXPECT_FALSE(Import(FromFooB, Lang_CXX11)); + CheckError(FromFooB); + EXPECT_FALSE(Import(FromFooC, Lang_CXX11)); + CheckError(FromFooC); +} + TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) { Decl *FromTU = getTuDecl( R"( _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits