Author: Gabor Marton Date: 2020-12-03T11:35:47+01:00 New Revision: 1e14588d0f6845976e774c87a18a84a0f7b61015
URL: https://github.com/llvm/llvm-project/commit/1e14588d0f6845976e774c87a18a84a0f7b61015 DIFF: https://github.com/llvm/llvm-project/commit/1e14588d0f6845976e774c87a18a84a0f7b61015.diff LOG: [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 Added: Modified: clang/lib/Sema/SemaTemplate.cpp clang/unittests/AST/ASTImporterTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 5b321bb74400..5710f9e3daad 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2077,27 +2077,28 @@ class ExtractTypeForDeductionGuide 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()); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 7e56b3ed501f..e4c73a832a14 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -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, ); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits