forked from OSchip/llvm-project
[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 llvm-svn: 370457
This commit is contained in:
parent
6381b143f6
commit
b4fd7d4258
|
@ -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::VisitFunctionDecl(FunctionDecl *D) {
|
|||
}
|
||||
|
||||
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::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
|
|||
*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,
|
||||
|
|
|
@ -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"(
|
||||
|
|
Loading…
Reference in New Issue