[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