[cfe-commits] r150519 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaLambda.cpp lib/Sema/TreeTransform.h test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp

Douglas Gregor dgregor at apple.com
Tue Feb 14 14:28:59 PST 2012


Author: dgregor
Date: Tue Feb 14 16:28:59 2012
New Revision: 150519

URL: http://llvm.org/viewvc/llvm-project?rev=150519&view=rev
Log:
Implement C++ core issue 974, which permits default arguments for
lambda expressions. Because these issue was pulled back from Ready
status at the Kona meeting, we still emit an ExtWarn when using
default arguments for lambda expressions.

Added:
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=150519&r1=150518&r2=150519&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Feb 14 16:28:59 2012
@@ -183,6 +183,7 @@
 def : DiagGroup<"strict-overflow">;
 
 def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
+def LambdaExtensions : DiagGroup<"lambda-extensions">;
 def : DiagGroup<"strict-prototypes">;
 def StrictSelector : DiagGroup<"strict-selector-match">;
 def MethodDuplicate : DiagGroup<"duplicate-method-match">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=150519&r1=150518&r2=150519&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Feb 14 16:28:59 2012
@@ -4031,7 +4031,7 @@
   def ext_lambda_implies_void_return : ExtWarn<
     "C++11 requires lambda with omitted result type to consist of a single "
     "return statement">,
-    InGroup<DiagGroup<"lambda-return">>;
+    InGroup<LambdaExtensions>;
   def err_lambda_return_init_list : Error<
     "cannot deduce lambda return type from initializer list">;
   def err_lambda_capture_default_arg : Error<
@@ -4042,6 +4042,9 @@
     "incomplete result type %0 in lambda expression">;
   def err_lambda_objc_object_result : Error<
     "non-pointer Objective-C class type %0 in lambda expression result">;
+  def ext_lambda_default_arguments : ExtWarn<
+    "C++11 forbids default arguments for lambda expressions">,
+    InGroup<LambdaExtensions>;
 }
 
 def err_operator_arrow_circular : Error<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=150519&r1=150518&r2=150519&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Feb 14 16:28:59 2012
@@ -3515,7 +3515,8 @@
   CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
                                        SourceRange IntroducerRange,
                                        TypeSourceInfo *MethodType,
-                                       SourceLocation EndLoc);
+                                       SourceLocation EndLoc,
+                                       llvm::ArrayRef<ParmVarDecl *> Params);
   
   /// \brief Introduce the scope for a lambda expression.
   sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
@@ -3530,8 +3531,7 @@
   void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
   
   /// \brief Introduce the lambda parameters into scope.
-  void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope,
-                           llvm::ArrayRef<ParmVarDecl *> Params);
+  void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope);
   
   /// ActOnStartOfLambdaDefinition - This is called just before we start
   /// parsing the body of a lambda; it analyzes the explicit captures and 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=150519&r1=150518&r2=150519&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Feb 14 16:28:59 2012
@@ -585,11 +585,25 @@
   unsigned NumParams = FD->getNumParams();
   unsigned p;
 
+  bool IsLambda = FD->getOverloadedOperator() == OO_Call &&
+                  isa<CXXMethodDecl>(FD) &&
+                  cast<CXXMethodDecl>(FD)->getParent()->isLambda();
+              
   // Find first parameter with a default argument
   for (p = 0; p < NumParams; ++p) {
     ParmVarDecl *Param = FD->getParamDecl(p);
-    if (Param->hasDefaultArg())
+    if (Param->hasDefaultArg()) {
+      // C++11 [expr.prim.lambda]p5:
+      //   [...] Default arguments (8.3.6) shall not be specified in the 
+      //   parameter-declaration-clause of a lambda-declarator.
+      //
+      // FIXME: Core issue 974 strikes this sentence, we only provide an
+      // extension warning.
+      if (IsLambda)
+        Diag(Param->getLocation(), diag::ext_lambda_default_arguments)
+          << Param->getDefaultArgRange();
       break;
+    }
   }
 
   // C++ [dcl.fct.default]p4:

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=150519&r1=150518&r2=150519&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Tue Feb 14 16:28:59 2012
@@ -36,7 +36,8 @@
 CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
                                            SourceRange IntroducerRange,
                                            TypeSourceInfo *MethodType,
