[cfe-commits] r122527 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/AST/ lib/Sema/ lib/Serialization/ test/CXX/dcl.decl/dcl.meaning/dcl.fct/ test/CXX/temp/temp.decls/temp.variadic/

Douglas Gregor dgregor at apple.com
Thu Dec 23 15:51:58 PST 2010


Author: dgregor
Date: Thu Dec 23 17:51:58 2010
New Revision: 122527

URL: http://llvm.org/viewvc/llvm-project?rev=122527&view=rev
Log:
Add an AST representation for non-type template parameter
packs, e.g.,

  template<typename T, unsigned ...Dims> struct multi_array;

along with semantic analysis support for finding unexpanded non-type
template parameter packs in types, expressions, and so on.

Template instantiation involving non-type template parameter packs
probably doesn't work yet. That'll come soon.


Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Thu Dec 23 17:51:58 2010
@@ -990,17 +990,27 @@
   /// it was inherited.
   llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited;
 
+  // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
+  // down here to save memory.
+    
+  /// \brief Whether this non-type template parameter is a parameter pack.
+  bool ParameterPack;
+    
   NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
                           unsigned P, IdentifierInfo *Id, QualType T,
-                          TypeSourceInfo *TInfo)
+                          bool ParameterPack, TypeSourceInfo *TInfo)
     : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
-      TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false)
+      TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
+      ParameterPack(ParameterPack)
   { }
 
+  friend class ASTDeclReader;
+    
 public:
   static NonTypeTemplateParmDecl *
   Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
-         unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo);
+         unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, 
+         TypeSourceInfo *TInfo);
 
   using TemplateParmPosition::getDepth;
   using TemplateParmPosition::setDepth;
@@ -1042,6 +1052,17 @@
     DefaultArgumentAndInherited.setInt(false);
   }
 
+  /// \brief Whether this parameter is a non-type template parameter pack.
+  ///
+  /// If the parameter is a parameter pack, the type may be a
+  /// \c PackExpansionType. In the following example, the \c Dims parameter
+  /// is a parameter pack (whose type is 'unsigned').
+  ///
+  /// \code
+  /// template<typename T, unsigned ...Dims> struct multi_array;
+  /// \endcode
+  bool isParameterPack() const { return ParameterPack; }
+    
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classof(const NonTypeTemplateParmDecl *D) { return true; }

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Thu Dec 23 17:51:58 2010
@@ -3564,6 +3564,7 @@
   Stmt *CopyConstructorVal;
 public:
   // FIXME: Fix type/value dependence!
+  // FIXME: Variadic templates.
   BlockDeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK,
                    SourceLocation l, bool ByRef, bool constAdded = false,
                    Stmt *copyConstructorVal = 0)

Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Thu Dec 23 17:51:58 2010
@@ -47,6 +47,8 @@
 def err_invalid_storage_class_in_func_decl : Error<
   "invalid storage class specifier in function declarator">;
 def err_expected_namespace_name : Error<"expected namespace name">;
+def err_variadic_templates : Error<
+  "variadic templates are only allowed in C++0x">;
 
 // Sema && Lex
 def ext_longlong : Extension<

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Dec 23 17:51:58 2010
@@ -374,9 +374,6 @@
 def err_explicit_spec_non_template : Error<
   "explicit %select{specialization|instantiation}0 of non-template "
   "%select{class|struct|union}1 %2">;
-
-def err_variadic_templates : Error<
-  "variadic templates are only allowed in C++0x">;
   
 def err_default_template_template_parameter_not_template : Error<
   "default template argument for a template template parameter must be a class "

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Dec 23 17:51:58 2010
@@ -1876,8 +1876,6 @@
   "clang cannot yet instantiate pack expansions with mismatched pack levels">;
 def err_function_parameter_pack_unsupported : Error<
   "clang does not yet support function parameter packs">;
-def err_non_type_parameter_pack_unsupported : Error<
-  "clang does not yet support non-type template parameter packs">;
 
 def err_unexpected_typedef : Error<
   "unexpected type name %0: expected expression">;

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Dec 23 17:51:58 2010
@@ -109,6 +109,7 @@
                                             SourceLocation(), NTTP->getDepth(),
                                             NTTP->getPosition(), 0, 
                                             getCanonicalType(NTTP->getType()),
