[cfe-commits] r158525 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/Parser.h include/clang/Sema/Sema.h lib/Parse/ParseExpr.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaLambda.cpp test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm

Douglas Gregor dgregor at apple.com
Fri Jun 15 09:59:29 PDT 2012


Author: dgregor
Date: Fri Jun 15 11:59:29 2012
New Revision: 158525

URL: http://llvm.org/viewvc/llvm-project?rev=158525&view=rev
Log:
Check the parameter lists and return type of both blocks and lambdas
for unexpanded parameter packs. Fixes the crash-on-invalid in
PR13117.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=158525&r1=158524&r2=158525&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 15 11:59:29 2012
@@ -2859,28 +2859,28 @@
   "size|static assertion|fixed underlying type|enumerator value|"
   "using declaration|friend declaration|qualifier|initializer|default argument|"
   "non-type template parameter type|exception type|partial specialization|"
-  "__if_exists name|__if_not_exists name}0 "
+  "__if_exists name|__if_not_exists name|lambda|block}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|default argument|"
   "non-type template parameter type|exception type|partial specialization|"
-  "__if_exists name|__if_not_exists name}0 "
+  "__if_exists name|__if_not_exists name|lambda|block}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|default argument|"
   "non-type template parameter type|exception type|partial specialization|"
-  "__if_exists name|__if_not_exists name}0 "
+  "__if_exists name|__if_not_exists name|lambda|block}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|default argument|"
   "non-type template parameter type|exception type|partial specialization|"
-  "__if_exists name|__if_not_exists name}0 "
+  "__if_exists name|__if_not_exists name|lambda|block}0 "
   "contains unexpanded parameter packs %1, %2, ...">;
 
 def err_pack_expansion_without_parameter_packs : Error<

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=158525&r1=158524&r2=158525&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Jun 15 11:59:29 2012
@@ -1711,7 +1711,7 @@
                              = Declarator::TypeNameContext,
                            AccessSpecifier AS = AS_none,
                            Decl **OwnedType = 0);
-  void ParseBlockId();
+  void ParseBlockId(SourceLocation CaretLoc);
 
   // Check for the start of a C++11 attribute-specifier-seq in a context where
   // an attribute is not allowed.

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=158525&r1=158524&r2=158525&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun 15 11:59:29 2012
@@ -3118,7 +3118,8 @@
 
   /// ActOnBlockArguments - This callback allows processing of block arguments.
   /// If there are no arguments, this is still invoked.
-  void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope);
+  void ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
+                           Scope *CurScope);
 
   /// ActOnBlockError - If there is an error parsing a block, this callback
   /// is invoked to pop the information about the block from the action impl.
@@ -4960,7 +4961,13 @@
     UPPC_IfExists,
 
     /// \brief Microsoft __if_not_exists.
-    UPPC_IfNotExists
+    UPPC_IfNotExists,
+    
+    /// \brief Lambda expression.
+    UPPC_Lambda,
+    
+    /// \brief Block expression,
+    UPPC_Block
 };
 
   /// \brief Diagnose unexpanded parameter packs.

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=158525&r1=158524&r2=158525&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Jun 15 11:59:29 2012
@@ -2299,7 +2299,7 @@
 /// [clang] block-id:
 /// [clang]   specifier-qualifier-list block-declarator
 ///
