diff options
-rw-r--r-- | include/clang/Sema/Sema.h | 8 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 30 | ||||
-rw-r--r-- | test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp | 18 |
4 files changed, 74 insertions, 13 deletions
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<PackExpansionTypeLoc>(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<Derived>:: template<typename Derived> QualType TreeTransform<Derived>::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<PackExpansionTypeLoc>(Result); + NewT.setEllipsisLoc(TL.getEllipsisLoc()); + return Result; } template<typename Derived> 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<typename T, typename ...Types> template<typename ...InnerTypes> template<typename ...ReallyInner> void X0<T, T, Types...>::Inner<InnerTypes...>::f4() { } + +namespace rdar8848837 { + // Out-of-line definitions that cause rebuilding in the current + // instantiation. + template<typename F> struct X; + + template<typename R, typename ...ArgTypes> + struct X<R(ArgTypes...)> { + X<R(ArgTypes...)> f(); + }; + + template<typename R, typename ...ArgTypes> + X<R(ArgTypes...)> X<R(ArgTypes...)>::f() { return *this; } + + + X<int(float, double)> xif; + +} |