]> granicus.if.org Git - clang/commitdiff
Check for unexpanded parameter packs in using declarations. As a
authorDouglas Gregor <dgregor@apple.com>
Thu, 16 Dec 2010 00:46:58 +0000 (00:46 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 16 Dec 2010 00:46:58 +0000 (00:46 +0000)
drive-by, make sure to check for unexpanded parameter packs within the
name of a declaration.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121930 91177308-0d34-0410-b5e6-96231b3b80d8

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

index f6e6f075b6c79149cdc09616cd57a08763200214..e9617a2f11fe5c0b02338968230f6a6dacd83cff 100644 (file)
@@ -1823,19 +1823,23 @@ 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}0 "
+  "size|static assertion|fixed underlying type|enumerator value|"
+  "using declaration}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}0 "
+  "size|static assertion|fixed underlying type|enumerator value|"
+  "using declaration}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}0 "
+  "size|static assertion|fixed underlying type|enumerator value|"
+  "using declaration}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}0 "
+  "size|static assertion|fixed underlying type|enumerator value|"
+  "using declaration}0 "
   "contains unexpanded parameter packs %1, %2, ...">;
 
 def err_unexpected_typedef : Error<
index c375b848085f573dd0c3970d766916f8a92cd17b..c48f40403c1147e0051e6f760a9d22fb3c2178ed 100644 (file)
@@ -3157,7 +3157,10 @@ public:
     UPPC_FixedUnderlyingType,
 
     /// \brief The enumerator value.
-    UPPC_EnumeratorValue
+    UPPC_EnumeratorValue,
+
+    /// \brief A using declaration.
+    UPPC_UsingDeclaration
   };
 
   /// \brief If the given type contains an unexpanded parameter pack,
@@ -3182,6 +3185,26 @@ public:
   bool DiagnoseUnexpandedParameterPack(Expr *E,
                        UnexpandedParameterPackContext UPPC = UPPC_Expression);
 
+  /// \brief If the given nested-name-specifier contains an unexpanded
+  /// parameter pack, diagnose the error.
+  ///
+  /// \param SS The nested-name-specifier that is being checked for
+  /// unexpanded parameter packs.
+  ///
+  /// \returns true if an error ocurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
+                                       UnexpandedParameterPackContext UPPC);
+
+  /// \brief If the given name contains an unexpanded parameter pack,
+  /// diagnose the error.
+  ///
+  /// \param NameInfo The name (with source location information) that
+  /// is being checked for unexpanded parameter packs.
+  ///
+  /// \returns true if an error ocurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
+                                       UnexpandedParameterPackContext UPPC);
+
   /// \brief Describes the result of template argument deduction.
   ///
   /// The TemplateDeductionResult enumeration describes the result of
index 95c3b998019ef25bd49f0a15486aedd4e80a4fea..c3384a51628b8ed06199f19a4906ec23d41a9374 100644 (file)
@@ -2319,7 +2319,8 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
            diag::err_declarator_need_ident)
         << D.getDeclSpec().getSourceRange() << D.getSourceRange();
     return 0;
-  }
+  } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
+    return 0;
 
   // The scope passed in may not be a decl scope.  Zip up the scope tree until
   // we find one that is.
index 555f5fd42422ac0594b0126687c0cb561069b888..4a9abec5838de62120d89be62603903af6512b3c 100644 (file)
@@ -928,6 +928,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
     }
     
     // FIXME: Check for template parameters!
+    // FIXME: Check that the name is an identifier!
     Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
                          AS);
     assert(Member && "HandleField never returns null");
@@ -3547,6 +3548,10 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
       << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
   }
 
+  if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
+      DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
+    return 0;
+
   NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
                                         TargetNameInfo, AttrList,
                                         /* IsInstantiation */ false,
index 057792914b28063f9081ed4510880d3e0d6264e5..2338b5bfbca4602efc45fae838a7bd743a352e7f 100644 (file)
@@ -171,7 +171,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
 }
 
 bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
-                                           UnexpandedParameterPackContext UPPC) {
+                                        UnexpandedParameterPackContext UPPC) {
   // C++0x [temp.variadic]p5:
   //   An appearance of a name of a parameter pack that is not expanded is 
   //   ill-formed.
@@ -184,3 +184,53 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
   DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded);
   return true;
 }
+
+bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
+                                        UnexpandedParameterPackContext UPPC) {
+  // C++0x [temp.variadic]p5:
+  //   An appearance of a name of a parameter pack that is not expanded is 
+  //   ill-formed.
+  if (!SS.getScopeRep() || 
+      !SS.getScopeRep()->containsUnexpandedParameterPack())
+    return false;
+
+  llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseNestedNameSpecifier(SS.getScopeRep());
+  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+  DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(), 
+                                   UPPC, Unexpanded);
+  return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
+                                         UnexpandedParameterPackContext UPPC) {
+  // C++0x [temp.variadic]p5:
+  //   An appearance of a name of a parameter pack that is not expanded is 
+  //   ill-formed.
+  switch (NameInfo.getName().getNameKind()) {
+  case DeclarationName::Identifier:
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+  case DeclarationName::CXXOperatorName:
+  case DeclarationName::CXXLiteralOperatorName:
+  case DeclarationName::CXXUsingDirective:
+    return false;
+
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+    if (!NameInfo.getNamedTypeInfo()->getType()
+                                          ->containsUnexpandedParameterPack())
+      return false;
+    break;
+  }
+
+  llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseTypeLoc(NameInfo.getNamedTypeInfo()->getTypeLoc());
+  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+  DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
+  return true;
+}
index 1f56c889a6eae4c232316cc942ffa22887e7276c..a1c07c96fe7c99d80b3faba9199b46f8e56afdd1 100644 (file)
@@ -104,10 +104,11 @@ void TestPPNameFunc(int i) {
 }
 
 // FIXME: Test for unexpanded parameter packs in declarations.
-template<typename... Types>
-struct TestUnexpandedDecls {
+template<typename T, typename... Types>
+struct TestUnexpandedDecls : T{
   void member_function(Types);  // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
   void member_function () throw(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
+  operator Types() const; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
   Types data_member;  // expected-error{{data member type contains unexpanded parameter pack 'Types'}}
   static Types static_data_member; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}}
   unsigned bit_field : static_cast<Types>(0);  // expected-error{{bit-field size contains unexpanded parameter pack 'Types'}}
@@ -116,6 +117,10 @@ struct TestUnexpandedDecls {
   enum E0 : Types {  // expected-error{{fixed underlying type contains unexpanded parameter pack 'Types'}}
     EnumValue = static_cast<Types>(0) // expected-error{{enumerator value contains unexpanded parameter pack 'Types'}}
   };
+
+  using typename Types::type; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}}
+  using Types::value; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}}
+  using T::operator Types; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}}
 };
 
 // Test for diagnostics in the presence of multiple unexpanded