[Clang][Sema] Attempt to fix CTAD faulty copy of non-local typedefs

http://lists.llvm.org/pipermail/cfe-dev/2020-November/067252.html

Differential Revision: https://reviews.llvm.org/D92101
This commit is contained in:
Gabor Marton
2020-11-25 16:29:28 +01:00
parent 7ec6188921
commit 1e14588d0f
2 changed files with 91 additions and 19 deletions

View File

@@ -2077,27 +2077,28 @@ public:
QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
ASTContext &Context = SemaRef.getASTContext();
TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl();
TypeLocBuilder InnerTLB;
QualType Transformed =
TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc());
TypeSourceInfo *TSI =
TransformType(InnerTLB.getTypeSourceInfo(Context, Transformed));
TypedefNameDecl *Decl = nullptr;
if (isa<TypeAliasDecl>(OrigDecl))
Decl = TypeAliasDecl::Create(
Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
else {
assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef");
Decl = TypedefDecl::Create(
Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
TypedefNameDecl *Decl = OrigDecl;
// Transform the underlying type of the typedef and clone the Decl only if
// the typedef has a dependent context.
if (OrigDecl->getDeclContext()->isDependentContext()) {
TypeLocBuilder InnerTLB;
QualType Transformed =
TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc());
TypeSourceInfo *TSI =
TransformType(InnerTLB.getTypeSourceInfo(Context, Transformed));
if (isa<TypeAliasDecl>(OrigDecl))
Decl = TypeAliasDecl::Create(
Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
else {
assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef");
Decl = TypedefDecl::Create(
Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
}
MaterializedTypedefs.push_back(Decl);
}
MaterializedTypedefs.push_back(Decl);
QualType TDTy = Context.getTypedefType(Decl);
TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy);
TypedefTL.setNameLoc(TL.getNameLoc());

View File

@@ -5998,6 +5998,77 @@ TEST_P(ImportFunctions, CTADUserDefinedExplicit) {
EXPECT_TRUE(ToD->isExplicit());
}
// FIXME Move these tests out of ASTImporterTest. For that we need to factor
// out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase
// into a new test Fixture. Then we should lift up this Fixture to its own
// implementation file and only then could we reuse the Fixture in other AST
// unitttests.
struct CTAD : ASTImporterOptionSpecificTestBase {};
TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedef) {
Decl *TU = getTuDecl(
R"(
typedef int U;
template <typename T> struct A {
A(U, T);
};
A a{(int)0, (int)0};
)",
Lang_CXX17, "input.cc");
auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
TU, cxxDeductionGuideDecl());
auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
TU, typedefNameDecl(hasName("U")));
ParmVarDecl *Param = Guide->getParamDecl(0);
// The type of the first param (which is a typedef) should match the typedef
// in the global scope.
EXPECT_EQ(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
}
TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedefInParamPtr) {
Decl *TU = getTuDecl(
R"(
typedef int U;
template <typename T> struct A {
A(U*, T);
};
A a{(int*)0, (int)0};
)",
Lang_CXX17, "input.cc");
auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
TU, cxxDeductionGuideDecl());
auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
TU, typedefNameDecl(hasName("U")));
ParmVarDecl *Param = Guide->getParamDecl(0);
EXPECT_EQ(Param->getType()
->getAs<PointerType>()
->getPointeeType()
->getAs<TypedefType>()
->getDecl(),
Typedef);
}
TEST_P(CTAD, DeductionGuideShouldCopyALocalTypedef) {
Decl *TU = getTuDecl(
R"(
template <typename T> struct A {
typedef T U;
A(U, T);
};
A a{(int)0, (int)0};
)",
Lang_CXX17, "input.cc");
auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
TU, cxxDeductionGuideDecl());
auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
TU, typedefNameDecl(hasName("U")));
ParmVarDecl *Param = Guide->getParamDecl(0);
EXPECT_NE(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
}
INSTANTIATE_TEST_CASE_P(ParameterizedTests, CTAD,
DefaultTestValuesForRunOptions, );
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
DefaultTestValuesForRunOptions, );