]> granicus.if.org Git - clang/commitdiff
When completing a lambda expression, make sure to check and attach the
authorDouglas Gregor <dgregor@apple.com>
Wed, 8 Feb 2012 20:17:14 +0000 (20:17 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 8 Feb 2012 20:17:14 +0000 (20:17 +0000)
body of the lambda to the function call operator.

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

include/clang/AST/ExprCXX.h
include/clang/Sema/ScopeInfo.h
include/clang/Sema/Sema.h
lib/Sema/Sema.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp
test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp [new file with mode: 0644]

index 6161f92d3fbe2d5aac368e12c771882ea6a07c75..b9ba3c37555ee557d88ec4756202fde66f90c63c 100644 (file)
@@ -1226,8 +1226,7 @@ public:
   }
 
   /// \brief Retrieve the iterator pointing one past the last
-  /// initialization argument for this lambda expression (which
-  /// initializes the first capture field).
+  /// initialization argument for this lambda expression.
   capture_init_iterator capture_init_end() const {
     return capture_init_begin() + NumCaptures;
   }
index d6b10720c6d395ade68ff990bb37debf3b24b0dc..d1e47b2b2f33aa62584984cd03de1cff81f3c541 100644 (file)
@@ -280,6 +280,9 @@ public:
   /// \brief The class that describes the lambda.
   CXXRecordDecl *Lambda;
 
+  /// \brief The class that describes the lambda.
+  CXXMethodDecl *CallOperator;
+
   /// \brief Source range covering the lambda introducer [...].
   SourceRange IntroducerRange;
 
@@ -292,9 +295,10 @@ public:
   /// \brief Whether the (empty) parameter list is explicit.
   bool ExplicitParams;
 
-  LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda)
+  LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
+                  CXXMethodDecl *CallOperator)
     : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
-      NumExplicitCaptures(0), Mutable(false)
+      CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false)
   {
     Kind = SK_Lambda;
   }
index e7441ada130591ee1935fba7398ab6a45a3f2002..6a0ffa9b3045cb5847c1ac73330320408048e370 100644 (file)
@@ -732,7 +732,7 @@ public:
 
   void PushFunctionScope();
   void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
-  void PushLambdaScope(CXXRecordDecl *Lambda);
+  void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator);
   void PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP =0,
                             const Decl *D = 0, const BlockExpr *blkExpr = 0);
 
index 9c5bdbea6ad99816111f9fa75ed247ad0d28c568..22d2a20d457271a0e6272c9f634b00bab139c1aa 100644 (file)
@@ -831,8 +831,10 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
                                               BlockScope, Block));
 }
 
-void Sema::PushLambdaScope(CXXRecordDecl *Lambda) {
-  FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda));
+void Sema::PushLambdaScope(CXXRecordDecl *Lambda, 
+                           CXXMethodDecl *CallOperator) {
+  FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,
+                                               CallOperator));
 }
 
 void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
index ffc7c618727c0ab81a4d022bd291ee10deeadfc1..ed8d8a5d71bb556253e916d2b61616b57fff4860 100644 (file)
@@ -7236,7 +7236,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
       computeNRVO(Body, getCurFunction());
     }
     
-    assert(FD == getCurFunctionDecl() && "Function parsing confused");
+    assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) &&
+           "Function parsing confused");
   } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
     assert(MD == getCurMethodDecl() && "Method parsing confused");
     MD->setBody(Body);
index 182956523821e3c2ea5d423cfe6f3d51e5a567a1..bbf992c21987e9673dce8ed1cb40ba3167a01e9c 100644 (file)
@@ -9722,8 +9722,6 @@ void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc,
       // of the copy/move done to move a __block variable to the heap.
       type.addConst();
 
