[cfe-commits] r122297 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/TreeTransform.h test/CXX/temp/temp.decls/temp.variadic/p4.cpp

Douglas Gregor dgregor at apple.com
Mon Dec 20 16:52:54 PST 2010


Author: dgregor
Date: Mon Dec 20 18:52:54 2010
New Revision: 122297

URL: http://llvm.org/viewvc/llvm-project?rev=122297&view=rev
Log:
Implement instantiation of pack expansions whose pattern is a type-id
in an exception specification.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Dec 20 18:52:54 2010
@@ -3249,7 +3249,15 @@
   /// unexpanded parameter packs.
   void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
                     llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
-                                       
+
+  /// \brief Collect the set of unexpanded parameter packs within the given
+  /// type.  
+  ///
+  /// \param Arg The template argument that will be traversed to find
+  /// unexpanded parameter packs.
+  void collectUnexpandedParameterPacks(QualType T,
+                   llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
   /// \brief Invoked when parsing a template argument followed by an
   /// ellipsis, which creates a pack expansion.
   ///
@@ -3274,6 +3282,42 @@
   TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
                                      SourceLocation EllipsisLoc);
   
+  /// \brief Determine whether we could expand a pack expansion with the
+  /// given set of parameter packs into separate arguments by repeatedly
+  /// transforming the pattern.
+  ///
+  /// \param EllipsisLoc The location of the ellipsis that identifies the
+  /// pack expansion.
+  ///
+  /// \param PatternRange The source range that covers the entire pattern of
+  /// the pack expansion.
+  ///
+  /// \param Unexpanded The set of unexpanded parameter packs within the 
+  /// pattern.
+  ///
+  /// \param NumUnexpanded The number of unexpanded parameter packs in
+  /// \p Unexpanded.
+  ///
+  /// \param ShouldExpand Will be set to \c true if the transformer should
+  /// expand the corresponding pack expansions into separate arguments. When
+  /// set, \c NumExpansions must also be set.
+  ///
+  /// \param NumExpansions The number of separate arguments that will be in
+  /// the expanded form of the corresponding pack expansion. Must be set when
+  /// \c ShouldExpand is \c true.
+  ///
+  /// \returns true if an error occurred (e.g., because the parameter packs 
+  /// are to be instantiated with arguments of different lengths), false 
+  /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions) 
+  /// must be set.
+  bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
+                                       SourceRange PatternRange,
+                                     const UnexpandedParameterPack *Unexpanded,
+                                       unsigned NumUnexpanded,
+                             const MultiLevelTemplateArgumentList &TemplateArgs,
+                                       bool &ShouldExpand,
+                                       unsigned &NumExpansions);
+
   /// \brief Describes the result of template argument deduction.
   ///
   /// The TemplateDeductionResult enumeration describes the result of

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Dec 20 18:52:54 2010
@@ -595,7 +595,14 @@
                                  const UnexpandedParameterPack *Unexpanded,
                                  unsigned NumUnexpanded,
                                  bool &ShouldExpand,
-                                 unsigned &NumExpansions);
+                                 unsigned &NumExpansions) {
+      return getSema().CheckParameterPacksForExpansion(EllipsisLoc, 
+                                                       PatternRange, Unexpanded,
+                                                       NumUnexpanded, 
+                                                       TemplateArgs, 
+                                                       ShouldExpand,
+                                                       NumExpansions);
+    }
 
     /// \brief Transform the given declaration by instantiating a reference to
     /// this declaration.
@@ -663,79 +670,6 @@
   return true;
 }
 
