diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-14 21:20:44 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-14 21:20:44 +0000 |
commit | 621003e7b956906f25b4d9e7c55fa051a54e0f0b (patch) | |
tree | fd6fa3d4aca6e97dbaa5d9966e131e11446d1237 | |
parent | 1bfe068e71c525b8cb2c98724d5c93e213d2cf9a (diff) | |
download | bcm5719-llvm-621003e7b956906f25b4d9e7c55fa051a54e0f0b.tar.gz bcm5719-llvm-621003e7b956906f25b4d9e7c55fa051a54e0f0b.zip |
Check the return type of lambda expressions.
llvm-svn: 150503
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 83 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 17 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp | 8 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm | 8 |
4 files changed, 74 insertions, 42 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ba7e63ab803..f76dcc2bad7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3999,44 +3999,51 @@ 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_capture_more_than_once : Error< - "%0 can appear only once in a capture list">; -def err_reference_capture_with_reference_default : Error< - "'&' cannot precede a capture when the capture default is '&'">; -def err_this_capture_with_copy_default : Error< - "'this' cannot be explicitly captured when the capture default is '='">; -def err_copy_capture_with_copy_default : Error< - "'&' must precede a capture when the capture default is '='">; -def err_capture_does_not_name_variable : Error< - "%0 in capture list does not name a variable">; -def err_capture_non_automatic_variable : Error< - "%0 cannot be captured because it does not have automatic storage duration">; -def err_this_capture : Error< - "'this' cannot be %select{implicitly |}0captured in this context">; -def err_lambda_capture_block : Error< - "__block variable %0 cannot be captured in a lambda expression">; -def err_lambda_capture_anonymous_var : Error< - "unnamed variable cannot be implicitly captured in a lambda expression">; -def err_lambda_capture_vm_type : Error< - "variable %0 with variably modified type cannot be captured in " - "a lambda expression">; -def err_lambda_impcap : Error< - "variable %0 cannot be implicitly captured in a lambda with no " - "capture-default specified">; -def note_lambda_decl : Note<"lambda expression begins here">; -def err_lambda_unevaluated_operand : Error< - "lambda expression in an unevaluated operand">; -def ext_lambda_implies_void_return : ExtWarn< - "C++11 requires lambda with omitted result type to consist of a single " - "return statement">, - InGroup<DiagGroup<"lambda-return">>; -def err_lambda_return_init_list : Error< - "cannot deduce lambda return type from initializer list">; -def err_lambda_capture_default_arg : Error< - "lambda expression in default argument cannot capture any entity">; -def err_lambda_unexpanded_pack : Error< - "unexpanded function parameter pack capture is unsupported">; - +let CategoryName = "Lambda Issue" in { + def err_capture_more_than_once : Error< + "%0 can appear only once in a capture list">; + def err_reference_capture_with_reference_default : Error< + "'&' cannot precede a capture when the capture default is '&'">; + def err_this_capture_with_copy_default : Error< + "'this' cannot be explicitly captured when the capture default is '='">; + def err_copy_capture_with_copy_default : Error< + "'&' must precede a capture when the capture default is '='">; + def err_capture_does_not_name_variable : Error< + "%0 in capture list does not name a variable">; + def err_capture_non_automatic_variable : Error< + "%0 cannot be captured because it does not have automatic storage " + "duration">; + def err_this_capture : Error< + "'this' cannot be %select{implicitly |}0captured in this context">; + def err_lambda_capture_block : Error< + "__block variable %0 cannot be captured in a lambda expression">; + def err_lambda_capture_anonymous_var : Error< + "unnamed variable cannot be implicitly captured in a lambda expression">; + def err_lambda_capture_vm_type : Error< + "variable %0 with variably modified type cannot be captured in " + "a lambda expression">; + def err_lambda_impcap : Error< + "variable %0 cannot be implicitly captured in a lambda with no " + "capture-default specified">; + def note_lambda_decl : Note<"lambda expression begins here">; + def err_lambda_unevaluated_operand : Error< + "lambda expression in an unevaluated operand">; + def ext_lambda_implies_void_return : ExtWarn< + "C++11 requires lambda with omitted result type to consist of a single " + "return statement">, + InGroup<DiagGroup<"lambda-return">>; + def err_lambda_return_init_list : Error< + "cannot deduce lambda return type from initializer list">; + def err_lambda_capture_default_arg : Error< + "lambda expression in default argument cannot capture any entity">; + def err_lambda_unexpanded_pack : Error< + "unexpanded function parameter pack capture is unsupported">; + def err_lambda_incomplete_result : Error< + "incomplete result type %0 in lambda expression">; + def err_lambda_objc_object_result : Error< + "non-pointer Objective-C class type %0 in lambda expression result">; +} + def err_operator_arrow_circular : Error< "circular pointer delegation detected">; def err_pseudo_dtor_base_not_scalar : Error< diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index c75c3c5b7d7..8b8a083a066 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -87,6 +87,17 @@ LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator, if (ExplicitResultType) { LSI->ReturnType = CallOperator->getResultType(); + + if (!LSI->ReturnType->isDependentType() && + !LSI->ReturnType->isVoidType()) { + if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType, + diag::err_lambda_incomplete_result)) { + // Do nothing. + } else if (LSI->ReturnType->isObjCObjectOrInterfaceType()) { + Diag(CallOperator->getLocStart(), diag::err_lambda_objc_object_result) + << LSI->ReturnType; + } + } } else { LSI->HasImplicitReturnType = true; } @@ -161,7 +172,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, CheckExtraCXXDefaultArguments(ParamInfo); MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); - // FIXME: Can these asserts actually fail? assert(MethodTyInfo && "no type from lambda-declarator"); EndLoc = ParamInfo.getSourceRange().getEnd(); @@ -266,7 +276,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // for unqualified name lookup (3.4.1); each such lookup shall find a // variable with automatic storage duration declared in the reaching // scope of the local lambda expression. - // FIXME: Check reaching scope. + // + // Note that the 'reaching scope' check happens in TryCaptureVar. VarDecl *Var = R.getAsSingle<VarDecl>(); if (!Var) { Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id; @@ -321,8 +332,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, addLambdaParameters(Method, CurScope, Proto.getParams()); } - // FIXME: Check return type is complete, !isObjCObjectType - // Enter a new evaluation context to insulate the lambda from any // cleanups from the enclosing full-expression. PushExpressionEvaluationContext(PotentiallyEvaluated); diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp index cff0c099505..586825f0531 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp @@ -41,3 +41,11 @@ X infer_X_return_type_fail(X x) { return x; // expected-error{{return type 'const X' must match previous return type 'X' when block literal has unspecified explicit return type}} }(5); } + +struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}} +void test_result_type(int N) { + auto l1 = [] () -> Incomplete { }; // expected-error{{incomplete result type 'Incomplete' in lambda expression}} + + typedef int vla[N]; + auto l2 = [] () -> vla { }; // expected-error{{function cannot return array type 'vla' (aka 'int [N]')}} +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm new file mode 100644 index 00000000000..0126e23a74a --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +@interface A +@end + +void test_result_type() { + auto l1 = [] () -> A { }; // expected-error{{non-pointer Objective-C class type 'A' in lambda expression result}} +} |