-                                           SourceLocation EndLoc) {
+                                           SourceLocation EndLoc,
+                 llvm::ArrayRef<ParmVarDecl *> Params) {
   // C++11 [expr.prim.lambda]p5:
   //   The closure type for a lambda-expression has a public inline function 
   //   call operator (13.5.4) whose parameters and return type are described by
@@ -66,6 +67,19 @@
   // context, so that the Scope stack matches the lexical nesting.
   Method->setLexicalDeclContext(Class->getDeclContext());  
   
+  // Add parameters.
+  if (!Params.empty()) {
+    Method->setParams(Params);
+    CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()),
+                             const_cast<ParmVarDecl **>(Params.end()),
+                             /*CheckParameterNames=*/false);
+    
+    for (CXXMethodDecl::param_iterator P = Method->param_begin(), 
+                                    PEnd = Method->param_end();
+         P != PEnd; ++P)
+      (*P)->setOwningFunction(Method);
+  }
+  
   return Method;
 }
 
@@ -109,18 +123,11 @@
   LSI->finishedExplicitCaptures();
 }
 
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope,
-                               llvm::ArrayRef<ParmVarDecl *> Params) {
-  CallOperator->setParams(Params);
-  CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()), 
-                           const_cast<ParmVarDecl **>(Params.end()),
-                           /*CheckParameterNames=*/false);
-  
+void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {  
   // Introduce our parameters into the function scope
   for (unsigned p = 0, NumParams = CallOperator->getNumParams(); 
        p < NumParams; ++p) {
     ParmVarDecl *Param = CallOperator->getParamDecl(p);
-    Param->setOwningFunction(CallOperator);
     
     // If this has an identifier, add it to the scope stack.
     if (CurScope && Param->getIdentifier()) {
@@ -141,6 +148,7 @@
   bool ExplicitParams = true;
   bool ExplicitResultType = true;
   SourceLocation EndLoc;
+  llvm::ArrayRef<ParmVarDecl *> Params;
   if (ParamInfo.getNumTypeObjects() == 0) {
     // C++11 [expr.prim.lambda]p4:
     //   If a lambda-expression does not include a lambda-declarator, it is as 
@@ -166,11 +174,6 @@
     if (!FTI.hasMutableQualifier())
       FTI.TypeQuals |= DeclSpec::TQ_const;
     
-    // C++11 [expr.prim.lambda]p5:
-    //   [...] Default arguments (8.3.6) shall not be specified in the 
-    //   parameter-declaration-clause of a lambda-declarator.
-    CheckExtraCXXDefaultArguments(ParamInfo);
-    
     MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
     assert(MethodTyInfo && "no type from lambda-declarator");
     EndLoc = ParamInfo.getSourceRange().getEnd();
@@ -178,10 +181,18 @@
     ExplicitResultType
       = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType() 
                                                         != Context.DependentTy;
+    
+    TypeLoc TL = MethodTyInfo->getTypeLoc();
+    FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL);
+    Params = llvm::ArrayRef<ParmVarDecl *>(Proto.getParmArray(), 
+                                           Proto.getNumArgs());
   }
   
   CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, 
-                                                MethodTyInfo, EndLoc);
+                                                MethodTyInfo, EndLoc, Params);
+  
+  if (ExplicitParams)
+    CheckCXXDefaultArguments(Method);
   
   // Attributes on the lambda apply to the method.  
   ProcessDeclAttributes(CurScope, Method, ParamInfo);
@@ -325,12 +336,8 @@
   }
   finishLambdaExplicitCaptures(LSI);
 
-  // Set the parameters on the decl, if specified.
-  if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
-    FunctionProtoTypeLoc Proto
-      = cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
-    addLambdaParameters(Method, CurScope, Proto.getParams());
-  }
+  // Add lambda parameters into scope.
+  addLambdaParameters(Method, CurScope);
 
   // Enter a new evaluation context to insulate the lambda from any
   // cleanups from the enclosing full-expression.

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=150519&r1=150518&r2=150519&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Feb 14 16:28:59 2012
@@ -7667,11 +7667,22 @@
   if (!MethodTy)
     return ExprError();
 
