[clang] f93dee1 - [clang][ASTImporter] Fix import of function with auto return type.
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 10 01:19:48 PDT 2022
Author: Balázs Kéri
Date: 2022-06-10T10:18:53+02:00
New Revision: f93dee10336a2361da528db0ff0f7188acba9627
URL: https://github.com/llvm/llvm-project/commit/f93dee10336a2361da528db0ff0f7188acba9627
DIFF: https://github.com/llvm/llvm-project/commit/f93dee10336a2361da528db0ff0f7188acba9627.diff
LOG: [clang][ASTImporter] Fix import of function with auto return type.
Fix a case of importing a function with auto return type
that is resolved with a type template argument that is declared
inside the function.
Fixes #55500
Reviewed By: martong
Differential Revision: https://reviews.llvm.org/D127396
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 21b9f21b8e6e2..7fee8d21fa39e 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3227,23 +3227,32 @@ static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) {
return false;
}
+static bool hasTypeDeclaredInsideFunction(QualType T, const FunctionDecl *FD) {
+ if (T.isNull())
+ return false;
+ if (const auto *RecordT = T->getAs<RecordType>()) {
+ const RecordDecl *RD = RecordT->getDecl();
+ assert(RD);
+ if (isAncestorDeclContextOf(FD, RD)) {
+ assert(RD->getLexicalDeclContext() == RD->getDeclContext());
+ return true;
+ }
+ if (const auto *RDTempl = dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ return llvm::count_if(RDTempl->getTemplateArgs().asArray(),
+ [FD](const TemplateArgument &Arg) {
+ return hasTypeDeclaredInsideFunction(
+ Arg.getAsType(), FD);
+ });
+ }
+ return false;
+}
+
bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
QualType FromTy = D->getType();
const auto *FromFPT = FromTy->getAs<FunctionProtoType>();
assert(FromFPT && "Must be called on FunctionProtoType");
- if (const AutoType *AutoT =
- FromFPT->getReturnType()->getContainedAutoType()) {
- QualType DeducedT = AutoT->getDeducedType();
- if (const auto *RecordT =
- !DeducedT.isNull() ? DeducedT->getAs<RecordType>() : nullptr) {
- const RecordDecl *RD = RecordT->getDecl();
- assert(RD);
- if (isAncestorDeclContextOf(D, RD)) {
- assert(RD->getLexicalDeclContext() == RD->getDeclContext());
- return true;
- }
- }
- }
+ if (const AutoType *AutoT = FromFPT->getReturnType()->getContainedAutoType())
+ return hasTypeDeclaredInsideFunction(AutoT->getDeducedType(), D);
if (const auto *TypedefT = FromFPT->getReturnType()->getAs<TypedefType>()) {
const TypedefNameDecl *TD = TypedefT->getDecl();
assert(TD);
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 4d37ac2ebb2ed..607c049608e6f 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -6319,6 +6319,61 @@ TEST_P(ASTImporterOptionSpecificTestBase,
struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {};
+TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside1) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ template<class> struct Tmpl {};
+ auto foo() {
+ struct X {};
+ return Tmpl<X>();
+ }
+ )",
+ Lang_CXX14, "input0.cc");
+ FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("foo")));
+
+ FunctionDecl *To = Import(From, Lang_CXX14);
+ EXPECT_TRUE(To);
+ EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
+}
+
+TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside2) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ template<class> struct Tmpl {};
+ auto foo() {
+ struct X {};
+ return Tmpl<Tmpl<X>>();
+ }
+ )",
+ Lang_CXX14, "input0.cc");
+ FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("foo")));
+
+ FunctionDecl *To = Import(From, Lang_CXX14);
+ EXPECT_TRUE(To);
+ EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
+}
+
+TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTypedefDeclaredInside) {
+ Decl *FromTU = getTuDecl(
+ R"(
+ template<class> struct Tmpl {};
+ auto foo() {
+ struct X {};
+ using x_type = X;
+ return Tmpl<x_type>();
+ }
+ )",
+ Lang_CXX14, "input0.cc");
+ FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("foo")));
+
+ FunctionDecl *To = Import(From, Lang_CXX14);
+ EXPECT_TRUE(To);
+ EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
+}
+
TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {
Decl *FromTU = getTuDecl(
R"(
More information about the cfe-commits
mailing list