[cfe-commits] r147595 - in /cfe/trunk: include/clang/AST/TypeLoc.h include/clang/Sema/ScopeInfo.h include/clang/Sema/Sema.h lib/Parse/ParseExprCXX.cpp lib/Sema/Sema.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp test/Parser/objcxx0x-lambda-expressions.mm

Eli Friedman eli.friedman at gmail.com
Wed Jan 4 19:35:19 PST 2012


Author: efriedma
Date: Wed Jan  4 21:35:19 2012
New Revision: 147595

URL: http://llvm.org/viewvc/llvm-project?rev=147595&view=rev
Log:
More lambda work. Tweak the Sema interface slightly.  Start adding the pieces to build the lambda class and its call operator.  Create an actual scope for the lambda body.


Modified:
    cfe/trunk/include/clang/AST/TypeLoc.h
    cfe/trunk/include/clang/Sema/ScopeInfo.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm

Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Wed Jan  4 21:35:19 2012
@@ -1078,6 +1078,10 @@
     getLocalData()->TrailingReturn = Trailing;
   }
 
+  ArrayRef<ParmVarDecl *> getParams() const {
+    return ArrayRef<ParmVarDecl *>(getParmArray(), getNumArgs());
+  }
+
   // ParmVarDecls* are stored after Info, one for each argument.
   ParmVarDecl **getParmArray() const {
     return (ParmVarDecl**) getExtraLocalData();

Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Wed Jan  4 21:35:19 2012
@@ -45,11 +45,17 @@
 /// \brief Retains information about a function, method, or block that is
 /// currently being parsed.
 class FunctionScopeInfo {
+protected:
+  enum ScopeKind {
+    SK_Function,
+    SK_Block,
+    SK_Lambda
+  };
+  
 public:
-
-  /// \brief Whether this scope information structure defined information for
-  /// a block.
-  bool IsBlockInfo;
+  /// \brief What kind of scope we are describing.
+  ///
+  ScopeKind Kind;
 
   /// \brief Whether this function contains a VLA, @try, try, C++
   /// initializer, or anything else that can't be jumped past.
@@ -96,7 +102,7 @@
   }
   
   FunctionScopeInfo(DiagnosticsEngine &Diag)
-    : IsBlockInfo(false),
+    : Kind(SK_Function),
       HasBranchProtectedScope(false),
       HasBranchIntoScope(false),
       HasIndirectGoto(false),
@@ -141,15 +147,55 @@
     : FunctionScopeInfo(Diag), TheDecl(Block), TheScope(BlockScope),
       CapturesCXXThis(false)
   {
-    IsBlockInfo = true;
+    Kind = SK_Block;
   }
 
   virtual ~BlockScopeInfo();
 
-  static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; }
+  static bool classof(const FunctionScopeInfo *FSI) { 
+    return FSI->Kind == SK_Block; 
+  }
   static bool classof(const BlockScopeInfo *BSI) { return true; }
 };
 
+class LambdaScopeInfo : public FunctionScopeInfo {
+public:
+  /// \brief The class that describes the lambda.
+  CXXRecordDecl *Lambda;
+  
+  /// \brief A mapping from the set of captured variables to the 
+  /// fields (within the lambda class) that represent the captured variables.
+  llvm::DenseMap<VarDecl *, FieldDecl *> CapturedVariables;
+  
+  /// \brief The list of captured variables, starting with the explicit 
+  /// captures and then finishing with any implicit captures.
+  // TODO: This is commented out until an implementation of LambdaExpr is
+  // committed.
+  //  llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
+  
+  /// \brief The number of captures in the \c Captures list that are 
+  /// explicit captures.
+  unsigned NumExplicitCaptures;
+  
+  /// \brief The field associated with the captured 'this' pointer.
+  FieldDecl *ThisCapture;
+
+  LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda) 
+    : FunctionScopeInfo(Diag), Lambda(Lambda), 
+      NumExplicitCaptures(0), ThisCapture(0) 
+  {
+    Kind = SK_Lambda;
+  }
+    
+  virtual ~LambdaScopeInfo();
+  
+  static bool classof(const FunctionScopeInfo *FSI) { 
+    return FSI->Kind == SK_Lambda; 
+  }
+  static bool classof(const LambdaScopeInfo *BSI) { return true; }
+
+};
+
 }
 }
 

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Jan  4 21:35:19 2012
@@ -767,8 +767,9 @@
 
   void PushFunctionScope();
   void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
