]> granicus.if.org Git - clang/commitdiff
Check for unexpanded parameter packs in default arguments.
authorDouglas Gregor <dgregor@apple.com>
Thu, 16 Dec 2010 08:48:57 +0000 (08:48 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 16 Dec 2010 08:48:57 +0000 (08:48 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121962 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateVariadic.cpp
test/CXX/temp/temp.decls/temp.variadic/p5.cpp

index 617bc62bc9aa80ea09842bec4e939d5778d4327c..1d3239b3d47d8c94e0102f2b037390dc0637260d 100644 (file)
@@ -1824,22 +1824,26 @@ def note_template_parameter_pack_here : Note<
 def err_unexpanded_parameter_pack_0 : Error<
   "%select{expression|base type|declaration type|data member type|bit-field "
   "size|static assertion|fixed underlying type|enumerator value|"
-  "using declaration|friend declaration|qualifier|initializer}0 "
+  "using declaration|friend declaration|qualifier|initializer|default argument"
+  "}0 "
   "contains an unexpanded parameter pack">;
 def err_unexpanded_parameter_pack_1 : Error<
   "%select{expression|base type|declaration type|data member type|bit-field "
   "size|static assertion|fixed underlying type|enumerator value|"
-  "using declaration|friend declaration|qualifier|initializer}0 "
+  "using declaration|friend declaration|qualifier|initializer|default argument"
+  "}0 "
   "contains unexpanded parameter pack %1">;
 def err_unexpanded_parameter_pack_2 : Error<
   "%select{expression|base type|declaration type|data member type|bit-field "
   "size|static assertion|fixed underlying type|enumerator value|"
-  "using declaration|friend declaration|qualifier|initializer}0 "
+  "using declaration|friend declaration|qualifier|initializer|default argument"
+  "}0 "
   "contains unexpanded parameter packs %1 and %2">;
 def err_unexpanded_parameter_pack_3_or_more : Error<
   "%select{expression|base type|declaration type|data member type|bit-field "
   "size|static assertion|fixed underlying type|enumerator value|"
-  "using declaration|friend declaration|qualifier|initializer}0 "
+  "using declaration|friend declaration|qualifier|initializer|default argument"
+  "}0 "
   "contains unexpanded parameter packs %1, %2, ...">;
 
 def err_unexpected_typedef : Error<
index 32a658ae4bf83bfa9aa18d6d421f502d263d1064..db0faa806d94890cb84861070567b432295a4f09 100644 (file)
@@ -3169,7 +3169,10 @@ public:
     UPPC_DeclarationQualifier,
 
     /// \brief An initializer.
-    UPPC_Initializer
+    UPPC_Initializer,
+    
+    /// \brief A default argument.
+    UPPC_DefaultArgument
   };
 
   /// \brief If the given type contains an unexpanded parameter pack,
@@ -3214,6 +3217,19 @@ public:
   bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
                                        UnexpandedParameterPackContext UPPC);
 
+  /// \brief If the given template name contains an unexpanded parameter pack,
+  /// diagnose the error.
+  ///
+  /// \param Loc The location of the template name.
+  ///
+  /// \param Template The template name that is being checked for unexpanded 
+  /// parameter packs.
+  ///
+  /// \returns true if an error ocurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(SourceLocation Loc,
+                                       TemplateName Template,
+                                       UnexpandedParameterPackContext UPPC);
+
   /// \brief Describes the result of template argument deduction.
   ///
   /// The TemplateDeductionResult enumeration describes the result of
index 30e8b1e28e6b1b2a9718a56ba1a080b381dd87d4..54e69a11115aaca76aacc8185c62dd5d2fc75c6b 100644 (file)
@@ -177,6 +177,12 @@ Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc,
     return;
   }
 