-bool TemplateInstantiator::TryExpandParameterPacks(SourceLocation EllipsisLoc,
-                                                   SourceRange PatternRange,
-                                     const UnexpandedParameterPack *Unexpanded,
-                                                   unsigned NumUnexpanded,
-                                                   bool &ShouldExpand,
-                                                   unsigned &NumExpansions) {
-  ShouldExpand = true;
-  std::pair<IdentifierInfo *, SourceLocation> FirstPack;
-  bool HaveFirstPack = false;
-  
-  for (unsigned I = 0; I != NumUnexpanded; ++I) {
-    // Compute the depth and index for this parameter pack.
-    unsigned Depth;
-    unsigned Index;
-    IdentifierInfo *Name;
-    
-    if (const TemplateTypeParmType *TTP
-              = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
-      Depth = TTP->getDepth();
-      Index = TTP->getIndex();
-      Name = TTP->getName();
-    } else {
-      NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
-      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) {
-        Depth = TTP->getDepth();
-        Index = TTP->getIndex();
-      } else if (NonTypeTemplateParmDecl *NTTP
-                                      = dyn_cast<NonTypeTemplateParmDecl>(ND)) {        
-        Depth = NTTP->getDepth();
-        Index = NTTP->getIndex();
-      } else {
-        TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
-        Depth = TTP->getDepth();
-        Index = TTP->getIndex();
-      }
-      // FIXME: Variadic templates function parameter packs?
-      Name = ND->getIdentifier();
-    }
-    
-    // If we don't have a template argument at this depth/index, then we 
-    // cannot expand the pack expansion. Make a note of this, but we still 
-    // want to check that any parameter packs we *do* have arguments for.
-    if (!TemplateArgs.hasTemplateArgument(Depth, Index)) {
-      ShouldExpand = false;
-      continue;
-    }
-
-    // Determine the size of the argument pack.
-    unsigned NewPackSize = TemplateArgs(Depth, Index).pack_size();
-    if (!HaveFirstPack) {
-      // The is the first pack we've seen for which we have an argument. 
-      // Record it.
-      NumExpansions = NewPackSize;
-      FirstPack.first = Name;
-      FirstPack.second = Unexpanded[I].second;
-      HaveFirstPack = true;
-      continue;
-    }
-    
-    if (NewPackSize != NumExpansions) {
-      // C++0x [temp.variadic]p5:
-      //   All of the parameter packs expanded by a pack expansion shall have 
-      //   the same number of arguments specified.
-      getSema().Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
-        << FirstPack.first << Name << NumExpansions << NewPackSize
-        << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
-      return true;
-    }
-  }
-  
-  return false;
-}
-
 Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
   if (!D)
     return 0;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Dec 20 18:52:54 2010
@@ -1983,6 +1983,61 @@
     llvm::SmallVector<QualType, 4> Exceptions;
     for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
       // FIXME: Poor location information!
+      if (const PackExpansionType *PackExpansion
+            = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
+        // We have a pack expansion. Instantiate it.
+        llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+        SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
+                                                Unexpanded);
+        assert(!Unexpanded.empty() && 
+               "Pack expansion without parameter packs?");
+        
+        bool Expand = false;
+        unsigned NumExpansions = 0;
+        if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(), 
+                                                    SourceRange(),
+                                                    Unexpanded.data(), 
+                                                    Unexpanded.size(),
+                                                    TemplateArgs,
+                                                    Expand, NumExpansions))
+          break;
+                      
+        if (!Expand) {
+          // We can't expand this pack expansion into separate arguments yet;
+          // just substitute into the argument pack.
+          Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
+          QualType T = SemaRef.SubstType(PackExpansion->getPattern(), 
+                                         TemplateArgs,
+                                       New->getLocation(), New->getDeclName());
+          if (T.isNull())
+            break;
+          
+          Exceptions.push_back(T);
+          continue;
+        }
+        
+        // Substitute into the pack expansion pattern for each template
+        bool Invalid = false;
+        for (unsigned ArgIdx = 0; ArgIdx != NumExpansions; ++ArgIdx) {
+          Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
+          
+          QualType T = SemaRef.SubstType(PackExpansion->getPattern(), 
+                                         TemplateArgs,
+                                       New->getLocation(), New->getDeclName());
+          if (T.isNull()) {
+            Invalid = true;
+            break;
+          }
+          
+          Exceptions.push_back(T);
+        }
+        
+        if (Invalid)
+          break;
+        
+        continue;
+      }
+      
       QualType T
         = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
                             New->getLocation(), New->getDeclName());

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Mon Dec 20 18:52:54 2010
@@ -259,6 +259,11 @@
     .TraverseTemplateArgumentLoc(Arg);
 }
 
+void Sema::collectUnexpandedParameterPacks(QualType T,
+                   llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);  
+}  
+
 ParsedTemplateArgument 
 Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
                          SourceLocation EllipsisLoc) {
@@ -327,3 +332,78 @@
          Pattern->getTypeLoc().getFullDataSize());
   return TSResult;
 }
