balazske created this revision.
Herald added subscribers: cfe-commits, martong.
Herald added a reviewer: a.sidorin.
When a Decl is imported over an already existing similar one,
the isUsed flag is updated if it is set in the imported Decl.
This can happen if the Decl is used somewhere in the imported code
but was not used in the existing code.
Repository:
rC Clang
https://reviews.llvm.org/D48722
Files:
lib/AST/ASTImporter.cpp
unittests/AST/ASTImporterTest.cpp
Index: unittests/AST/ASTImporterTest.cpp
===
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -290,13 +290,24 @@
std::string FileName;
std::unique_ptr Unit;
TranslationUnitDecl *TUDecl = nullptr;
+std::unique_ptr Importer;
TU(StringRef Code, StringRef FileName, ArgVector Args)
: Code(Code), FileName(FileName),
Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
this->FileName)),
TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
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
@@ -329,14 +340,10 @@
ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
ToAST->enableSourceFileDiagnostics();
-ASTContext = FromTU.Unit->getASTContext(),
-= ToAST->getASTContext();
+ASTContext = FromTU.Unit->getASTContext();
createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
-ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
- FromTU.Unit->getFileManager(), false);
-
IdentifierInfo *ImportedII = (Identifier);
assert(ImportedII && "Declaration with the given identifier "
"should be specified in test!");
@@ -347,7 +354,8 @@
assert(FoundDecls.size() == 1);
-Decl *Imported = Importer.Import(FoundDecls.front());
+Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
+
assert(Imported);
return std::make_tuple(*FoundDecls.begin(), Imported);
}
@@ -401,11 +409,7 @@
assert(It != FromTUs.end());
createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code);
-ASTContext = From->getASTContext(),
-= ToAST->getASTContext();
-ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
- FromCtx.getSourceManager().getFileManager(), false);
-return Importer.Import(From);
+return It->import(ToAST.get(), From);
}
~ASTImporterTestBase() {
@@ -469,6 +473,48 @@
EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
}
+TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
+ auto Pattern = varDecl(hasName("x"));
+ VarDecl *Imported1;
+ {
+Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
+auto *FromD = FirstDeclMatcher().match(FromTU, Pattern);
+Imported1 = cast(Import(FromD, Lang_CXX));
+ }
+ VarDecl *Imported2;
+ {
+Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
+auto *FromD = FirstDeclMatcher().match(FromTU, Pattern);
+Imported2 = cast(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().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().match(FromTU, Pattern);
+
+ auto *Imported1 = cast(Import(FromD, Lang_CXX));
+
+ ASSERT_FALSE(Imported1->isUsed(false));
+
+ FromD->setIsUsed();
+ auto *Imported2 = cast(Import(FromD, Lang_CXX));
+
+ EXPECT_EQ(Imported1, Imported2);
+ EXPECT_TRUE(Imported2->isUsed(false));
+}
TEST_P(ImportExpr, ImportStringLiteral) {
MatchVerifier Verifier;
Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -90,6 +90,13 @@
return getCanonicalForwardRedeclChain(FD);
}
+ void updateAttrAndFlags(const Decl *From, Decl *To) {
+// Check if some flags or attrs are new in 'From' and copy into 'To'.
+// FIXME: Other flags or attrs?
+if (From->isUsed(false) &&