]> granicus.if.org Git - clang/commitdiff
Teach TreeTransform how to transform a pack expansion type into
authorDouglas Gregor <dgregor@apple.com>
Wed, 12 Jan 2011 17:07:58 +0000 (17:07 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 12 Jan 2011 17:07:58 +0000 (17:07 +0000)
another pack expansion type. This can happen when rebuilding types in
the current instantiation.

Fixes <rdar://problem/8848837> (Clang crashing on libc++ <functional>).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123316 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaTemplateVariadic.cpp
lib/Sema/TreeTransform.h
test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp

index df4e4dc48ceb2aa34e255aacfeb6838da5fe2d99..1b22cd8ad71aeca724680a4407ffa466d2c2b450 100644 (file)
@@ -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.
   ///
index 63a8394d67a41794942ccf957a7a0b120a479c7b..473dcb7d1fa693896e7e94eafffba62ebea0515e 100644 (file)
@@ -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();
index e63cc7da7c75c8a67b2e120f30beb6c0e6c958f4..f601d5c047c004ad3f607306246d43fbb3e6ef9c 100644 (file)
@@ -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>
index bcdbe5351eb9519a2563523286adc28abe6e5542..36621ecf5aecc68600202e6489238703e8adff21 100644 (file)
@@ -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;
+
+}