+
+
+bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
+                                           SourceRange PatternRange,
+                                     const UnexpandedParameterPack *Unexpanded,
+                                           unsigned NumUnexpanded,
+                             const MultiLevelTemplateArgumentList &TemplateArgs,
+                                           bool &ShouldExpand,
+                                           unsigned &NumExpansions) {                                        
+  ShouldExpand = true;
+  std::pair<IdentifierInfo *, SourceLocation> FirstPack;
+  bool HaveFirstPack = false;
+  
+  for (unsigned I = 0; I != NumUnexpanded; ++I) {
+    // Compute the depth and index for this parameter pack.
+    unsigned Depth;
+    unsigned Index;
+    IdentifierInfo *Name;
+    
+    if (const TemplateTypeParmType *TTP
+        = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+      Depth = TTP->getDepth();
+      Index = TTP->getIndex();
+      Name = TTP->getName();
+    } else {
+      NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
+      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) {
+        Depth = TTP->getDepth();
+        Index = TTP->getIndex();
+      } else if (NonTypeTemplateParmDecl *NTTP
+                 = dyn_cast<NonTypeTemplateParmDecl>(ND)) {        
+        Depth = NTTP->getDepth();
+        Index = NTTP->getIndex();
+      } else {
+        TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+        Depth = TTP->getDepth();
+        Index = TTP->getIndex();
+      }
+      // FIXME: Variadic templates function parameter packs?
+      Name = ND->getIdentifier();
+    }
+    
+    // If we don't have a template argument at this depth/index, then we 
+    // cannot expand the pack expansion. Make a note of this, but we still 
+    // want to check that any parameter packs we *do* have arguments for.
+    if (!TemplateArgs.hasTemplateArgument(Depth, Index)) {
+      ShouldExpand = false;
+      continue;
+    }
+    
+    // Determine the size of the argument pack.
+    unsigned NewPackSize = TemplateArgs(Depth, Index).pack_size();
+    if (!HaveFirstPack) {
+      // The is the first pack we've seen for which we have an argument. 
+      // Record it.
+      NumExpansions = NewPackSize;
+      FirstPack.first = Name;
+      FirstPack.second = Unexpanded[I].second;
+      HaveFirstPack = true;
+      continue;
+    }
+    
+    if (NewPackSize != NumExpansions) {
+      // C++0x [temp.variadic]p5:
+      //   All of the parameter packs expanded by a pack expansion shall have 
+      //   the same number of arguments specified.
+      Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
+        << FirstPack.first << Name << NumExpansions << NewPackSize
+        << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
+      return true;
+    }
+  }
+  
+  return false;
+}

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Dec 20 18:52:54 2010
@@ -91,11 +91,10 @@
 class TreeTransform {
 protected:
   Sema &SemaRef;
-  Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
   
 public:
   /// \brief Initializes a new tree transformer.
-  TreeTransform(Sema &SemaRef) : SemaRef(SemaRef), SubstIndex(SemaRef, -1) { }
+  TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
 
   /// \brief Retrieves a reference to the derived class.
   Derived &getDerived() { return static_cast<Derived&>(*this); }
@@ -186,7 +185,7 @@
   /// given set of parameter packs into separate arguments by repeatedly
   /// transforming the pattern.
   ///
-  /// By default, the transformed never tries to expand pack expansions.
+  /// By default, the transformer never tries to expand pack expansions.
   /// Subclasses can override this routine to provide different behavior.
   ///
   /// \param EllipsisLoc The location of the ellipsis that identifies the

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp Mon Dec 20 18:52:54 2010
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -fexceptions -verify %s
 
 template<typename... Types> struct tuple;
 
@@ -30,12 +30,9 @@
 // In a dynamic-exception-specification (15.4); the pattern is a type-id.
 template<typename ...Types>
 struct f_with_except {
-  virtual void f() throw(Types...);
+  virtual void f() throw(Types...); // expected-note{{overridden virtual function is here}}
 };
 
-// FIXME: the code below requires the ability to instantiate pack
-// expansions whose pattern is a type-id.
-#if 0
 struct check_f_with_except_1 : f_with_except<int, float> {
   virtual void f() throw(int, float);
 };
@@ -43,4 +40,7 @@
 struct check_f_with_except_2 : f_with_except<int, float> {
   virtual void f() throw(int);
 };
-#endif
+
+struct check_f_with_except_3 : f_with_except<int, float> {
+  virtual void f() throw(int, float, double); // expected-error{{exception specification of overriding function is more lax than base version}}
+};





More information about the cfe-commits mailing list