[cfe-commits] r122520 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/DeclSpec.h include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/ParseTentative.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/SemaType.cpp test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp

Douglas Gregor dgregor at apple.com
Thu Dec 23 14:44:42 PST 2010


Author: dgregor
Date: Thu Dec 23 16:44:42 2010
New Revision: 122520

URL: http://llvm.org/viewvc/llvm-project?rev=122520&view=rev
Log:
Implement parsing of function parameter packs and non-type template
parameter packs (C++0x [dcl.fct]p13), including disambiguation between
unnamed function parameter packs and varargs (C++0x [dcl.fct]p14) for
cases like 

  void f(T...)

where T may or may not contain unexpanded parameter packs.

Added:
    cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseTentative.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=122520&r1=122519&r2=122520&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Dec 23 16:44:42 2010
@@ -1861,6 +1861,12 @@
   "pack expansion contains parameter packs %0 and %1 that have different "
   "lengths (%2 vs. %3)">;
 
+def err_function_parameter_pack_without_parameter_packs : Error<
+  "type %0 of function parameter pack does not contain any unexpanded "
+  "parameter packs">;
+def err_ellipsis_in_declarator_not_parameter : Error<
+  "only function and template parameters can be parameter packs">;
+
 // Unsupported variadic templates features
 def err_pack_expansion_unsupported : Error<
   "clang does not yet support %select{non-type|template}0 pack expansions">;
@@ -1868,6 +1874,10 @@
   "clang cannot yet instantiate pack expansions">;
 def err_pack_expansion_mismatch_unsupported : Error<
   "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/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=122520&r1=122519&r2=122520&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu Dec 23 16:44:42 2010
@@ -1186,6 +1186,10 @@
   /// Extension - true if the declaration is preceded by __extension__.
   bool Extension : 1;
 
+  /// \brief If provided, the source location of the ellipsis used to describe
+  /// this declarator as a parameter pack.
+  SourceLocation EllipsisLoc;
+  
   friend struct DeclaratorChunk;
 
 public:
@@ -1427,6 +1431,10 @@
 
   void setGroupingParens(bool flag) { GroupingParens = flag; }
   bool hasGroupingParens() const { return GroupingParens; }
+  
+  bool hasEllipsis() const { return EllipsisLoc.isValid(); }
+  SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+  void setEllipsisLoc(SourceLocation EL) { EllipsisLoc = EL; }
 };
 
 /// FieldDeclarator - This little struct is used to capture information about

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122520&r1=122519&r2=122520&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Dec 23 16:44:42 2010
@@ -3134,6 +3134,8 @@
                                   const TemplateArgument *Args,
                                   unsigned NumArgs);
 
+#pragma mark C++ Variadic Templates (C++0x [temp.variadic])
+
   /// \brief The context in which an unexpanded parameter pack is
   /// being diagnosed.
   ///
@@ -3325,6 +3327,25 @@
                                        bool &ShouldExpand,
                                        unsigned &NumExpansions);
 
+  /// \brief Determine whether the given declarator contains any unexpanded
+  /// parameter packs.
+  ///
+  /// This routine is used by the parser to disambiguate function declarators
+  /// with an ellipsis prior to the ')', e.g.,
+  ///
+  /// \code
+  ///   void f(T...);
+  /// \endcode
+  ///
+  /// To determine whether we have an (unnamed) function parameter pack or
+  /// a variadic function.
+  ///
+  /// \returns true if the declarator contains any unexpanded parameter packs,
+  /// false otherwise.
+  bool containsUnexpandedParameterPacks(Declarator &D);
+  
+#pragma mark C++ Template Argument Deduction (C++ [temp.deduct])
+
   /// \brief Describes the result of template argument deduction.
   ///
   /// The TemplateDeductionResult enumeration describes the result of

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=122520&r1=122519&r2=122520&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Dec 23 16:44:42 2010
@@ -2819,7 +2819,7 @@
 /// [C++]   declarator-id
 ///
 ///       declarator-id: [C++ 8]
-///         id-expression
+///         '...'[opt] id-expression
 ///         '::'[opt] nested-name-specifier[opt] type-name
 ///
 ///       id-expression: [C++ 5.1]
@@ -2849,6 +2849,21 @@
         DeclScopeObj.EnterDeclaratorScope();
     }
 
