[cfe-commits] r150236 - in /cfe/trunk: lib/Sema/SemaLambda.cpp lib/Sema/SemaOverload.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp

Douglas Gregor dgregor at apple.com
Fri Feb 10 00:36:39 PST 2012


Author: dgregor
Date: Fri Feb 10 02:36:38 2012
New Revision: 150236

URL: http://llvm.org/viewvc/llvm-project?rev=150236&view=rev
Log:
Implement the conversion to a function pointer for lambda expressions,
per C++ [expr.prim.lambda]p6.

Added:
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp   (with props)
Modified:
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=150236&r1=150235&r2=150236&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Feb 10 02:36:38 2012
@@ -102,7 +102,10 @@
                             EndLoc);
   Method->setAccess(AS_public);
   Class->addDecl(Method);
-  Method->setLexicalDeclContext(DC); // FIXME: Minor hack.
+
+  // Temporarily set the lexical declaration context to the current
+  // context, so that the Scope stack matches the lexical nesting.
+  Method->setLexicalDeclContext(DC);
 
   // Attributes on the lambda apply to the method.  
   ProcessDeclAttributes(CurScope, Method, ParamInfo);
@@ -289,12 +292,13 @@
   llvm::SmallVector<Expr *, 4> CaptureInits;
   LambdaCaptureDefault CaptureDefault;
   CXXRecordDecl *Class;
+  CXXMethodDecl *CallOperator;
   SourceRange IntroducerRange;
   bool ExplicitParams;
   bool LambdaExprNeedsCleanups;
   {
     LambdaScopeInfo *LSI = getCurLambda();
-    CXXMethodDecl *CallOperator = LSI->CallOperator;
+    CallOperator = LSI->CallOperator;
     Class = LSI->Lambda;
     IntroducerRange = LSI->IntroducerRange;
     ExplicitParams = LSI->ExplicitParams;
@@ -427,5 +431,48 @@
     break;
   }
 
+  // C++11 [expr.prim.lambda]p6:
+  //   The closure type for a lambda-expression with no lambda-capture
+  //   has a public non-virtual non-explicit const conversion function
+  //   to pointer to function having the same parameter and return
+  //   types as the closure type's function call operator.
+  if (Captures.empty() && CaptureDefault == LCD_None) {
+    const FunctionProtoType *Proto
+      = CallOperator->getType()->getAs<FunctionProtoType>(); 
+    QualType FunctionPtrTy;
+    {
+      FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
+      ExtInfo.TypeQuals = 0;
+      QualType FunctionTy
+        = Context.getFunctionType(Proto->getResultType(),
+                                  Proto->arg_type_begin(),
+                                  Proto->getNumArgs(),
+                                  ExtInfo);
+      FunctionPtrTy = Context.getPointerType(FunctionTy);
+    }
+
+    FunctionProtoType::ExtProtoInfo ExtInfo;
+    ExtInfo.TypeQuals = Qualifiers::Const;
+    QualType ConvTy = Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo);
+
+    SourceLocation Loc = IntroducerRange.getBegin();
+    DeclarationName Name
+      = Context.DeclarationNames.getCXXConversionFunctionName(
+          Context.getCanonicalType(FunctionPtrTy));
+    DeclarationNameLoc NameLoc;
+    NameLoc.NamedType.TInfo = Context.getTrivialTypeSourceInfo(FunctionPtrTy,
+                                                               Loc);
+    CXXConversionDecl *Conversion 
+      = CXXConversionDecl::Create(Context, Class, Loc, 
+                                  DeclarationNameInfo(Name, Loc, NameLoc),
+                                  ConvTy, 
+                                  Context.getTrivialTypeSourceInfo(ConvTy, Loc),
+                                  /*isInline=*/false, /*isExplicit=*/false,
+                                  /*isConstexpr=*/false, Body->getLocEnd());
+    Conversion->setAccess(AS_public);
+    Conversion->setImplicit(true);
+    Class->addDecl(Conversion);
+  }
+
   return MaybeBindToTemporary(Lambda);
 }

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=150236&r1=150235&r2=150236&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Feb 10 02:36:38 2012
@@ -7583,9 +7583,11 @@
     if (Meth->isMoveAssignmentOperator())
       return oc_implicit_move_assignment;
 
-    assert(Meth->isCopyAssignmentOperator()
-           && "implicit method is not copy assignment operator?");
-    return oc_implicit_copy_assignment;
+    if (Meth->isCopyAssignmentOperator())
+      return oc_implicit_copy_assignment;
+
+    assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
+    return oc_method;
   }
 
   return isTemplate ? oc_function_template : oc_function;

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=150236&r1=150235&r2=150236&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 Fri Feb 10 02:36:38 2012
@@ -15,13 +15,13 @@
   // This function call operator is declared const (9.3.1) if and only
   // if the lambda- expression's parameter-declaration-clause is not
   // followed by mutable.
-  auto l = [](){}; // expected-note{{method is not marked volatile}}
+  auto l = [=](){}; // expected-note{{method is not marked volatile}}
   const decltype(l) lc = l;
   l();
   lc();
 
-  auto ml = []() mutable{}; // expected-note{{method is not marked const}} \
-                            // expected-note{{method is not marked volatile}} 
+  auto ml = [=]() mutable{}; // expected-note{{method is not marked const}} \
+                             // expected-note{{method is not marked volatile}} 
   const decltype(ml) mlc = ml;
   ml();
   mlc(); // expected-error{{no matching function for call to object of type}}

Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp?rev=150236&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp Fri Feb 10 02:36:38 2012
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+void test_conversion() {
+  int (*fp1)(int) = [](int x) { return x + 1; };
+  void (*fp2)(int) = [](int x) { };
+
+  const auto lambda = [](int x) { };
+  void (*fp3)(int) = lambda;
+
+  volatile const auto lambda2 = [](int x) { }; // expected-note{{but method is not marked volatile}}
+  void (*fp4)(int) = lambda2; // expected-error{{no viable conversion}}
+}
+
+void test_no_conversion() { 
+  int (*fp1)(int) = [=](int x) { return x + 1; }; // expected-error{{no viable conversion}}
+  void (*fp2)(int) = [&](int x) { }; // expected-error{{no viable conversion}}
+}
+
+void test_wonky() {
+  const auto l = [](int x) mutable -> int { return + 1; };
+  l(17); // okay: uses conversion function
+}

Propchange: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list