diff options
author | Faisal Vali <faisalv@yahoo.com> | 2013-08-22 01:49:11 +0000 |
---|---|---|
committer | Faisal Vali <faisalv@yahoo.com> | 2013-08-22 01:49:11 +0000 |
commit | fd5277c0635f74bbdbb2daa3bb95e08f39db7d63 (patch) | |
tree | 776347516605949ffff1243cb3f85194200e9452 /clang/lib/Sema/TreeTransform.h | |
parent | da68efdb689ee5b54bf3836add187b62b584de9a (diff) | |
download | bcm5719-llvm-fd5277c0635f74bbdbb2daa3bb95e08f39db7d63.tar.gz bcm5719-llvm-fd5277c0635f74bbdbb2daa3bb95e08f39db7d63.zip |
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- nested lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
As an example of what compiles:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Augment AutoType's constructor (similar to how variadic
template-type-parameters ala TemplateTypeParmDecl are implemented) to
accept an IsParameterPack to encode a generic lambda parameter pack.
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that Sema::ActOnLambdaAutoParameter may use it to create the
appropriate list of corresponding TemplateTypeParmDecl for each
auto parameter identified within the generic lambda (also stored
within the current LambdaScopeInfo). Additionally,
a TemplateParameterList data-member was added to hold the invented
TemplateParameterList AST node which will be much more useful
once we teach TreeTransform how to transform generic lambdas.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- Teach Sema::ActOnStartOfLambdaDefinition to set the
return type of a lambda without a trailing return type
to 'auto' in C++1y mode, and teach the return type
deduction machinery in SemaStmt.cpp to process either
C++11 and C++14 lambda's correctly depending on the flag.
- various tests were added - but much more will be needed.
A greatful thanks to all reviewers including Eli Friedman,
James Dennett and the ever illuminating Richard Smith. And
yet I am certain that I have allowed unidentified bugs to creep in;
bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 188977
Diffstat (limited to 'clang/lib/Sema/TreeTransform.h')
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 9e5738394ea..6e69bdc5128 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -782,7 +782,10 @@ public: // Note, IsDependent is always false here: we implicitly convert an 'auto' // which has been deduced to a dependent type into an undeduced 'auto', so // that we'll retry deduction after the transformation. - return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto); + // FIXME: Can we assume the same about IsParameterPack? + return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto, + /*IsDependent*/ false, + /*IsParameterPack*/ false); } /// \brief Build a new template specialization type. @@ -3494,7 +3497,9 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, Qs.removeObjCLifetime(); Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(), Qs); - Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto()); + Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(), + AutoTy->isDependentType(), + AutoTy->containsUnexpandedParameterPack()); TLB.TypeWasModifiedSafely(Result); } else { // Otherwise, complain about the addition of a qualifier to an @@ -8193,6 +8198,14 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( template<typename Derived> ExprResult TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { + + // FIXME: Implement nested generic lambda transformations. + if (E->isGenericLambda()) { + getSema().Diag(E->getIntroducerRange().getBegin(), + diag::err_glambda_not_fully_implemented) + << " nested lambdas not implemented yet"; + return ExprError(); + } // Transform the type of the lambda parameters and start the definition of // the lambda itself. TypeSourceInfo *MethodTy @@ -8215,7 +8228,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { E->getCallOperator()->param_size(), 0, ParamTypes, &Params)) return ExprError(); - + getSema().PushLambdaScope(); + LambdaScopeInfo *LSI = getSema().getCurLambda(); + // TODO: Fix for nested lambdas + LSI->GLTemplateParameterList = 0; // Build the call operator. CXXMethodDecl *CallOperator = getSema().startLambdaDefinition(Class, E->getIntroducerRange(), @@ -8250,9 +8266,9 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, // Introduce the context of the call operator. Sema::ContextRAII SavedContext(getSema(), CallOperator); + LambdaScopeInfo *const LSI = getSema().getCurLambda(); // Enter the scope of the lambda. - sema::LambdaScopeInfo *LSI - = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(), + getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(), E->getCaptureDefault(), E->getCaptureDefaultLoc(), E->hasExplicitParameters(), |