[cfe-commits] r123316 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplateVariadic.cpp lib/Sema/TreeTransform.h test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp

Douglas Gregor dgregor at apple.com
Wed Jan 12 09:07:58 PST 2011


Author: dgregor
Date: Wed Jan 12 11:07:58 2011
New Revision: 123316

URL: http://llvm.org/viewvc/llvm-project?rev=123316&view=rev
Log:
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 <rdar://problem/8848837> (Clang crashing on libc++ <functional>).

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

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=123316&r1=123315&r2=123316&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Jan 12 11:07:58 2011
@@ -3331,7 +3331,13 @@
   /// 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.
   ///

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=123316&r1=123315&r2=123316&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Wed Jan 12 11:07:58 2011
@@ -377,18 +377,13 @@
 
 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 @@
   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();

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=123316&r1=123315&r2=123316&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Jan 12 11:07:58 2011
@@ -808,6 +808,16 @@
     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 @@
 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>

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp?rev=123316&r1=123315&r2=123316&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp Wed Jan 12 11:07:58 2011
@@ -39,3 +39,21 @@
 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;
+
+}





More information about the cfe-commits mailing list