+    // C++0x [dcl.fct]p14:
+    //   There is a syntactic ambiguity when an ellipsis occurs at the end
+    //   of a parameter-declaration-clause without a preceding comma. In 
+    //   this case, the ellipsis is parsed as part of the 
+    //   abstract-declarator if the type of the parameter names a template 
+    //   parameter pack that has not been expanded; otherwise, it is parsed
+    //   as part of the parameter-declaration-clause.
+    if (Tok.is(tok::ellipsis) &&
+        !((D.getContext() == Declarator::PrototypeContext ||
+           D.getContext() == Declarator::BlockLiteralContext) &&
+          getCurScope()->getTemplateParamParent() &&
+          NextToken().is(tok::r_paren) &&
+          !Actions.containsUnexpandedParameterPacks(D)))
+      D.setEllipsisLoc(ConsumeToken());
+    
     if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
         Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
       // We found something that indicates the start of an unqualified-id.

Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=122520&r1=122519&r2=122520&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Thu Dec 23 16:44:42 2010
@@ -461,6 +461,7 @@
 ///         abstract-declarator:
 ///           ptr-operator abstract-declarator[opt]
 ///           direct-abstract-declarator
+///           ...
 ///
 ///         direct-abstract-declarator:
 ///           direct-abstract-declarator[opt]
@@ -483,7 +484,7 @@
 ///           'volatile'
 ///
 ///         declarator-id:
-///           id-expression
+///           '...'[opt] id-expression
 ///
 ///         id-expression:
 ///           unqualified-id
@@ -522,7 +523,9 @@
 
   // direct-declarator:
   // direct-abstract-declarator:
-
+  if (Tok.is(tok::ellipsis))
+    ConsumeToken();
+  
   if ((Tok.is(tok::identifier) ||
        (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
       mayHaveIdentifier) {
@@ -566,6 +569,10 @@
   while (1) {
     TPResult TPR(TPResult::Ambiguous());
 
+    // abstract-declarator: ...
+    if (Tok.is(tok::ellipsis))
+      ConsumeToken();
+
     if (Tok.is(tok::l_paren)) {
       // Check whether we have a function declarator or a possible ctor-style
       // initializer that follows the declarator. Note that ctor-style
@@ -1165,8 +1172,8 @@
     if (Tok.is(tok::equal)) {
       // '=' assignment-expression
       // Parse through assignment-expression.
-      tok::TokenKind StopToks[3] ={ tok::comma, tok::ellipsis, tok::r_paren };
-      if (!SkipUntil(StopToks, 3, true/*StopAtSemi*/, true/*DontConsume*/))
+      tok::TokenKind StopToks[2] ={ tok::comma, tok::r_paren };
+      if (!SkipUntil(StopToks, 2, true/*StopAtSemi*/, true/*DontConsume*/))
         return TPResult::Error();
     }
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=122520&r1=122519&r2=122520&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Dec 23 16:44:42 2010
@@ -4959,20 +4959,34 @@
 
   DiagnoseFunctionSpecifiers(D);
 
-  // Check that there are no default arguments inside the type of this
-  // parameter (C++ only).
-  if (getLangOptions().CPlusPlus)
-    CheckExtraCXXDefaultArguments(D);
-
   TagDecl *OwnedDecl = 0;
   TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl);
   QualType parmDeclType = TInfo->getType();
 
-  if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) {
-    // C++ [dcl.fct]p6:
-    //   Types shall not be defined in return or parameter types.
-    Diag(OwnedDecl->getLocation(), diag::err_type_defined_in_param_type)
-      << Context.getTypeDeclType(OwnedDecl);
+  if (getLangOptions().CPlusPlus) {
+    // Check that there are no default arguments inside the type of this
+    // parameter.
+    CheckExtraCXXDefaultArguments(D);
+     
+    if (OwnedDecl && OwnedDecl->isDefinition()) {
+      // C++ [dcl.fct]p6:
+      //   Types shall not be defined in return or parameter types.
+      Diag(OwnedDecl->getLocation(), diag::err_type_defined_in_param_type)
+        << Context.getTypeDeclType(OwnedDecl);
+    }
+    
+    // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
+    if (D.getCXXScopeSpec().isSet()) {
+      Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator)
+        << D.getCXXScopeSpec().getRange();
+      D.getCXXScopeSpec().clear();
+    }
+
+    // FIXME: Variadic templates.
+    if (D.hasEllipsis()) {
+      Diag(D.getEllipsisLoc(), diag::err_function_parameter_pack_unsupported);
+      D.setInvalidType();
+    }
   }
 
   // Ensure we have a valid name
@@ -5021,13 +5035,6 @@
   if (D.isInvalidType())
     New->setInvalidDecl();  
   
-  // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
-  if (D.getCXXScopeSpec().isSet()) {
-    Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator)
-      << D.getCXXScopeSpec().getRange();
-    New->setInvalidDecl();
-  }
-
   // Add the parameter declaration into this scope.
   S->AddDecl(New);
   if (II)

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=122520&r1=122519&r2=122520&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Dec 23 16:44:42 2010
@@ -632,6 +632,12 @@
     Invalid = true;
   }
   
+  if (D.hasEllipsis()) {
+    // FIXME: Variadic templates.
+    Diag(D.getEllipsisLoc(), diag::err_non_type_parameter_pack_unsupported);
+    Invalid = true;
+  }
+      
   NonTypeTemplateParmDecl *Param
     = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
                                       D.getIdentifierLoc(),

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=122520&r1=122519&r2=122520&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Thu Dec 23 16:44:42 2010
@@ -413,3 +413,72 @@
   
   return false;
 }