+  // Check for unexpanded parameter packs.
+  if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) {
+    Param->setInvalidDecl();
+    return;
+  }    
+      
   // Check that the default argument is well-formed
   CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this);
   if (DefaultArgChecker.Visit(DefaultArg)) {
index 4b8c455731a1600f2a9d84c0a964a4e81bb9aca0..a79c17cdbfa96821236e18126a0019730f7a8652 100644 (file)
@@ -536,6 +536,11 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
       Diag(EqualLoc, diag::err_template_param_pack_default_arg);
       return Param;
     }
+
+    // Check for unexpanded parameter packs.
+    if (DiagnoseUnexpandedParameterPack(Loc, DefaultTInfo, 
+                                        UPPC_DefaultArgument))
+      return Param;
     
     // Check the template argument itself.
     if (CheckTemplateArgument(Param, DefaultTInfo)) {
@@ -642,6 +647,10 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
   
   // Check the well-formedness of the default template argument, if provided.
   if (Default) {  
+    // Check for unexpanded parameter packs.
+    if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
+      return Param;
+
     TemplateArgument Converted;
     if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) {
       Param->setInvalidDecl();
@@ -683,6 +692,12 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
     IdResolver.AddDecl(Param);
   }
 
+  if (Params->size() == 0) {
+    Diag(Param->getLocation(), diag::err_template_template_parm_no_parms)
+    << SourceRange(Params->getLAngleLoc(), Params->getRAngleLoc());
+    Param->setInvalidDecl();
+  }
+
   if (!Default.isInvalid()) {
     // Check only that we have a template template argument. We don't want to
     // try to check well-formedness now, because our template template parameter
@@ -699,14 +714,15 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
       return Param;
     }
     
+    // Check for unexpanded parameter packs.
+    if (DiagnoseUnexpandedParameterPack(DefaultArg.getLocation(), 
+                                        DefaultArg.getArgument().getAsTemplate(),
+                                        UPPC_DefaultArgument))
+      return Param;
+    
     Param->setDefaultArgument(DefaultArg, false);
   }
   
-  if (Params->size() == 0) {
-    Diag(Param->getLocation(), diag::err_template_template_parm_no_parms)
-      << SourceRange(Params->getLAngleLoc(), Params->getRAngleLoc());
-    Param->setInvalidDecl();
-  }
   return Param;
 }
 
index 07873efdac66407265cf15f2d1efb5bfe6412176..20b05d59d35b256aea673736ffe6c75314982fbe 100644 (file)
@@ -238,3 +238,19 @@ bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
   DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
   return true;
 }
+
+bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
+                                           TemplateName Template,
+                                       UnexpandedParameterPackContext UPPC) {
+  
+  if (Template.isNull() || !Template.containsUnexpandedParameterPack())
+    return false;
+
+  llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseTemplateName(Template);
+  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+  DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
+  return true;
+}
+
index 94bcfe6ed200c11429aa68285cec57aac4358895..2352234f86c6583865474b6dd5c95d512a4221a7 100644 (file)
@@ -132,6 +132,15 @@ struct TestUnexpandedDecls : T{
     T direct_init(0, static_cast<Types>(0)); // expected-error{{expression contains unexpanded parameter pack 'Types'}}
     T list_init = { static_cast<Types>(0) }; // expected-error{{initializer contains unexpanded parameter pack 'Types'}}
   }
+
+  void default_function_args(T = static_cast<Types>(0)); // expected-error{{default argument contains unexpanded parameter pack 'Types'}}
+
+  template<typename = Types*> // expected-error{{default argument contains unexpanded parameter pack 'Types'}}
+    struct default_template_args_1; 
+  template<int = static_cast<Types>(0)> // expected-error{{default argument contains unexpanded parameter pack 'Types'}}
+    struct default_template_args_2;
+  template<template<typename> class = Types::template apply> // expected-error{{default argument contains unexpanded parameter pack 'Types'}}
+    struct default_template_args_3;
 };
 
 // Test for diagnostics in the presence of multiple unexpanded