summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-01-04 02:40:39 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-01-04 02:40:39 +0000
commitc7c97144afcb8a7ceeadd3d56ee0b25acd43856b (patch)
treef46bd2ff2dea61e99cae041908811228d230f1bd
parentcc1d7893d6e80ac3aa9240df01bdda50ece48db8 (diff)
downloadbcm5719-llvm-c7c97144afcb8a7ceeadd3d56ee0b25acd43856b.tar.gz
bcm5719-llvm-c7c97144afcb8a7ceeadd3d56ee0b25acd43856b.zip
Stub out the Sema interface for lambda expressions, and change the parser to use it. Unconditionally error on lambda expressions because they don't work in any meaningful way yet.
llvm-svn: 147515
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/include/clang/Sema/Sema.h17
-rw-r--r--clang/lib/Parse/ParseExpr.cpp7
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp59
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp35
-rw-r--r--clang/test/Parser/cxx0x-attributes.cpp2
-rw-r--r--clang/test/Parser/cxx0x-lambda-expressions.cpp14
-rw-r--r--clang/test/Parser/objcxx0x-lambda-expressions.mm12
-rw-r--r--clang/test/SemaCXX/cxx98-compat.cpp3
9 files changed, 118 insertions, 33 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7e5fff8ab46..d5047506cc9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3984,6 +3984,8 @@ def err_throw_incomplete_ptr : Error<
def err_return_in_constructor_handler : Error<
"return in the catch of a function try block of a constructor is illegal">;
+def err_lambda_unsupported : Error<"lambda expressions are not supported yet">;
+
def err_operator_arrow_circular : Error<
"circular pointer delegation detected">;
def err_pseudo_dtor_base_not_scalar : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 086bf23dab0..940ae2da989 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3449,6 +3449,23 @@ 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);
+
+ /// ActOnLambdaError - If there is an error parsing a lambda, this callback
+ /// is invoked to pop the information about the lambda from the action impl.
+ void ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope);
+
+ /// ActOnLambdaExpr - This is called when the body of a lambda expression
+ /// was successfully completed.
+ ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
+ Scope *CurScope);
+
// ParseObjCStringLiteral - Parse Objective-C string literals.
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
Expr **Strings,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 0dd48a29469..7eac9841725 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1132,8 +1132,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::l_square:
if (getLang().CPlusPlus0x) {
if (getLang().ObjC1) {
+ // C++11 lambda expressions and Objective-C message sends both start with a
+ // square bracket. There are three possibilities here:
+ // we have a valid lambda expression, we have an invalid lambda
+ // expression, or we have something that doesn't appear to be a lambda.
+ // If we're in the last case, we fall back to ParseObjCMessageExpression.
Res = TryParseLambdaExpression();
- if (Res.isInvalid())
+ if (!Res.isInvalid() && !Res.get())
Res = ParseObjCMessageExpression();
break;
}
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index bd97fcee7c5..901a537f5ed 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
+#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -563,6 +564,9 @@ ExprResult Parser::ParseLambdaExpression() {
if (DiagID) {
Diag(Tok, DiagID.getValue());
SkipUntil(tok::r_square);
+ SkipUntil(tok::l_brace);
+ SkipUntil(tok::r_brace);
+ return ExprError();
}
return ParseLambdaExpressionAfterIntroducer(Intro);
@@ -591,14 +595,21 @@ ExprResult Parser::TryParseLambdaExpression() {
return ParseLambdaExpression();
}
- // If lookahead indicates this is an Objective-C message...
+ // If lookahead indicates an ObjC message send...
+ // [identifier identifier
if (Next.is(tok::identifier) && After.is(tok::identifier)) {
- return ExprError();
+ return ExprEmpty();
}
+ // Here, we're stuck: lambda introducers and Objective-C message sends are
+ // unambiguous, but it requires arbitrary lookhead. [a,b,c,d,e,f,g] is a
+ // lambda, and [a,b,c,d,e,f,g h] is a Objective-C message send. Instead of
+ // writing two routines to parse a lambda introducer, just try to parse
+ // a lambda introducer first, and fall back if that fails.
+ // (TryParseLambdaIntroducer never produces any diagnostic output.)
LambdaIntroducer Intro;
if (TryParseLambdaIntroducer(Intro))
- return ExprError();
+ return ExprEmpty();
return ParseLambdaExpressionAfterIntroducer(Intro);
}
@@ -694,11 +705,17 @@ bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) {
/// expression.
ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
LambdaIntroducer &Intro) {
- Diag(Intro.Range.getBegin(), diag::warn_cxx98_compat_lambda);
+ SourceLocation LambdaBeginLoc = Intro.Range.getBegin();
+ Diag(LambdaBeginLoc, diag::warn_cxx98_compat_lambda);
+
+ PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
+ "lambda expression parsing");
+
+ Actions.ActOnLambdaStart(LambdaBeginLoc, getCurScope());
// Parse lambda-declarator[opt].
DeclSpec DS(AttrFactory);
- Declarator D(DS, Declarator::PrototypeContext);
+ Declarator D(DS, Declarator::BlockLiteralContext);
if (Tok.is(tok::l_paren)) {
ParseScope PrototypeScope(this,
@@ -775,24 +792,32 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
DeclLoc, DeclEndLoc, D,
TrailingReturnType),
Attr, DeclEndLoc);
+
+ // Inform sema that we are starting a block.
+ Actions.ActOnLambdaArguments(D, getCurScope());
}
// Parse compound-statement.
- if (Tok.is(tok::l_brace)) {
- // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
- // it.
- ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
- Scope::BreakScope | Scope::ContinueScope |
- Scope::DeclScope);
-
- ParseCompoundStatementBody();
-
- BodyScope.Exit();
- } else {
+ if (!Tok.is(tok::l_brace)) {
Diag(Tok, diag::err_expected_lambda_body);
+ Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope());
+ return ExprError();
}
- return ExprEmpty();
+ // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
+ // it.
+ ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
+ Scope::BreakScope | Scope::ContinueScope |
+ Scope::DeclScope);
+ StmtResult Stmt(ParseCompoundStatementBody());
+ BodyScope.Exit();
+
+ if (!Stmt.isInvalid())
+ return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(),
+ getCurScope());
+
+ Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope());
+ return ExprError();
}
/// ParseCXXCasts - This handles the various ways to cast expressions to another
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index eaa330b183a..67e1c2fb099 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4774,3 +4774,38 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
}
+//===----------------------------------------------------------------------===//
+// Lambdas.
+//===----------------------------------------------------------------------===//
+
+void Sema::ActOnLambdaStart(SourceLocation StartLoc, Scope *CurScope) {
+ // FIXME: Add lambda-scope
+ // FIXME: Build lambda-decl
+ // FIXME: PushDeclContext
+
+ // 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) {
+ // FIXME: Implement
+}
+
+void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
+ // Leave the expression-evaluation context.
+ DiscardCleanupsInEvaluationContext();
+ PopExpressionEvaluationContext();
+
+ // Leave the context of the lambda.
+ // FIXME: PopDeclContext
+ // FIXME: Pop lambda-scope
+}
+
+ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
+ Stmt *Body, Scope *CurScope) {
+ // FIXME: Implement
+ Diag(StartLoc, diag::err_lambda_unsupported);
+ ActOnLambdaError(StartLoc, CurScope);
+ return ExprError();
+}
diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp
index e762b57a93d..ff9118a0e15 100644
--- a/clang/test/Parser/cxx0x-attributes.cpp
+++ b/clang/test/Parser/cxx0x-attributes.cpp
@@ -20,7 +20,7 @@ int scope_attr [[foo::]]; // expected-error {{expected identifier}}
unsigned [[]] int attr_in_decl_spec; // expected-error {{expected unqualified-id}}
int & [[]] ref_attr = after_attr; // expected-error {{an attribute list cannot appear here}}
class foo {
- void after_const_attr () const [[]]; // expected-error {{expected body of lambda expression}} expected-error {{array has incomplete element type 'void'}}
+ void after_const_attr () const [[]]; // expected-error {{expected body of lambda expression}}
};
extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}}
[[]] template <typename T> void before_template_attr (); // expected-error {{an attribute list cannot appear here}}
diff --git a/clang/test/Parser/cxx0x-lambda-expressions.cpp b/clang/test/Parser/cxx0x-lambda-expressions.cpp
index 4fa4e6f1b99..df8d804931d 100644
--- a/clang/test/Parser/cxx0x-lambda-expressions.cpp
+++ b/clang/test/Parser/cxx0x-lambda-expressions.cpp
@@ -12,13 +12,13 @@ class C {
[&this] {}; // expected-error {{'this' cannot be captured by reference}}
[&,] {}; // expected-error {{expected variable name or 'this' in lambda capture list}}
[=,] {}; // expected-error {{expected variable name or 'this' in lambda capture list}}
- [] {};
- [=] (int i) {};
- [&] (int) mutable -> void {};
- [foo,bar] () { return 3; };
- [=,&foo] () {};
- [&,foo] () {};
- [this] () {};
+ [] {}; // 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}}
+ [foo,bar] () { return 3; }; // expected-error {{lambda expressions are not supported yet}}
+ [=,&foo] () {}; // 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}}
return 1;
}
diff --git a/clang/test/Parser/objcxx0x-lambda-expressions.mm b/clang/test/Parser/objcxx0x-lambda-expressions.mm
index 937464918b6..b9a96d6b2df 100644
--- a/clang/test/Parser/objcxx0x-lambda-expressions.mm
+++ b/clang/test/Parser/objcxx0x-lambda-expressions.mm
@@ -11,15 +11,15 @@ class C {
[]; // expected-error {{expected body of lambda expression}}
[=,foo+] {}; // expected-error {{expected ',' or ']' in lambda capture list}}
[&this] {}; // expected-error {{address expression must be an lvalue}}
- [] {};
- [=] (int i) {};
- [&] (int) mutable -> void {};
+ [] {}; // 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}}
- [=,&foo] () {};
- [this] () {};
+ [foo,bar] () { return 3; }; // expected-error {{void function 'f' should not return a value}} 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}}
}
};
diff --git a/clang/test/SemaCXX/cxx98-compat.cpp b/clang/test/SemaCXX/cxx98-compat.cpp
index 051176bf9c3..56e64d23a6e 100644
--- a/clang/test/SemaCXX/cxx98-compat.cpp
+++ b/clang/test/SemaCXX/cxx98-compat.cpp
@@ -34,7 +34,8 @@ namespace TemplateParsing {
}
void Lambda() {
- []{}; // expected-warning {{lambda expressions are incompatible with C++98}}
+ // FIXME: Enable when lambdas are minimally working.
+ //[]{}; // FIXME-warning {{lambda expressions are incompatible with C++98}}
}
int InitList() {
OpenPOWER on IntegriCloud