diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/include/clang/Sema/DeclSpec.h | 18 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 38 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 8 | ||||
-rw-r--r-- | clang/test/Parser/cxx0x-lambda-expressions.cpp | 18 | ||||
-rw-r--r-- | clang/test/Parser/objcxx0x-lambda-expressions.mm | 10 |
6 files changed, 84 insertions, 10 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 11fd91ab5bd..18d5796ea14 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4887,6 +4887,8 @@ let CategoryName = "Lambda Issue" in { def note_lambda_to_block_conv : Note< "implicit capture of lambda object due to conversion to block pointer " "here">; + def err_lambda_init_capture_unsupported : Error< + "sorry, initialized lambda-captures are not supported yet">; } def err_return_in_captured_stmt : Error< diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 059919a35bb..7ee2c6cc1e5 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -2088,13 +2088,15 @@ private: struct LambdaCapture { LambdaCaptureKind Kind; SourceLocation Loc; - IdentifierInfo* Id; + IdentifierInfo *Id; SourceLocation EllipsisLoc; - + ExprResult Init; + LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc, IdentifierInfo* Id = 0, - SourceLocation EllipsisLoc = SourceLocation()) - : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc) + SourceLocation EllipsisLoc = SourceLocation(), + ExprResult Init = ExprResult()) + : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init) {} }; @@ -2111,11 +2113,11 @@ struct LambdaIntroducer { /// \brief Append a capture in a lambda introducer. void addCapture(LambdaCaptureKind Kind, SourceLocation Loc, - IdentifierInfo* Id = 0, - SourceLocation EllipsisLoc = SourceLocation()) { - Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc)); + IdentifierInfo* Id = 0, + SourceLocation EllipsisLoc = SourceLocation(), + ExprResult Init = ExprResult()) { + Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, Init)); } - }; } // end namespace clang diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index f259d5f59b4..86e2e187d3e 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -583,7 +583,7 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { Tok.is(tok::l_paren), isAddressOfOperand); } -/// ParseLambdaExpression - Parse a C++0x lambda expression. +/// ParseLambdaExpression - Parse a C++11 lambda expression. /// /// lambda-expression: /// lambda-introducer lambda-declarator[opt] compound-statement @@ -605,10 +605,18 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { /// capture-list ',' capture /// /// capture: +/// simple-capture +/// init-capture [C++1y] +/// +/// simple-capture: /// identifier /// '&' identifier /// 'this' /// +/// init-capture: [C++1y] +/// identifier initializer +/// '&' identifier initializer +/// /// lambda-declarator: /// '(' parameter-declaration-clause ')' attribute-specifier[opt] /// 'mutable'[opt] exception-specification[opt] @@ -737,6 +745,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) { SourceLocation Loc; IdentifierInfo* Id = 0; SourceLocation EllipsisLoc; + ExprResult Init; if (Tok.is(tok::kw_this)) { Kind = LCK_This; @@ -768,9 +777,31 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) { } else { return DiagResult(diag::err_expected_capture); } + + if (Tok.is(tok::l_paren)) { + BalancedDelimiterTracker Parens(*this, tok::l_paren); + Parens.consumeOpen(); + + ExprVector Exprs; + CommaLocsTy Commas; + if (ParseExpressionList(Exprs, Commas)) { + Parens.skipToEnd(); + Init = ExprError(); + } else { + Parens.consumeClose(); + Init = Actions.ActOnParenListExpr(Parens.getOpenLocation(), + Parens.getCloseLocation(), + Exprs); + } + } else if (Tok.is(tok::l_brace) || Tok.is(tok::equal)) { + if (Tok.is(tok::equal)) + ConsumeToken(); + + Init = ParseInitializer(); + } } - Intro.addCapture(Kind, Loc, Id, EllipsisLoc); + Intro.addCapture(Kind, Loc, Id, EllipsisLoc, Init); } T.consumeClose(); @@ -806,6 +837,9 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc, "lambda expression parsing"); + // FIXME: Call into Actions to add any init-capture declarations to the + // scope while parsing the lambda-declarator and compound-statement. + // Parse lambda-declarator[opt]. DeclSpec DS(AttrFactory); Declarator D(DS, Declarator::LambdaExprContext); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 24388dd0f52..4e11bb4c055 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -559,6 +559,14 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, continue; } + // FIXME: C++1y [expr.prim.lambda]p11 + if (C->Init.isInvalid()) + continue; + if (C->Init.isUsable()) { + Diag(C->Loc, diag::err_lambda_init_capture_unsupported); + continue; + } + assert(C->Id && "missing identifier for capture"); // C++11 [expr.prim.lambda]p8: diff --git a/clang/test/Parser/cxx0x-lambda-expressions.cpp b/clang/test/Parser/cxx0x-lambda-expressions.cpp index 642c69a532e..d7dc7d3a473 100644 --- a/clang/test/Parser/cxx0x-lambda-expressions.cpp +++ b/clang/test/Parser/cxx0x-lambda-expressions.cpp @@ -48,4 +48,22 @@ class C { delete [] { return new int; } (); // expected-error{{expected expression}} delete [&] { return new int; } (); // ok, lambda } + + // We support init-captures in C++11 as an extension. + int z; + void init_capture() { + // FIXME: These diagnostics should all disappear once semantic analysis + // for init-captures is complete. + [n(0)] () -> int { return ++n; }; // expected-error {{not supported}} expected-error {{undeclared}} + [n{0}] { return; }; // expected-error {{not supported}} + [n = 0] { return ++n; }; // expected-error {{not supported}} expected-error {{undeclared}} + [n = {0}] { return; }; // expected-error {{not supported}} + [a([&b = z]{})](){}; // expected-error 2{{not supported}} + + int x = 4; // expected-note {{here}} + auto y = [&r = x, x = x + 1]() -> int { // expected-error 2{{not supported}} expected-note {{here}} + r += 2; // expected-error {{undeclared}} + return x + 2; // expected-error {{implicitly captured}} + } (); + } }; diff --git a/clang/test/Parser/objcxx0x-lambda-expressions.mm b/clang/test/Parser/objcxx0x-lambda-expressions.mm index fb90b16a971..94e47ccd3e0 100644 --- a/clang/test/Parser/objcxx0x-lambda-expressions.mm +++ b/clang/test/Parser/objcxx0x-lambda-expressions.mm @@ -17,6 +17,16 @@ class C { [foo,bar] () { return 3; }; [=,&foo] () {}; [this] () {}; + + [foo(bar)] () {}; // expected-error {{not supported}} + [foo = bar] () {}; // expected-error {{not supported}} + [foo{bar}] () {}; // expected-error {{not supported}} + [foo = {bar}] () {}; // expected-error {{not supported}} + + [foo(bar) baz] () {}; // expected-error {{called object type 'int' is not a function}} + + // FIXME: These are some appalling diagnostics. + [foo = bar baz]; // expected-error {{missing '['}} expected-warning 2{{receiver type 'int'}} expected-warning 2{{instance method '-baz'}} } }; |