[cfe-commits] r150252 - in /cfe/trunk: lib/Sema/SemaLambda.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp

Douglas Gregor dgregor at apple.com
Fri Feb 10 08:13:21 PST 2012


Author: dgregor
Date: Fri Feb 10 10:13:20 2012
New Revision: 150252

URL: http://llvm.org/viewvc/llvm-project?rev=150252&view=rev
Log:
Don't introduce a lambda's operator() into the class until after we
have finished parsing the body, so that name lookup will never find
anything within the closure type. Then, add this operator() and the
conversion function (if available) before completing the class.

Modified:
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=150252&r1=150251&r2=150252&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Feb 10 10:13:20 2012
@@ -102,7 +102,6 @@
                             /*isConstExpr=*/false,
                             EndLoc);
   Method->setAccess(AS_public);
-  Class->addDecl(Method);
 
   // Temporarily set the lexical declaration context to the current
   // context, so that the Scope stack matches the lexical nesting.
@@ -393,17 +392,63 @@
       CallOperator->setType(FunctionTy);
     }
 
-    // Finalize the lambda class.
-    SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end());
-    ActOnFields(0, Class->getLocation(), Class, Fields, 
-                SourceLocation(), SourceLocation(), 0);
-    CheckCompletedCXXClass(Class);
+    // 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);
+    }
 
     // C++ [expr.prim.lambda]p7:
     //   The lambda-expression's compound-statement yields the
     //   function-body (8.4) of the function call operator [...].
     ActOnFinishFunctionBody(CallOperator, Body, /*IsInstantation=*/false);
+
+    // Finalize the lambda class.
+    SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end());
     CallOperator->setLexicalDeclContext(Class);
+    Class->addDecl(CallOperator);
+    ActOnFields(0, Class->getLocation(), Class, Fields, 
+                SourceLocation(), SourceLocation(), 0);
+    CheckCompletedCXXClass(Class);
+
   }
 
   if (LambdaExprNeedsCleanups)
@@ -432,48 +477,5 @@
     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/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp?rev=150252&r1=150251&r2=150252&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp Fri Feb 10 10:13:20 2012
@@ -43,3 +43,12 @@
 }
 
 
+struct S1 {
+  int x, y;
+  int operator()(int);
+  void f() {
+    [&]()->int {
+      return operator()(this->x + y);
+    }(); 
+  }
+};





More information about the cfe-commits mailing list