[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:
@@ -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());
|
||||
|
||||
@@ -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, );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user