]> granicus.if.org Git - clang/commitdiff
Don't introduce a lambda's operator() into the class until after we
authorDouglas Gregor <dgregor@apple.com>
Fri, 10 Feb 2012 16:13:20 +0000 (16:13 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 10 Feb 2012 16:13:20 +0000 (16:13 +0000)
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.

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

lib/Sema/SemaLambda.cpp
test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp

index ed05eff8e1236da0285cbfc32cdb7316408b79b9..64fe7f7dcea7999ca5a64443aba4cc66cd85d95b 100644 (file)
@@ -102,7 +102,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
                             /*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 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
       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 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
     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);
 }
index 21c8e22092bddba8308df1b401782e6fc5fcf06a..8fa3837214d3f2d58e00d8f6453f1909d6f6c71f 100644 (file)
@@ -43,3 +43,12 @@ void test_capture_constness(int i, const int ic) {
 }
 
 
+struct S1 {
+  int x, y;
+  int operator()(int);
+  void f() {
+    [&]()->int {
+      return operator()(this->x + y);
+    }(); 
+  }
+};