-  void PopFunctionOrBlockScope(const sema::AnalysisBasedWarnings::Policy *WP =0,
-                               const Decl *D = 0, const BlockExpr *blkExpr = 0);
+  void PushLambdaScope(CXXRecordDecl *Lambda);
+  void PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP =0,
+                            const Decl *D = 0, const BlockExpr *blkExpr = 0);
 
   sema::FunctionScopeInfo *getCurFunction() const {
     return FunctionScopes.back();
@@ -3449,16 +3450,15 @@
   /// initializer for the declaration 'Dcl'.
   void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
 
-  /// ActOnLambdaStart - This callback is invoked when a lambda expression is
-  /// started.
-  void ActOnLambdaStart(SourceLocation StartLoc, Scope *CurScope);
-
-  /// ActOnLambdaArguments - This callback allows processing of lambda arguments.
-  /// If there are no arguments, this is still invoked.
-  void ActOnLambdaArguments(Declarator &ParamInfo, Scope *CurScope);
+  /// ActOnStartOfLambdaDefinition - This is called just before we start
+  /// parsing the body of a lambda; it analyzes the explicit captures and 
+  /// arguments, and sets up various data-structures for the body of the
+  /// lambda.
+  void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                    Declarator &ParamInfo, Scope *CurScope);
 
   /// ActOnLambdaError - If there is an error parsing a lambda, this callback
-  /// is invoked to pop the information about the lambda from the action impl.
+  /// is invoked to pop the information about the lambda.
   void ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope);
 
   /// ActOnLambdaExpr - This is called when the body of a lambda expression

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Jan  4 21:35:19 2012
@@ -711,8 +711,6 @@
   PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
                                 "lambda expression parsing");
 
-  Actions.ActOnLambdaStart(LambdaBeginLoc, getCurScope());
-
   // Parse lambda-declarator[opt].
   DeclSpec DS(AttrFactory);
   Declarator D(DS, Declarator::LambdaExprContext);
@@ -792,11 +790,10 @@
                                            DeclLoc, DeclEndLoc, D,
                                            TrailingReturnType),
                   Attr, DeclEndLoc);
-
-    // Inform sema that we are starting a block.
-    Actions.ActOnLambdaArguments(D, getCurScope());
   }
 
+  Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());
+
   // Parse compound-statement.
   if (!Tok.is(tok::l_brace)) {
     Diag(Tok, diag::err_expected_lambda_body);

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Wed Jan  4 21:35:19 2012
@@ -55,6 +55,7 @@
 }
 
 BlockScopeInfo::~BlockScopeInfo() { }
+LambdaScopeInfo::~LambdaScopeInfo() { }
 
 PrintingPolicy Sema::getPrintingPolicy() const {
   PrintingPolicy Policy = Context.getPrintingPolicy();
@@ -828,8 +829,12 @@
                                               BlockScope, Block));
 }
 
-void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP,
-                                   const Decl *D, const BlockExpr *blkExpr) {
+void Sema::PushLambdaScope(CXXRecordDecl *Lambda) {
+  FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda));
+}
+
+void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
+                                const Decl *D, const BlockExpr *blkExpr) {
   FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();  
   assert(!FunctionScopes.empty() && "mismatched push/pop!");
   

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Jan  4 21:35:19 2012
@@ -7207,7 +7207,7 @@
   if (!IsInstantiation)
     PopDeclContext();
 
-  PopFunctionOrBlockScope(ActivePolicy, dcl);
+  PopFunctionScopeInfo(ActivePolicy, dcl);
   
   // If any errors have occurred, clear out any temporaries that may have
   // been leftover. This ensures that these temporaries won't be picked up for

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Jan  4 21:35:19 2012
@@ -6784,7 +6784,7 @@
     
     ~ImplicitlyDefinedFunctionScope() {
       S.PopExpressionEvaluationContext();
-      S.PopFunctionOrBlockScope();
+      S.PopFunctionScopeInfo();
     }
   };
 }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jan  4 21:35:19 2012
@@ -8839,7 +8839,7 @@
 
   // Pop off CurBlock, handle nested blocks.
   PopDeclContext();
-  PopFunctionOrBlockScope();
+  PopFunctionScopeInfo();
 }
 
 /// ActOnBlockStmtExpr - This is called when the body of a block statement
@@ -8931,7 +8931,7 @@
   
   BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
   const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