-      // FIXME: Add an initialized entity for lambda capture.
-      // FIXME: Won't work for arrays, although we do need this behavior.
       Expr *declRef = new (Context) DeclRefExpr(var, type, VK_LValue, loc);
       ExprResult result =
         PerformCopyInitialization(
index cd2c210a39c04131c89c9e75e6d2cdc602657120..98ab97808c9f554cc591941d7d4cfeaaaf854cee 100644 (file)
@@ -4896,6 +4896,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
   QualType MethodTy;
   TypeSourceInfo *MethodTyInfo;
   bool ExplicitParams = true;
+  SourceLocation EndLoc;
   if (ParamInfo.getNumTypeObjects() == 0) {
     // C++11 [expr.prim.lambda]p4:
     //   If a lambda-expression does not include a lambda-declarator, it is as 
@@ -4906,6 +4907,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
                                        /*Args=*/0, /*NumArgs=*/0, EPI);
     MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
     ExplicitParams = false;
+    EndLoc = Intro.Range.getEnd();
   } else {
     assert(ParamInfo.isFunctionDeclarator() &&
            "lambda-declarator is a function");
@@ -4928,6 +4930,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
     assert(MethodTyInfo && "no type from lambda-declarator");
     MethodTy = MethodTyInfo->getType();
     assert(!MethodTy.isNull() && "no type from lambda declarator");
+    EndLoc = ParamInfo.getSourceRange().getEnd();
   }
   
   // C++11 [expr.prim.lambda]p5:
@@ -4937,19 +4940,22 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
   //   trailing-return-type respectively.
   DeclarationName MethodName
     = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclarationNameLoc MethodNameLoc;
+  MethodNameLoc.CXXOperatorName.BeginOpNameLoc
+    = Intro.Range.getBegin().getRawEncoding();
+  MethodNameLoc.CXXOperatorName.EndOpNameLoc
+    = Intro.Range.getEnd().getRawEncoding();
   CXXMethodDecl *Method
-    = CXXMethodDecl::Create(Context,
-                            Class,
-                            ParamInfo.getSourceRange().getEnd(),
-                            DeclarationNameInfo(MethodName,
-                                                /*NameLoc=*/SourceLocation()),
-                            MethodTy,
-                            MethodTyInfo,
+    = CXXMethodDecl::Create(Context, Class, EndLoc,
+                            DeclarationNameInfo(MethodName, 
+                                                Intro.Range.getBegin(),
+                                                MethodNameLoc),
+                            MethodTy, MethodTyInfo,
                             /*isStatic=*/false,
                             SC_None,
                             /*isInline=*/true,
                             /*isConstExpr=*/false,
-                            ParamInfo.getSourceRange().getEnd());
+                            EndLoc);
   Method->setAccess(AS_public);
   Class->addDecl(Method);
   Method->setLexicalDeclContext(DC); // FIXME: Minor hack.
@@ -4963,7 +4969,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
   PushDeclContext(CurScope, Method);
     
   // Introduce the lambda scope.
-  PushLambdaScope(Class);
+  PushLambdaScope(Class, Method);
   LambdaScopeInfo *LSI = getCurLambda();
   if (Intro.Default == LCD_ByCopy)
     LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
@@ -5123,9 +5129,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
   DiscardCleanupsInEvaluationContext();
   PopExpressionEvaluationContext();
 
-  // Leave the context of the lambda.
-  PopDeclContext();
-
   // FIXME: End-of-lambda checking
 
   // Collect information from the lambda scope.
@@ -5184,7 +5187,10 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
       break;
     }
 
-    PopFunctionScopeInfo();
+    // C++ [expr.prim.lambda]p7:
+    //   The lambda-expression’s compound-statement yields the
+    //   function-body (8.4) of the function call operator [...].
+    ActOnFinishFunctionBody(LSI->CallOperator, Body, /*IsInstantation=*/false);
   }
 
   Expr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, 
index a02340f8b96f033749970d5338819b51d7f8c44c..7264fa18d06c5771585f4c4227282afa7c16bb5b 100644 (file)
@@ -5,6 +5,6 @@ class NonCopyable {
 };
 
 void capture_by_ref(NonCopyable nc, NonCopyable &ncr) {
-  [&nc] {}; // expected-error{{lambda expressions are not supported yet}}
-  [&ncr] {}; // expected-error{{lambda expressions are not supported yet}}
+  [&nc] () -> void {}; // expected-error{{lambda expressions are not supported yet}}
+  [&ncr] () -> void {}; // expected-error{{lambda expressions are not supported yet}}
 }
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp
new file mode 100644 (file)
index 0000000..239b6d4
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+// Check that analysis-based warnings work in lambda bodies.
+void analysis_based_warnings() {
+  []() -> int { }; // expected-warning{{control reaches end of non-void function}} \
+  // expected-error{{lambda expressions are not supported yet}}
+}
+
+// FIXME: Also check translation of captured vars to data members,
+// most of which isn't in the AST.
+
+