summaryrefslogtreecommitdiffstats
path: root/clang/unittests/AST/ASTImporterTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/unittests/AST/ASTImporterTest.cpp')
-rw-r--r--clang/unittests/AST/ASTImporterTest.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 63bcc609f06..41a041f101e 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -4620,6 +4620,127 @@ TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
EXPECT_EQ(Imported->getPreviousDecl(), Friend);
}
+struct ASTImporterWithFakeErrors : ASTImporter {
+ using ASTImporter::ASTImporter;
+ bool returnWithErrorInTest() override { return true; }
+};
+
+struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
+ ErrorHandlingTest() {
+ Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
+ ASTContext &FromContext, FileManager &FromFileManager,
+ bool MinimalImport, ASTImporterLookupTable *LookupTable) {
+ return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
+ FromContext, FromFileManager,
+ MinimalImport, LookupTable);
+ };
+ }
+ // In this test we purposely report an error (UnsupportedConstruct) when
+ // importing the below stmt.
+ static constexpr auto* ErroneousStmt = R"( asm(""); )";
+};
+
+// Check a case when no new AST node is created in the AST before encountering
+// the error.
+TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
+ TranslationUnitDecl *ToTU = getToTuDecl(
+ R"(
+ template <typename T>
+ class X {};
+ template <>
+ class X<int> { int a; };
+ )",
+ Lang_CXX);
+ TranslationUnitDecl *FromTU = getTuDecl(
+ R"(
+ template <typename T>
+ class X {};
+ template <>
+ class X<int> { double b; };
+ )",
+ Lang_CXX);
+ auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
+ FromTU, classTemplateSpecializationDecl(hasName("X")));
+ ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX);
+ EXPECT_FALSE(ImportedSpec);
+
+ // The original Decl is kept, no new decl is created.
+ EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
+ ToTU, classTemplateSpecializationDecl(hasName("X"))),
+ 1u);
+
+ // But an error is set to the counterpart in the "from" context.
+ ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
+ Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec);
+ ASSERT_TRUE(OptErr);
+ EXPECT_EQ(OptErr->Error, ImportError::NameConflict);
+}
+
+// Check a case when a new AST node is created but not linked to the AST before
+// encountering the error.
+TEST_P(ErrorHandlingTest,
+ ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
+ TranslationUnitDecl *FromTU = getTuDecl(
+ std::string("void foo() { ") + ErroneousStmt + " }",
+ Lang_CXX);
+ auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("foo")));
+
+ FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX);
+ EXPECT_FALSE(ImportedFoo);
+
+ TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ // Created, but not linked.
+ EXPECT_EQ(
+ DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
+ 0u);
+
+ ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
+ Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo);
+ ASSERT_TRUE(OptErr);
+ EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
+}
+
+// Check a case when a new AST node is created and linked to the AST before
+// encountering the error. The error is set for the counterpart of the nodes in
+// the "from" context.
+TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
+ TranslationUnitDecl *FromTU = getTuDecl(
+ std::string(R"(
+ void f();
+ void f() { )") + ErroneousStmt + R"( }
+ )",
+ Lang_CXX);
+ auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("f")));
+ auto *FromDef =
+ LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
+ FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX);
+ EXPECT_FALSE(ImportedProto); // Could not import.
+ // However, we created two nodes in the AST. 1) the fwd decl 2) the
+ // definition. The definition is not added to its DC, but the fwd decl is
+ // there.
+ TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+ EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
+ 1u);
+ // Match the fwd decl.
+ auto *ToProto =
+ FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
+ EXPECT_TRUE(ToProto);
+ // An error is set to the counterpart in the "from" context both for the fwd
+ // decl and the definition.
+ ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
+ Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto);
+ ASSERT_TRUE(OptErr);
+ EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
+ OptErr = Importer->getImportDeclErrorIfAny(FromDef);
+ ASSERT_TRUE(OptErr);
+ EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
+}
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
+ DefaultTestValuesForRunOptions, );
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
DefaultTestValuesForRunOptions, );
OpenPOWER on IntegriCloud