[ASTImporter] Import ctor initializers after setting flags.

Summary:
Code to import "ctor initializers" at import of functions
is moved to be after the flags in the newly created function
are imported. This fixes an error when the already created but
incomplete (flags are not set) function declaration is accessed.

Reviewers: martong, shafik, a_sidorin, a.sidorin

Reviewed By: shafik

Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D65935

llvm-svn: 369098
This commit is contained in:
Balazs Keri 2019-08-16 12:10:03 +00:00
parent d3f774d33c
commit e13e836480
4 changed files with 33 additions and 17 deletions

View File

@ -3272,23 +3272,6 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// decl and its redeclarations may be required.
}
// Import Ctor initializers.
if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
SmallVector<CXXCtorInitializer *, 4> CtorInitializers(NumInitializers);
// Import first, then allocate memory and copy if there was no error.
if (Error Err = ImportContainerChecked(
FromConstructor->inits(), CtorInitializers))
return std::move(Err);
auto **Memory =
new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory);
auto *ToCtor = cast<CXXConstructorDecl>(ToFunction);
ToCtor->setCtorInitializers(Memory);
ToCtor->setNumCtorInitializers(NumInitializers);
}
}
ToFunction->setQualifierInfo(ToQualifierLoc);
ToFunction->setAccess(D->getAccess());
ToFunction->setLexicalDeclContext(LexicalDC);
@ -3332,6 +3315,23 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
return ToFTOrErr.takeError();
}
// Import Ctor initializers.
if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
SmallVector<CXXCtorInitializer *, 4> CtorInitializers(NumInitializers);
// Import first, then allocate memory and copy if there was no error.
if (Error Err = ImportContainerChecked(
FromConstructor->inits(), CtorInitializers))
return std::move(Err);
auto **Memory =
new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory);
auto *ToCtor = cast<CXXConstructorDecl>(ToFunction);
ToCtor->setCtorInitializers(Memory);
ToCtor->setNumCtorInitializers(NumInitializers);
}
}
if (D->doesThisDeclarationHaveABody()) {
Error Err = ImportFunctionDeclBody(D, ToFunction);

View File

@ -164,3 +164,14 @@ const int DefaultParmContext::I = 0;
int DefaultParmContext::f() {
return fDefaultParm();
}
class TestDelegateConstructor {
public:
TestDelegateConstructor() : TestDelegateConstructor(2) {}
TestDelegateConstructor(int) {}
};
int testImportOfDelegateConstructor(int i) {
TestDelegateConstructor TDC;
return i;
}

View File

@ -27,3 +27,4 @@ c:@extSCC ctu-other.cpp.ast
c:@extU ctu-other.cpp.ast
c:@S@TestAnonUnionUSR@Test ctu-other.cpp.ast
c:@F@testImportOfIncompleteDefaultParmDuringImport#I# ctu-other.cpp.ast
c:@F@testImportOfDelegateConstructor#I# ctu-other.cpp.ast

View File

@ -127,6 +127,8 @@ public:
extern int testImportOfIncompleteDefaultParmDuringImport(int);
extern int testImportOfDelegateConstructor(int);
int main() {
clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}}
clang_analyzer_eval(f(4) == 3); // expected-warning{{TRUE}}
@ -163,4 +165,6 @@ int main() {
clang_analyzer_eval(TestAnonUnionUSR::Test == 5); // expected-warning{{TRUE}}
clang_analyzer_eval(testImportOfIncompleteDefaultParmDuringImport(9) == 9); // expected-warning{{TRUE}}
clang_analyzer_eval(testImportOfDelegateConstructor(10) == 10); // expected-warning{{TRUE}}
}