+  // Transform lambda parameters.
+  bool Invalid = false;
+  llvm::SmallVector<QualType, 4> ParamTypes;
+  llvm::SmallVector<ParmVarDecl *, 4> Params;
+  if (getDerived().TransformFunctionTypeParams(E->getLocStart(),
+        E->getCallOperator()->param_begin(),
+        E->getCallOperator()->param_size(),
+        0, ParamTypes, &Params))
+    Invalid = true;  
+
   // Build the call operator.
   CXXMethodDecl *CallOperator
     = getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
                                       MethodTy, 
-                                      E->getCallOperator()->getLocEnd());
+                                      E->getCallOperator()->getLocEnd(),
+                                      Params);
   getDerived().transformAttrs(E->getCallOperator(), CallOperator);
   
   // FIXME: Instantiation-specific.
@@ -7690,7 +7701,6 @@
                                  E->isMutable());
   
   // Transform captures.
-  bool Invalid = false;
   bool FinishedExplicitCaptures = false;
   for (LambdaExpr::capture_iterator C = E->capture_begin(), 
                                  CEnd = E->capture_end();
@@ -7766,17 +7776,6 @@
   if (!FinishedExplicitCaptures)
     getSema().finishLambdaExplicitCaptures(LSI);
 
-  // Transform lambda parameters.
-  llvm::SmallVector<QualType, 4> ParamTypes;
-  llvm::SmallVector<ParmVarDecl *, 4> Params;
-  if (!getDerived().TransformFunctionTypeParams(E->getLocStart(),
-         E->getCallOperator()->param_begin(),
-         E->getCallOperator()->param_size(),
-         0, ParamTypes, &Params))
-    getSema().addLambdaParameters(CallOperator, /*CurScope=*/0, Params);
-  else
-    Invalid = true;
-  
 
   // Enter a new evaluation context to insulate the lambda from any
   // cleanups from the enclosing full-expression.

Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp?rev=150519&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp Tue Feb 14 16:28:59 2012
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -Wno-lambda-extensions -verify
+
+void defargs() {
+  auto l1 = [](int i, int j = 17, int k = 18) { return i + j + k; };
+  int i1 = l1(1);
+  int i2 = l1(1, 2);
+  int i3 = l1(1, 2, 3);
+}
+
+
+void defargs_errors() {
+  auto l1 = [](int i, 
+               int j = 17, 
+               int k) { }; // expected-error{{missing default argument on parameter 'k'}}
+
+  auto l2 = [](int i, int j = i) {}; // expected-error{{default argument references parameter 'i'}}
+
+  int foo;
+  auto l3 = [](int i = foo) {}; // expected-error{{default argument references local variable 'foo' of enclosing function}}
+}
+
+struct NonPOD {
+  NonPOD();
+  NonPOD(const NonPOD&);
+  ~NonPOD();
+};
+
+struct NoDefaultCtor {
+  NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}}
+  ~NoDefaultCtor();
+};
+
+template<typename T>
+void defargs_in_template_unused(T t) {
+  auto l1 = [](const T& value = T()) { };
+  l1(t);
+}
+
+template void defargs_in_template_unused(NonPOD);
+template void defargs_in_template_unused(NoDefaultCtor);
+
+template<typename T>
+void defargs_in_template_used() {
+  auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}}
+  l1(); // expected-note{{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}}
+}
+
+template void defargs_in_template_used<NonPOD>();
+template void defargs_in_template_used<NoDefaultCtor>(); // expected-note{{in instantiation of function template specialization}}
+

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp?rev=150519&r1=150518&r2=150519&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp Tue Feb 14 16:28:59 2012
@@ -38,9 +38,10 @@
 
 // Default arguments (8.3.6) shall not be specified in the
 // parameter-declaration-clause of a lambda- declarator.
+// Note: Removed by core issue 974.
 int test_default_args() {
-  return [](int i = 5,  // expected-error{{default arguments can only be specified for parameters in a function declaration}}
-            int j = 17) { return i+j;}(5, 6); // expected-error{{default arguments can only be specified for parameters in a function declaration}}
+  return [](int i = 5,  // expected-warning{{C++11 forbids default arguments for lambda expressions}}
+            int j = 17) { return i+j;}(5, 6);
 }
 
 // Any exception-specification specified on a lambda-expression





More information about the cfe-commits mailing list