[clang] 4ff103c - [clang][ASTImporter] Fix for importing functions with EST_Unevaluated prototype.
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 22 00:27:43 PDT 2021
Author: Balázs Kéri
Date: 2021-10-22T09:42:41+02:00
New Revision: 4ff103c024005fea997143a4bdb7918edd8712eb
URL: https://github.com/llvm/llvm-project/commit/4ff103c024005fea997143a4bdb7918edd8712eb
DIFF: https://github.com/llvm/llvm-project/commit/4ff103c024005fea997143a4bdb7918edd8712eb.diff
LOG: [clang][ASTImporter] Fix for importing functions with EST_Unevaluated prototype.
Fix for importing functions where the TypeSourceInfo is set and the
exception specification information contains reference to the function
declaration itself.
Reviewed By: martong, steakhal
Differential Revision: https://reviews.llvm.org/D112013
Added:
Modified:
clang/lib/AST/ASTImporter.cpp
clang/unittests/AST/ASTImporterTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index f0fcdd66560e5..1afc1e13d25a7 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3422,11 +3422,14 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
return std::move(Err);
QualType FromTy = D->getType();
+ TypeSourceInfo *FromTSI = D->getTypeSourceInfo();
// Set to true if we do not import the type of the function as is. There are
// cases when the original type would result in an infinite recursion during
// the import. To avoid an infinite recursion when importing, we create the
// FunctionDecl with a simplified function type and update it only after the
// relevant AST nodes are already imported.
+ // The type is related to TypeSourceInfo (it references the type), so we must
+ // do the same with TypeSourceInfo.
bool UsedDifferentProtoType = false;
if (const auto *FromFPT = FromTy->getAs<FunctionProtoType>()) {
QualType FromReturnTy = FromFPT->getReturnType();
@@ -3453,11 +3456,13 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
FromTy = Importer.getFromContext().getFunctionType(
FromReturnTy, FromFPT->getParamTypes(), FromEPI);
+ FromTSI = Importer.getFromContext().getTrivialTypeSourceInfo(
+ FromTy, D->getBeginLoc());
}
Error Err = Error::success();
auto T = importChecked(Err, FromTy);
- auto TInfo = importChecked(Err, D->getTypeSourceInfo());
+ auto TInfo = importChecked(Err, FromTSI);
auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
auto ToEndLoc = importChecked(Err, D->getEndLoc());
auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
@@ -3635,6 +3640,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction->setType(*TyOrErr);
else
return TyOrErr.takeError();
+ if (Expected<TypeSourceInfo *> TSIOrErr = import(D->getTypeSourceInfo()))
+ ToFunction->setTypeSourceInfo(*TSIOrErr);
+ else
+ return TSIOrErr.takeError();
}
// FIXME: Other bits to merge?
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 724de6c67f0f6..29b1500fcd76d 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6145,6 +6145,50 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {
2u);
}
+TEST_P(ASTImporterOptionSpecificTestBase,
+ ImportFunctionDeclWithTypeSourceInfoWithSourceDecl) {
+ // This code results in a lambda with implicit constructor.
+ // The constructor's TypeSourceInfo points out the function prototype.
+ // This prototype has an EST_Unevaluated in its exception information and a
+ // SourceDecl that is the function declaration itself.
+ // The test verifies that AST import of such AST does not crash.
+ // (Here the function's TypeSourceInfo references the function itself.)
+ Decl *FromTU = getTuDecl(
+ R"(
+ template<typename T> void f(T) { auto X = [](){}; }
+ void g() { f(10); }
+ )",
+ Lang_CXX11, "input0.cc");
+
+ // Use LastDeclMatcher to find the LambdaExpr in the template specialization.
+ CXXRecordDecl *FromL = LastDeclMatcher<LambdaExpr>()
+ .match(FromTU, lambdaExpr())
+ ->getLambdaClass();
+
+ CXXConstructorDecl *FromCtor = *FromL->ctor_begin();
+ ASSERT_TRUE(FromCtor->isCopyConstructor());
+ ASSERT_TRUE(FromCtor->getTypeSourceInfo());
+ const auto *FromFPT = FromCtor->getType()->getAs<FunctionProtoType>();
+ ASSERT_TRUE(FromFPT);
+ EXPECT_EQ(FromCtor->getTypeSourceInfo()->getType().getTypePtr(), FromFPT);
+ FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo();
+ // If type is EST_Unevaluated, SourceDecl should be set to the parent Decl.
+ EXPECT_EQ(FromEPI.ExceptionSpec.Type, EST_Unevaluated);
+ EXPECT_EQ(FromEPI.ExceptionSpec.SourceDecl, FromCtor);
+
+ auto ToL = Import(FromL, Lang_CXX11);
+
+ // Check if the import was correct.
+ CXXConstructorDecl *ToCtor = *ToL->ctor_begin();
+ EXPECT_TRUE(ToCtor->getTypeSourceInfo());
+ const auto *ToFPT = ToCtor->getType()->getAs<FunctionProtoType>();
+ ASSERT_TRUE(ToFPT);
+ EXPECT_EQ(ToCtor->getTypeSourceInfo()->getType().getTypePtr(), ToFPT);
+ FunctionProtoType::ExtProtoInfo ToEPI = ToFPT->getExtProtoInfo();
+ EXPECT_EQ(ToEPI.ExceptionSpec.Type, EST_Unevaluated);
+ EXPECT_EQ(ToEPI.ExceptionSpec.SourceDecl, ToCtor);
+}
+
struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {};
TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {
More information about the cfe-commits
mailing list