-void Parser::ParseBlockId() {
+void Parser::ParseBlockId(SourceLocation CaretLoc) {
   if (Tok.is(tok::code_completion)) {
     Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
     return cutOffParsing();
@@ -2319,7 +2319,7 @@
   MaybeParseGNUAttributes(DeclaratorInfo);
 
   // Inform sema that we are starting a block.
-  Actions.ActOnBlockArguments(DeclaratorInfo, getCurScope());
+  Actions.ActOnBlockArguments(CaretLoc, DeclaratorInfo, getCurScope());
 }
 
 /// ParseBlockLiteralExpression - Parse a block literal, which roughly looks
@@ -2376,9 +2376,9 @@
     MaybeParseGNUAttributes(ParamInfo);
 
     // Inform sema that we are starting a block.
-    Actions.ActOnBlockArguments(ParamInfo, getCurScope());
+    Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());
   } else if (!Tok.is(tok::l_brace)) {
-    ParseBlockId();
+    ParseBlockId(CaretLoc);
   } else {
     // Otherwise, pretend we saw (void).
     ParsedAttributes attrs(AttrFactory);
@@ -2399,7 +2399,7 @@
     MaybeParseGNUAttributes(ParamInfo);
 
     // Inform sema that we are starting a block.
-    Actions.ActOnBlockArguments(ParamInfo, getCurScope());
+    Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope());
   }
 
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=158525&r1=158524&r2=158525&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jun 15 11:59:29 2012
@@ -9086,7 +9086,8 @@
   PushExpressionEvaluationContext(PotentiallyEvaluated);  
 }
 
-void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
+void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
+                               Scope *CurScope) {
   assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");
   assert(ParamInfo.getContext() == Declarator::BlockLiteralContext);
   BlockScopeInfo *CurBlock = getCurBlock();
@@ -9094,6 +9095,18 @@
   TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
   QualType T = Sig->getType();
 
+  // FIXME: We should allow unexpanded parameter packs here, but that would,
+  // in turn, make the block expression contain unexpanded parameter packs.
+  if (DiagnoseUnexpandedParameterPack(CaretLoc, Sig, UPPC_Block)) {
+    // Drop the parameters.
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.HasTrailingReturn = false;
+    EPI.TypeQuals |= DeclSpec::TQ_const;
+    T = Context.getFunctionType(Context.DependentTy, /*Args=*/0, /*NumArgs=*/0,
+                                EPI);
+    Sig = Context.getTrivialTypeSourceInfo(T);
+  }
+  
   // GetTypeForDeclarator always produces a function type for a block
   // literal signature.  Furthermore, it is always a FunctionProtoType
   // unless the function was written with a typedef.

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=158525&r1=158524&r2=158525&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Jun 15 11:59:29 2012
@@ -269,9 +269,26 @@
     FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL);
     Params = llvm::ArrayRef<ParmVarDecl *>(Proto.getParmArray(), 
                                            Proto.getNumArgs());
+
+    // Check for unexpanded parameter packs in the method type.
+    // FIXME: We should allow unexpanded parameter packs here, but that would,
+    // in turn, make the lambda expression contain unexpanded parameter packs.
+    if (DiagnoseUnexpandedParameterPack(Intro.Range.getBegin(), MethodTyInfo,
+                                        UPPC_Lambda)) {
+      // Drop the parameters.
+      Params = llvm::ArrayRef<ParmVarDecl *>();
+      FunctionProtoType::ExtProtoInfo EPI;
+      EPI.HasTrailingReturn = false;
+      EPI.TypeQuals |= DeclSpec::TQ_const;
+      QualType MethodTy = Context.getFunctionType(Context.DependentTy,
+                                                  /*Args=*/0, /*NumArgs=*/0, EPI);
+      MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
+      ExplicitParams = false;
+      ExplicitResultType = false;
+    }
   }
   
-  CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, 
+  CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
                                                 MethodTyInfo, EndLoc, Params);
   
   if (ExplicitParams)

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm?rev=158525&r1=158524&r2=158525&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm Fri Jun 15 11:59:29 2012
@@ -86,3 +86,24 @@
     int &ir = accept_lambda_conv([](int x) { return x + 1; });
   }
 }
+
+namespace PR13117 {
+  struct A {
+    template<typename ... Args> static void f1()
+    {
+      (void)^(Args args) { // expected-error{{block contains unexpanded parameter pack 'Args'}}
+      };
+    }
+
+    template<typename ... Args> static void f2()
+    {
+      (void)[](Args args) { // expected-error{{lambda contains unexpanded parameter pack 'Args'}}
+      };
+    }
+  };
+
+  void g() {
+    A::f1<int, int>();
+    A::f2<int, int>();
+  }
+}





More information about the cfe-commits mailing list