+
+bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
+  const DeclSpec &DS = D.getDeclSpec();
+  switch (DS.getTypeSpecType()) {
+  case TST_typename:
+  case TST_typeofType: {
+    QualType T = DS.getRepAsType().get();
+    if (!T.isNull() && T->containsUnexpandedParameterPack())
+      return true;
+    break;
+  }
+      
+  case TST_typeofExpr:
+  case TST_decltype:
+    if (DS.getRepAsExpr() && 
+        DS.getRepAsExpr()->containsUnexpandedParameterPack())
+      return true;
+    break;
+      
+  case TST_unspecified:
+  case TST_void:
+  case TST_char:
+  case TST_wchar:
+  case TST_char16:
+  case TST_char32:
+  case TST_int:
+  case TST_float:
+  case TST_double:
+  case TST_bool:
+  case TST_decimal32:
+  case TST_decimal64:
+  case TST_decimal128:
+  case TST_enum:
+  case TST_union:
+  case TST_struct:
+  case TST_class:
+  case TST_auto:
+  case TST_error:
+    break;
+  }
+  
+  for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
+    const DeclaratorChunk &Chunk = D.getTypeObject(I);
+    switch (Chunk.Kind) {
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::Paren:
+      // These declarator chunks cannot contain any parameter packs.
+      break;
+        
+    case DeclaratorChunk::Array:
+    case DeclaratorChunk::Function:
+    case DeclaratorChunk::BlockPointer:
+      // Syntactically, these kinds of declarator chunks all come after the
+      // declarator-id (conceptually), so the parser should not invoke this
+      // routine at this time.
+      llvm_unreachable("Could not have seen this kind of declarator chunk");
+      break;
+        
+    case DeclaratorChunk::MemberPointer:
+      if (Chunk.Mem.Scope().getScopeRep() &&
+          Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack())
+        return true;
+      break;
+    }
+  }
+  
+  return false;
+}

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=122520&r1=122519&r2=122520&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Dec 23 16:44:42 2010
@@ -1465,6 +1465,64 @@
     T.addConst();
   }
 
+  // If there was an ellipsis in the declarator, the declaration declares a 
+  // parameter pack whose type may be a pack expansion type.
+  if (D.hasEllipsis() && !T.isNull()) {
+    // C++0x [dcl.fct]p13:
+    //   A declarator-id or abstract-declarator containing an ellipsis shall 
+    //   only be used in a parameter-declaration. Such a parameter-declaration
+    //   is a parameter pack (14.5.3). [...]
+    switch (D.getContext()) {
+    case Declarator::PrototypeContext:
+      // C++0x [dcl.fct]p13:
+      //   [...] When it is part of a parameter-declaration-clause, the 
+      //   parameter pack is a function parameter pack (14.5.3). The type T 
+      //   of the declarator-id of the function parameter pack shall contain
+      //   a template parameter pack; each template parameter pack in T is 
+      //   expanded by the function parameter pack.
+      //
+      // We represent function parameter packs as function parameters whose
+      // type is a pack expansion.
+      if (!T->containsUnexpandedParameterPack()) {
+        Diag(D.getEllipsisLoc(), 
+             diag::err_function_parameter_pack_without_parameter_packs)
+          << T <<  D.getSourceRange();
+        D.setEllipsisLoc(SourceLocation());
+      } else {
+        T = Context.getPackExpansionType(T);
+      }
+      break;
+        
+    case Declarator::TemplateParamContext:
+      // C++0x [temp.param]p15:
+      //   If a template-parameter is a [...] is a parameter-declaration that 
+      //   declares a parameter pack (8.3.5), then the template-parameter is a
+      //   template parameter pack (14.5.3).
+      //
+      // Note: core issue 778 clarifies that, if there are any unexpanded
+      // parameter packs in the type of the non-type template parameter, then
+      // it expands those parameter packs.
+      if (T->containsUnexpandedParameterPack())
+        T = Context.getPackExpansionType(T);
+      break;
+    
+    case Declarator::FileContext:
+    case Declarator::KNRTypeListContext:
+    case Declarator::TypeNameContext:
+    case Declarator::MemberContext:
+    case Declarator::BlockContext:
+    case Declarator::ForContext:
+    case Declarator::ConditionContext:
+    case Declarator::CXXCatchContext:
+    case Declarator::BlockLiteralContext:
+      // FIXME: We may want to allow parameter packs in block-literal contexts
+      // in the future.
+      Diag(D.getEllipsisLoc(), diag::err_ellipsis_in_declarator_not_parameter);
+      D.setEllipsisLoc(SourceLocation());
+      break;
+    }
+  }
+  
   // Process any function attributes we might have delayed from the
   // declaration-specifiers.
   ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec);
