From: Douglas Gregor Date: Wed, 12 Jan 2011 17:07:58 +0000 (+0000) Subject: Teach TreeTransform how to transform a pack expansion type into X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2fc1bb76e719d0620b4a6e2134413933b21ca6b6;p=clang Teach TreeTransform how to transform a pack expansion type into another pack expansion type. This can happen when rebuilding types in the current instantiation. Fixes (Clang crashing on libc++ ). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123316 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index df4e4dc48c..1b22cd8ad7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3331,7 +3331,13 @@ public: /// expansion. TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc); - + + /// \brief Construct a pack expansion type from the pattern of the pack + /// expansion. + QualType CheckPackExpansion(QualType Pattern, + SourceRange PatternRange, + SourceLocation EllipsisLoc); + /// \brief Invoked when parsing an expression followed by an ellipsis, which /// creates a pack expansion. /// diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 63a8394d67..473dcb7d1f 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -377,18 +377,13 @@ TypeResult Sema::ActOnPackExpansion(ParsedType Type, TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc) { - // C++0x [temp.variadic]p5: - // The pattern of a pack expansion shall name one or more - // parameter packs that are not expanded by a nested pack - // expansion. - if (!Pattern->getType()->containsUnexpandedParameterPack()) { - Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) - << Pattern->getTypeLoc().getSourceRange(); + // Create the pack expansion type and source-location information. + QualType Result = CheckPackExpansion(Pattern->getType(), + Pattern->getTypeLoc().getSourceRange(), + EllipsisLoc); + if (Result.isNull()) return 0; - } - // Create the pack expansion type and source-location information. - QualType Result = Context.getPackExpansionType(Pattern->getType()); TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result); PackExpansionTypeLoc TL = cast(TSResult->getTypeLoc()); TL.setEllipsisLoc(EllipsisLoc); @@ -400,6 +395,22 @@ TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern, return TSResult; } +QualType Sema::CheckPackExpansion(QualType Pattern, + SourceRange PatternRange, + SourceLocation EllipsisLoc) { + // C++0x [temp.variadic]p5: + // The pattern of a pack expansion shall name one or more + // parameter packs that are not expanded by a nested pack + // expansion. + if (!Pattern->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << PatternRange; + return QualType(); + } + + return Context.getPackExpansionType(Pattern); +} + ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) { if (!Pattern) return ExprError(); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index e63cc7da7c..f601d5c047 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -808,6 +808,16 @@ public: return SemaRef.Context.getElaboratedType(Keyword, NNS, T); } + /// \brief Build a new pack expansion type. + /// + /// By default, builds a new PackExpansionType type from the given pattern. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildPackExpansionType(QualType Pattern, + SourceRange PatternRange, + SourceLocation EllipsisLoc) { + return getSema().CheckPackExpansion(Pattern, PatternRange, EllipsisLoc); + } + /// \brief Build a new nested-name-specifier given the prefix and an /// identifier that names the next step in the nested-name-specifier. /// @@ -4232,8 +4242,24 @@ QualType TreeTransform:: template QualType TreeTransform::TransformPackExpansionType(TypeLocBuilder &TLB, PackExpansionTypeLoc TL) { - llvm_unreachable("Caller must expansion pack expansion types"); - return QualType(); + QualType Pattern + = getDerived().TransformType(TLB, TL.getPatternLoc()); + if (Pattern.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Pattern != TL.getPatternLoc().getType()) { + Result = getDerived().RebuildPackExpansionType(Pattern, + TL.getPatternLoc().getSourceRange(), + TL.getEllipsisLoc()); + if (Result.isNull()) + return QualType(); + } + + PackExpansionTypeLoc NewT = TLB.push(Result); + NewT.setEllipsisLoc(TL.getEllipsisLoc()); + return Result; } template diff --git a/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp b/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp index bcdbe5351e..36621ecf5a 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp @@ -39,3 +39,21 @@ template template template void X0::Inner::f4() { } + +namespace rdar8848837 { + // Out-of-line definitions that cause rebuilding in the current + // instantiation. + template struct X; + + template + struct X { + X f(); + }; + + template + X X::f() { return *this; } + + + X xif; + +}