aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-14 21:20:44 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-14 21:20:44 +0000
commit53393f23d8b767f976427a6d45b310bf37dd91c4 (patch)
tree2ebf1f5c8b333d93257a55f54b5a7ce11e0c743a
parent1d0c9a8d0573d1f670f484cc17aa94f06be971a5 (diff)
Check the return type of lambda expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150503 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td83
-rw-r--r--lib/Sema/SemaLambda.cpp17
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp8
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm8
4 files changed, 74 insertions, 42 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index ba7e63ab80..f76dcc2bad 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/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/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index c75c3c5b7d..8b8a083a06 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/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/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
index cff0c09950..586825f053 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
+++ b/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/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm
new file mode 100644
index 0000000000..0126e23a74
--- /dev/null
+++ b/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}}
+}