@@ -1729,6 +1787,12 @@
   TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
   UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
 
+  // Handle parameter packs whose type is a pack expansion.
+  if (isa<PackExpansionType>(T)) {
+    cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc());
+    CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();    
+  }
+  
   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
     DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL);
     CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();

Added: 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=122520&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp Thu Dec 23 16:44:42 2010
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -fexceptions -verify %s
+
+// When it is part of a parameter-declaration-clause, the parameter
+// pack is a function parameter pack.
+template<typename ...Types>
+void f0(Types ...args); // FIXME: temporary expected-error{{clang does not yet support function parameter packs}}
+
+template<typename ...Types>
+void f1(const Types &...args); // FIXME: temporary expected-error{{clang does not yet support function parameter packs}}
+
+// [ 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}}
+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}}
+};
+
+// A declarator-id or abstract-declarator containing an ellipsis shall
+// only be used in a parameter-declaration.
+int (...f2)(int); // expected-error{{only function and template parameters can be parameter packs}}
+
+void f3() {
+  int ...x; // expected-error{{only function and template parameters can be parameter packs}}
+  if (int ...y = 17) { }  // expected-error{{only function and template parameters can be parameter packs}}
+
+  for (int ...z = 0; z < 10; ++z) { }  // expected-error{{only function and template parameters can be parameter packs}}
+
+  try {
+  } catch (int ...e) { // expected-error{{only function and template parameters can be parameter packs}}
+  }
+}
+
+template<typename ...Types>
+struct X2 {
+  Types ...members; // expected-error{{only function and template parameters can be parameter packs}} \
+                    // expected-error{{data member type contains unexpanded parameter pack}}
+};
+
+// The type T of the declarator-id of the function parameter pack
+// shall contain a template parameter pack; each template parameter
+// pack in T is expanded by the function parameter pack.
+template<typename T>
+void f4(T ...args); // expected-error{{type 'T' of function parameter pack does not contain any unexpanded parameter packs}}
+

Added: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp?rev=122520&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp Thu Dec 23 16:44:42 2010
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename T> struct identity;
+template<typename ...Types> struct tuple;
+
+template<typename T, typename U> struct is_same {
+  static const bool value = false;
+};
+
+template<typename T> struct is_same<T, T> {
+  static const bool value = true;
+};
+
+// There is a syntactic ambiguity when an ellipsis occurs at the end
+// of a parameter-declaration-clause without a preceding comma. In
+// this case, the ellipsis is parsed as part of the
+// abstract-declarator if the type of the parameter names a template
+// parameter pack that has not been expanded; otherwise, it is parsed
+// as part of the parameter-declaration-clause.
+
+template<typename T, typename ...Types>
+struct X0 {
+  typedef identity<T(Types...)> function_pack_1; // expected-error{{clang does not yet support function parameter packs}}
+  typedef identity<T(Types......)> variadic_function_pack_1;  // expected-error{{clang does not yet support function parameter packs}}
+  typedef identity<T(T...)> variadic_1;
+  typedef tuple<T(Types, ...)...> template_arg_expansion_1;
+};
+
+
+
+// FIXME: Once function parameter packs are implemented, we can test all of the disambiguation





More information about the cfe-commits mailing list