+                                            NTTP->isParameterPack(),
                                             0));
     else
       CanonParams.push_back(getCanonicalTemplateTemplateParmDecl(

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Dec 23 17:51:58 2010
@@ -3414,7 +3414,7 @@
                                Importer.getToContext().getTranslationUnitDecl(),
                                          Loc, D->getDepth(), D->getPosition(),
                                          Name.getAsIdentifierInfo(),
-                                         T, TInfo);
+                                         T, D->isParameterPack(), TInfo);
 }
 
 Decl *

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Thu Dec 23 17:51:58 2010
@@ -110,7 +110,9 @@
 bool Decl::isTemplateParameterPack() const {
   if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(this))
     return TTP->isParameterPack();
-
+  if (const NonTypeTemplateParmDecl *NTTP
+                                = llvm::dyn_cast<NonTypeTemplateParmDecl>(this))
+    return NTTP->isParameterPack();
   return false;
 }
 

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Thu Dec 23 17:51:58 2010
@@ -390,8 +390,9 @@
 NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
                                 SourceLocation L, unsigned D, unsigned P,
                                 IdentifierInfo *Id, QualType T,
-                                TypeSourceInfo *TInfo) {
-  return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, TInfo);
+                                bool ParameterPack, TypeSourceInfo *TInfo) {
+  return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, ParameterPack,
+                                         TInfo);
 }
 
 SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu Dec 23 17:51:58 2010
@@ -208,8 +208,14 @@
   //          member of an unknown specialization.
   //        (handled by DependentScopeDeclRefExpr)
 
-  // FIXME: Variadic templates require that we compute whether this
-  // declaration reference contains an unexpanded parameter pack.
+  // Determine whether this expression contains any unexpanded parameter
+  // packs.
+  // Is the declaration a parameter pack?
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+    if (NTTP->isParameterPack())
+      ExprBits.ContainsUnexpandedParameterPack = true;
+  }
+  // FIXME: Variadic templates function parameter packs.
 }
 
 DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Dec 23 17:51:58 2010
@@ -632,16 +632,12 @@
     Invalid = true;
   }
   
-  if (D.hasEllipsis()) {
-    // FIXME: Variadic templates.
-    Diag(D.getEllipsisLoc(), diag::err_non_type_parameter_pack_unsupported);
-    Invalid = true;
-  }
-      
+  bool IsParameterPack = D.hasEllipsis();
   NonTypeTemplateParmDecl *Param
     = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
                                       D.getIdentifierLoc(),
-                                      Depth, Position, ParamName, T, TInfo);
+                                      Depth, Position, ParamName, T, 
+                                      IsParameterPack, TInfo);
   if (Invalid)
     Param->setInvalidDecl();
 
@@ -652,7 +648,7 @@
   }
   
   // Check the well-formedness of the default template argument, if provided.
-  if (Default) {  
+  if (Default) {
     // Check for unexpanded parameter packs.
     if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
       return Param;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Dec 23 17:51:58 2010
@@ -1506,11 +1506,12 @@
     Invalid = true;
   }
   
+  // FIXME: Variadic templates.
   NonTypeTemplateParmDecl *Param
     = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
                                     D->getDepth() - TemplateArgs.getNumLevels(), 
                                       D->getPosition(), D->getIdentifier(), T, 
-                                      DI);
+                                      D->isParameterPack(), DI);
   if (Invalid)
     Param->setInvalidDecl();
   

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Thu Dec 23 17:51:58 2010
@@ -63,8 +63,21 @@
       return true;
     }
 
-    // FIXME: Record occurrences of non-type and template template
-    // parameter packs.
+    /// \brief Record occurrences of (FIXME: function and) non-type template
+    /// parameter packs in an expression.
+    bool VisitDeclRefExpr(DeclRefExpr *E) {
+      if (NonTypeTemplateParmDecl *NTTP 
+                            = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
+        if (NTTP->isParameterPack())
+          Unexpanded.push_back(std::make_pair(NTTP, E->getLocation()));
+      }
+      
+      // FIXME: Function parameter packs.
+      
+      return true;
+    }
+    
+    // FIXME: Record occurrences of template template parameter packs.
 
     // FIXME: Once we have pack expansions in the AST, block their
     // traversal.
