|
@@ -284,12 +284,15 @@ class ASTImporterTestBase : public ParameterizedTestsFixture {
|
|
// Buffer for the To context, must live in the test scope.
|
|
// Buffer for the To context, must live in the test scope.
|
|
std::string ToCode;
|
|
std::string ToCode;
|
|
|
|
|
|
|
|
+ // Represents a "From" translation unit and holds an importer object which we
|
|
|
|
+ // use to import from this translation unit.
|
|
struct TU {
|
|
struct TU {
|
|
// Buffer for the context, must live in the test scope.
|
|
// Buffer for the context, must live in the test scope.
|
|
std::string Code;
|
|
std::string Code;
|
|
std::string FileName;
|
|
std::string FileName;
|
|
std::unique_ptr<ASTUnit> Unit;
|
|
std::unique_ptr<ASTUnit> Unit;
|
|
TranslationUnitDecl *TUDecl = nullptr;
|
|
TranslationUnitDecl *TUDecl = nullptr;
|
|
|
|
+ std::unique_ptr<ASTImporter> Importer;
|
|
TU(StringRef Code, StringRef FileName, ArgVector Args)
|
|
TU(StringRef Code, StringRef FileName, ArgVector Args)
|
|
: Code(Code), FileName(FileName),
|
|
: Code(Code), FileName(FileName),
|
|
Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
|
|
Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
|
|
@@ -297,6 +300,16 @@ class ASTImporterTestBase : public ParameterizedTestsFixture {
|
|
TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
|
|
TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
|
|
Unit->enableSourceFileDiagnostics();
|
|
Unit->enableSourceFileDiagnostics();
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
|
|
|
|
+ assert(ToAST);
|
|
|
|
+ if (!Importer) {
|
|
|
|
+ Importer.reset(new ASTImporter(
|
|
|
|
+ ToAST->getASTContext(), ToAST->getFileManager(),
|
|
|
|
+ Unit->getASTContext(), Unit->getFileManager(), false));
|
|
|
|
+ }
|
|
|
|
+ return Importer->Import(FromDecl);
|
|
|
|
+ }
|
|
};
|
|
};
|
|
|
|
|
|
// We may have several From contexts and related translation units. In each
|
|
// We may have several From contexts and related translation units. In each
|
|
@@ -329,14 +342,10 @@ public:
|
|
ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
|
|
ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
|
|
ToAST->enableSourceFileDiagnostics();
|
|
ToAST->enableSourceFileDiagnostics();
|
|
|
|
|
|
- ASTContext &FromCtx = FromTU.Unit->getASTContext(),
|
|
|
|
- &ToCtx = ToAST->getASTContext();
|
|
|
|
|
|
+ ASTContext &FromCtx = FromTU.Unit->getASTContext();
|
|
|
|
|
|
createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
|
|
createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
|
|
|
|
|
|
- ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
|
|
|
|
- FromTU.Unit->getFileManager(), false);
|
|
|
|
-
|
|
|
|
IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
|
|
IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
|
|
assert(ImportedII && "Declaration with the given identifier "
|
|
assert(ImportedII && "Declaration with the given identifier "
|
|
"should be specified in test!");
|
|
"should be specified in test!");
|
|
@@ -347,7 +356,8 @@ public:
|
|
|
|
|
|
assert(FoundDecls.size() == 1);
|
|
assert(FoundDecls.size() == 1);
|
|
|
|
|
|
- Decl *Imported = Importer.Import(FoundDecls.front());
|
|
|
|
|
|
+ Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
|
|
|
|
+
|
|
assert(Imported);
|
|
assert(Imported);
|
|
return std::make_tuple(*FoundDecls.begin(), Imported);
|
|
return std::make_tuple(*FoundDecls.begin(), Imported);
|
|
}
|
|
}
|
|
@@ -401,11 +411,7 @@ public:
|
|
assert(It != FromTUs.end());
|
|
assert(It != FromTUs.end());
|
|
createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code);
|
|
createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code);
|
|
|
|
|
|
- ASTContext &FromCtx = From->getASTContext(),
|
|
|
|
- &ToCtx = ToAST->getASTContext();
|
|
|
|
- ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
|
|
|
|
- FromCtx.getSourceManager().getFileManager(), false);
|
|
|
|
- return Importer.Import(From);
|
|
|
|
|
|
+ return It->import(ToAST.get(), From);
|
|
}
|
|
}
|
|
|
|
|
|
~ASTImporterTestBase() {
|
|
~ASTImporterTestBase() {
|
|
@@ -1089,8 +1095,7 @@ TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
|
|
EXPECT_EQ(ToTemplated1, ToTemplated);
|
|
EXPECT_EQ(ToTemplated1, ToTemplated);
|
|
}
|
|
}
|
|
|
|
|
|
-TEST_P(ASTImporterTestBase,
|
|
|
|
- DISABLED_ImportOfTemplatedDeclOfFunctionTemplateDecl) {
|
|
|
|
|
|
+TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
|
|
Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
|
|
Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
|
|
auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
|
|
auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
|
|
FromTU, functionTemplateDecl());
|
|
FromTU, functionTemplateDecl());
|
|
@@ -1166,7 +1171,7 @@ TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
|
|
ASSERT_EQ(ToTemplated1, ToTemplated);
|
|
ASSERT_EQ(ToTemplated1, ToTemplated);
|
|
}
|
|
}
|
|
|
|
|
|
-TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) {
|
|
|
|
|
|
+TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
|
|
Decl *From, *To;
|
|
Decl *From, *To;
|
|
std::tie(From, To) = getImportedDecl(
|
|
std::tie(From, To) = getImportedDecl(
|
|
R"(
|
|
R"(
|
|
@@ -1711,6 +1716,49 @@ TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
|
|
EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
|
|
EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
|
|
|
|
+ auto Pattern = varDecl(hasName("x"));
|
|
|
|
+ VarDecl *Imported1;
|
|
|
|
+ {
|
|
|
|
+ Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
|
|
|
|
+ auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
|
|
|
|
+ Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
|
|
|
|
+ }
|
|
|
|
+ VarDecl *Imported2;
|
|
|
|
+ {
|
|
|
|
+ Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
|
|
|
|
+ auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
|
|
|
|
+ Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
|
|
|
|
+ }
|
|
|
|
+ EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
|
|
|
|
+ EXPECT_FALSE(Imported2->isUsed(false));
|
|
|
|
+ {
|
|
|
|
+ Decl *FromTU =
|
|
|
|
+ getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
|
|
|
|
+ auto *FromD =
|
|
|
|
+ FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
|
|
|
|
+ Import(FromD, Lang_CXX);
|
|
|
|
+ }
|
|
|
|
+ EXPECT_TRUE(Imported2->isUsed(false));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
|
|
|
|
+ auto Pattern = varDecl(hasName("x"));
|
|
|
|
+
|
|
|
|
+ Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
|
|
|
|
+ auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
|
|
|
|
+
|
|
|
|
+ auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
|
|
|
|
+
|
|
|
|
+ ASSERT_FALSE(Imported1->isUsed(false));
|
|
|
|
+
|
|
|
|
+ FromD->setIsUsed();
|
|
|
|
+ auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
|
|
|
|
+
|
|
|
|
+ EXPECT_EQ(Imported1, Imported2);
|
|
|
|
+ EXPECT_TRUE(Imported2->isUsed(false));
|
|
|
|
+}
|
|
|
|
+
|
|
struct ImportFunctions : ASTImporterTestBase {};
|
|
struct ImportFunctions : ASTImporterTestBase {};
|
|
|
|
|
|
TEST_P(ImportFunctions,
|
|
TEST_P(ImportFunctions,
|
|
@@ -2043,14 +2091,10 @@ TEST_P(ImportFriendFunctions,
|
|
EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
|
|
EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
|
|
}
|
|
}
|
|
|
|
|
|
-// This test is disabled, because ATM we create a redundant FunctionDecl. We
|
|
|
|
-// start the import with the definition of `f` then we continue with the import
|
|
|
|
-// of the type of `f` which involves `X`. During the import of `X` we start
|
|
|
|
-// again the import of the definition of `f` and then finally we create the
|
|
|
|
-// node. But then in the first frame of `VisitFunctionDecl` we create a node
|
|
|
|
-// again since we do not check if such a node exists yet or not. This is being
|
|
|
|
-// fixed in a separate patch: https://reviews.llvm.org/D47632
|
|
|
|
-// FIXME enable this test once the above patch is approved.
|
|
|
|
|
|
+// Disabled temporarily, because the new structural equivalence check
|
|
|
|
+// (https://reviews.llvm.org/D48628) breaks it.
|
|
|
|
+// PreviousDecl is not set because there is no structural match.
|
|
|
|
+// FIXME Enable!
|
|
TEST_P(ImportFriendFunctions,
|
|
TEST_P(ImportFriendFunctions,
|
|
DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
|
|
DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
|
|
auto Pattern = functionDecl(hasName("f"));
|
|
auto Pattern = functionDecl(hasName("f"));
|
|
@@ -2080,16 +2124,12 @@ TEST_P(ImportFriendFunctions,
|
|
(*ImportedD->param_begin())->getOriginalType());
|
|
(*ImportedD->param_begin())->getOriginalType());
|
|
}
|
|
}
|
|
|
|
|
|
-// This test is disabled, because ATM we create a redundant FunctionDecl. We
|
|
|
|
-// start the import with the definition of `f` then we continue with the import
|
|
|
|
-// of the type of `f` which involves `X`. During the import of `X` we start
|
|
|
|
-// again the import of the definition of `f` and then finally we create the
|
|
|
|
-// node. But then in the first frame of `VisitFunctionDecl` we create a node
|
|
|
|
-// again since we do not check if such a node exists yet or not. This is being
|
|
|
|
-// fixed in a separate patch: https://reviews.llvm.org/D47632
|
|
|
|
-// FIXME enable this test once the above patch is approved.
|
|
|
|
|
|
+// Disabled temporarily, because the new structural equivalence check
|
|
|
|
+// (https://reviews.llvm.org/D48628) breaks it.
|
|
|
|
+// PreviousDecl is not set because there is no structural match.
|
|
|
|
+// FIXME Enable!
|
|
TEST_P(ImportFriendFunctions,
|
|
TEST_P(ImportFriendFunctions,
|
|
- DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
|
|
|
|
|
|
+ DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
|
|
auto Pattern = functionDecl(hasName("f"));
|
|
auto Pattern = functionDecl(hasName("f"));
|
|
|
|
|
|
Decl *FromTU = getTuDecl(
|
|
Decl *FromTU = getTuDecl(
|