-  PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result);
+  PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result);
 
   // If the block isn't obviously global, i.e. it captures anything at
   // all, mark this full-expression as needing a cleanup.

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Jan  4 21:35:19 2012
@@ -4778,20 +4778,68 @@
 // Lambdas.
 //===----------------------------------------------------------------------===//
 
-void Sema::ActOnLambdaStart(SourceLocation StartLoc, Scope *CurScope) {
-  // FIXME: Add lambda-scope
-  // FIXME: PushDeclContext
+void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                        Declarator &ParamInfo,
+                                        Scope *CurScope) {
+  DeclContext *DC = CurContext;
+  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isNamespace()))
+    DC = DC->getParent();
+
+  // Start constructing the lambda class.
+  CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC,
+                                               Intro.Range.getBegin(),
+                                               /*IdLoc=*/SourceLocation(),
+                                               /*Id=*/0);
+  Class->startDefinition();
+  CurContext->addDecl(Class);
 
-  // Enter a new evaluation context to insulate the block from any
-  // cleanups from the enclosing full-expression.
-  PushExpressionEvaluationContext(PotentiallyEvaluated);  
-}
-
-void Sema::ActOnLambdaArguments(Declarator &ParamInfo, Scope *CurScope) {
+  // Build the call operator; we don't really have all the relevant information
+  // at this point, but we need something to attach child declarations to.
   TypeSourceInfo *MethodTyInfo;
   MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
 
-  // FIXME: Build CXXMethodDecl
+  DeclarationName MethodName
+    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  CXXMethodDecl *Method
+    = CXXMethodDecl::Create(Context,
+                            Class,
+                            ParamInfo.getSourceRange().getEnd(),
+                            DeclarationNameInfo(MethodName,
+                                                /*NameLoc=*/SourceLocation()),
+                            MethodTyInfo->getType(),
+                            MethodTyInfo,
+                            /*isStatic=*/false,
+                            SC_None,
+                            /*isInline=*/true,
+                            /*isConstExpr=*/false,
+                            ParamInfo.getSourceRange().getEnd());
+  Method->setAccess(AS_public);
+  Class->addDecl(Method);
+  Method->setLexicalDeclContext(DC); // FIXME: Is this really correct?
+
+  // Set the parameters on the decl, if specified.
+  if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
+    FunctionProtoTypeLoc Proto =
+        cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
+    Method->setParams(Proto.getParams());
+    CheckParmsForFunctionDef(Method->param_begin(),
+                             Method->param_end(),
+                             /*CheckParameterNames=*/false);
+  }
+
+  ProcessDeclAttributes(CurScope, Method, ParamInfo);
+
+  // FIXME: There's a bunch of missing checking etc;
+  // see ActOnBlockArguments
+
+  // Introduce the lambda scope.
+  PushLambdaScope(Class);
+
+  // Enter a new evaluation context to insulate the block from any
+  // cleanups from the enclosing full-expression.
+  PushExpressionEvaluationContext(PotentiallyEvaluated);
+
+  PushDeclContext(CurScope, Method);
 }
 
 void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
@@ -4800,8 +4848,8 @@
   PopExpressionEvaluationContext();
 
   // Leave the context of the lambda.
-  // FIXME: PopDeclContext
-  // FIXME: Pop lambda-scope
+  PopDeclContext();
+  PopFunctionScopeInfo();
 }
 
 ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,

Modified: cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm?rev=147595&r1=147594&r2=147595&view=diff
==============================================================================
--- cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm (original)
+++ cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm Wed Jan  4 21:35:19 2012
@@ -14,10 +14,7 @@
     [] {}; // expected-error {{lambda expressions are not supported yet}}
     [=] (int i) {}; // expected-error {{lambda expressions are not supported yet}}
     [&] (int) mutable -> void {}; // expected-error {{lambda expressions are not supported yet}}
-    // FIXME: this error occurs because we do not yet handle lambda scopes
-    // properly. I did not anticipate it because I thought it was a semantic (not
-    // syntactic) check.
-    [foo,bar] () { return 3; }; // expected-error {{void function 'f' should not return a value}} expected-error {{lambda expressions are not supported yet}}
+    [foo,bar] () { return 3; }; // expected-error {{lambda expressions are not supported yet}}
     [=,&foo] () {}; // expected-error {{lambda expressions are not supported yet}}
     [this] () {}; // expected-error {{lambda expressions are not supported yet}}
   }





More information about the cfe-commits mailing list