@@ -95,8 +108,8 @@
     /// \brief Suppress traversel into types with location information
     /// that do not contain unexpanded parameter packs.
     bool TraverseTypeLoc(TypeLoc TL) {
-      if (!TL.getType().isNull() && TL.
-          getType()->containsUnexpandedParameterPack())
+      if (!TL.getType().isNull() && 
+          TL.getType()->containsUnexpandedParameterPack())
         return inherited::TraverseTypeLoc(TL);
 
       return true;

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Dec 23 17:51:58 2010
@@ -1504,6 +1504,8 @@
       // it expands those parameter packs.
       if (T->containsUnexpandedParameterPack())
         T = Context.getPackExpansionType(T);
+      else if (!getLangOptions().CPlusPlus0x)
+        Diag(D.getEllipsisLoc(), diag::err_variadic_templates);
       break;
     
     case Declarator::FileContext:

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Dec 23 17:51:58 2010
@@ -1156,6 +1156,7 @@
   D->setDepth(Record[Idx++]);
   D->setPosition(Record[Idx++]);
   // Rest of NonTypeTemplateParmDecl.
+  D->ParameterPack = Record[Idx++];
   if (Record[Idx++]) {
     Expr *DefArg = Reader.ReadExpr(F);
     bool Inherited = Record[Idx++];
@@ -1429,7 +1430,7 @@
     break;
   case DECL_NON_TYPE_TEMPLATE_PARM:
     D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,
-                                        QualType(),0);
+                                        QualType(), false, 0);
     break;
   case DECL_TEMPLATE_TEMPLATE_PARM:
     D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(),0,0,0,0);

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Thu Dec 23 17:51:58 2010
@@ -994,6 +994,7 @@
   Record.push_back(D->getDepth());
   Record.push_back(D->getPosition());
   // Rest of NonTypeTemplateParmDecl.
+  Record.push_back(D->isParameterPack());
   Record.push_back(D->getDefaultArgument() != 0);
   if (D->getDefaultArgument()) {
     Writer.AddStmt(D->getDefaultArgument());

Modified: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp Thu Dec 23 17:51:58 2010
@@ -11,12 +11,12 @@
 // [ Note: Otherwise, the parameter-declaration is part of a
 // template-parameter-list and the parameter pack is a template
 // parameter pack; see 14.1. -- end note ]
-template<int ...N> // FIXME: temporary expected-error{{clang does not yet support non-type template parameter packs}}
+template<int ...N>
 struct X0 { };
 
 template<typename ...Types>
 struct X1 {
-  template<Types ...Values> struct Inner; // FIXME: temporary expected-error{{clang does not yet support non-type template parameter packs}}
+  template<Types ...Values> struct Inner;
 };
 
 // A declarator-id or abstract-declarator containing an ellipsis shall

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp?rev=122527&r1=122526&r2=122527&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp Thu Dec 23 17:51:58 2010
@@ -128,6 +128,26 @@
 };
 
 // FIXME: Test for unexpanded parameter packs in each of the expression nodes.
+template<int ...Values>
+void test_unexpanded_in_exprs() {
+  // PredefinedExpr is uninteresting
+  // DeclRefExpr
+  Values; // expected-error{{expression contains unexpanded parameter pack 'Values'}}
+  // IntegerLiteral is uninteresting
+  // FloatingLiteral is uninteresting
+  // ImaginaryLiteral is uninteresting
+  // StringLiteral is uninteresting
+  // CharacterLiteral is uninteresting
+  (Values); // expected-error{{expression contains unexpanded parameter pack 'Values'}}
+  // UnaryOperator
+  -Values; // expected-error{{expression contains unexpanded parameter pack 'Values'}}
+  // OffsetOfExpr
+  struct OffsetMe {
+    int array[17];
+  };
+  __builtin_offsetof(OffsetMe, array[Values]); // expected-error{{expression contains unexpanded parameter pack 'Values'}}
+  // FIXME: continue this...
+}
 
 template<typename ... Types>
 void TestPPNameFunc(int i) {





More information about the cfe-commits mailing list