зеркало из https://github.com/microsoft/clang-1.git
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147595 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
edb9459c43
Коммит
ec9ea72007
|
@ -1078,6 +1078,10 @@ public:
|
|||
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();
|
||||
|
|
|
@ -45,11 +45,17 @@ public:
|
|||
/// \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 @@ public:
|
|||
}
|
||||
|
||||
FunctionScopeInfo(DiagnosticsEngine &Diag)
|
||||
: IsBlockInfo(false),
|
||||
: Kind(SK_Function),
|
||||
HasBranchProtectedScope(false),
|
||||
HasBranchIntoScope(false),
|
||||
HasIndirectGoto(false),
|
||||
|
@ -141,15 +147,55 @@ public:
|
|||
: 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; }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -767,8 +767,9 @@ public:
|
|||
|
||||
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 @@ public:
|
|||
/// 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
|
||||
|
|
|
@ -711,8 +711,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
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 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
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);
|
||||
|
|
|
@ -55,6 +55,7 @@ void FunctionScopeInfo::Clear() {
|
|||
}
|
||||
|
||||
BlockScopeInfo::~BlockScopeInfo() { }
|
||||
LambdaScopeInfo::~LambdaScopeInfo() { }
|
||||
|
||||
PrintingPolicy Sema::getPrintingPolicy() const {
|
||||
PrintingPolicy Policy = Context.getPrintingPolicy();
|
||||
|
@ -828,8 +829,12 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
|
|||
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!");
|
||||
|
||||
|
|
|
@ -7207,7 +7207,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
|||
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
|
||||
|
|
|
@ -6784,7 +6784,7 @@ namespace {
|
|||
|
||||
~ImplicitlyDefinedFunctionScope() {
|
||||
S.PopExpressionEvaluationContext();
|
||||
S.PopFunctionOrBlockScope();
|
||||
S.PopFunctionScopeInfo();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8839,7 +8839,7 @@ void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
|
|||
|
||||
// Pop off CurBlock, handle nested blocks.
|
||||
PopDeclContext();
|
||||
PopFunctionOrBlockScope();
|
||||
PopFunctionScopeInfo();
|
||||
}
|
||||
|
||||
/// ActOnBlockStmtExpr - This is called when the body of a block statement
|
||||
|
@ -8931,7 +8931,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
|
|||
|
||||
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.
|
||||
|
|
|
@ -4778,20 +4778,68 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
|
|||
// 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();
|
||||
|
||||
// Enter a new evaluation context to insulate the block from any
|
||||
// cleanups from the enclosing full-expression.
|
||||
PushExpressionEvaluationContext(PotentiallyEvaluated);
|
||||
}
|
||||
// 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);
|
||||
|
||||
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 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
|
|||
PopExpressionEvaluationContext();
|
||||
|
||||
// Leave the context of the lambda.
|
||||
// FIXME: PopDeclContext
|
||||
// FIXME: Pop lambda-scope
|
||||
PopDeclContext();
|
||||
PopFunctionScopeInfo();
|
||||
}
|
||||
|
||||
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
|
||||
|
|
|
@ -14,10 +14,7 @@ class C {
|
|||
[] {}; // 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}}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче