[cxx1z-constexpr-lambda] Make a lambda's closure type eligible as a literal-type in C++1z

Additionally, for pre-C++1z, instead of forbidding a lambda's closure type from being a literal type through circumlocutorily setting HasNonLiteralTypeFieldsOrBases falsely to true -- handle lambda's more directly in CXXRecordDecl::isLiteral().

One additional small step towards implementing constexpr-lambdas.

Thanks to Richard Smith for his review! 
https://reviews.llvm.org/D22662

llvm-svn: 276514
This commit is contained in:
Faisal Vali 2016-07-23 04:05:19 +00:00
parent a653927e8b
commit c6b9be29f2
2 changed files with 24 additions and 9 deletions

View File

@ -535,11 +535,10 @@ class CXXRecordDecl : public RecordDecl {
MethodTyInfo(Info) {
IsLambda = true;
// C++11 [expr.prim.lambda]p3:
// This class type is neither an aggregate nor a literal type.
// C++1z [expr.prim.lambda]p4:
// This class type is not an aggregate type.
Aggregate = false;
PlainOldData = false;
HasNonLiteralTypeFieldsOrBases = true;
}
/// \brief Whether this lambda is known to be dependent, even if its
@ -1338,11 +1337,15 @@ public:
///
/// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
/// treating types with trivial default constructors as literal types.
///
/// Only in C++1z and beyond, are lambdas literal types.
bool isLiteral() const {
return hasTrivialDestructor() &&
(isAggregate() || hasConstexprNonCopyMoveConstructor() ||
hasTrivialDefaultConstructor()) &&
!hasNonLiteralTypeFieldsOrBases();
(!isLambda() || getASTContext().getLangOpts().CPlusPlus1z) &&
!hasNonLiteralTypeFieldsOrBases() &&
(isAggregate() || isLambda() ||
hasConstexprNonCopyMoveConstructor() ||
hasTrivialDefaultConstructor());
}
/// \brief If this record is an instantiation of a member class,

View File

@ -1,8 +1,8 @@
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks %s
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions %s
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s
// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -fblocks %s -DCPP14_AND_EARLIER
#ifndef CPP14_AND_EARLIER
namespace test_constexpr_checking {
namespace ns1 {
@ -33,4 +33,16 @@ namespace ns3 {
L(3); //expected-note{{non-constexpr function}}
}
} // end ns test_constexpr_call
} // end ns test_constexpr_call
#endif
namespace test_lambda_is_literal {
#ifdef CPP14_AND_EARLIER
//expected-error@+4{{not a literal type}}
//expected-note@+2{{not an aggregate and has no constexpr constructors}}
#endif
auto L = [] { };
constexpr int foo(decltype(L) l) { return 0; }
}