More lambda work. Fixes a minor bug Richard pointed out, makes lookup for lambda parameters work correctly, recording more information into the AST.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147650 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index caa4c1a..1edeff5 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -180,9 +180,15 @@
/// \brief The field associated with the captured 'this' pointer.
FieldDecl *ThisCapture;
+ /// \brief - Whether the return type of the lambda is implicit
+ bool HasImplicitReturnType;
+
+ /// ReturnType - The return type of the lambda, or null if unknown.
+ QualType ReturnType;
+
LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda)
: FunctionScopeInfo(Diag), Lambda(Lambda),
- NumExplicitCaptures(0), ThisCapture(0)
+ NumExplicitCaptures(0), ThisCapture(0) , HasImplicitReturnType(false)
{
Kind = SK_Lambda;
}
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 7bf2de4..6d20480 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -164,6 +164,7 @@
class BlockScopeInfo;
class DelayedDiagnostic;
class FunctionScopeInfo;
+ class LambdaScopeInfo;
class TemplateDeductionInfo;
}
@@ -780,6 +781,9 @@
/// \brief Retrieve the current block, if any.
sema::BlockScopeInfo *getCurBlock();
+ /// \brief Retrieve the current lambda expression, if any.
+ sema::LambdaScopeInfo *getCurLambda();
+
/// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls
SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index e54858f..cad0a4a 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -792,6 +792,12 @@
Attr, DeclEndLoc);
}
+ // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
+ // it.
+ ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
+ Scope::BreakScope | Scope::ContinueScope |
+ Scope::DeclScope);
+
Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());
// Parse compound-statement.
@@ -801,11 +807,6 @@
return ExprError();
}
- // 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();
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 6a77d8c..4ab960d 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -869,6 +869,13 @@
return dyn_cast<BlockScopeInfo>(FunctionScopes.back());
}
+LambdaScopeInfo *Sema::getCurLambda() {
+ if (FunctionScopes.empty())
+ return 0;
+
+ return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
+}
+
// Pin this vtable to this file.
ExternalSemaSource::~ExternalSemaSource() {}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index fd47dc7..0b1dcbd 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -4782,7 +4782,7 @@
Declarator &ParamInfo,
Scope *CurScope) {
DeclContext *DC = CurContext;
- while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isNamespace()))
+ while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
// Start constructing the lambda class.
@@ -4795,8 +4795,26 @@
// Build the call operator; we don't really have all the relevant information
// at this point, but we need something to attach child declarations to.
+ QualType MethodTy;
TypeSourceInfo *MethodTyInfo;
- MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
+ if (ParamInfo.getNumTypeObjects() == 0) {
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.TypeQuals |= DeclSpec::TQ_const;
+ MethodTy = Context.getFunctionType(Context.DependentTy,
+ /*Args=*/0, /*NumArgs=*/0, EPI);
+ MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
+ } else {
+ assert(ParamInfo.isFunctionDeclarator() &&
+ "lambda-declarator is a function");
+ DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
+ if (!FTI.hasMutableQualifier())
+ FTI.TypeQuals |= DeclSpec::TQ_const;
+ MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
+ // FIXME: Can these asserts actually fail?
+ assert(MethodTyInfo && "no type from lambda-declarator");
+ MethodTy = MethodTyInfo->getType();
+ assert(!MethodTy.isNull() && "no type from lambda declarator");
+ }
DeclarationName MethodName
= Context.DeclarationNames.getCXXOperatorName(OO_Call);
@@ -4806,7 +4824,7 @@
ParamInfo.getSourceRange().getEnd(),
DeclarationNameInfo(MethodName,
/*NameLoc=*/SourceLocation()),
- MethodTyInfo->getType(),
+ MethodTy,
MethodTyInfo,
/*isStatic=*/false,
SC_None,
@@ -4817,21 +4835,8 @@
Class->addDecl(Method);
Method->setLexicalDeclContext(DC); // FIXME: Is this really correct?
- // Set the parameters on the decl, if specified.
- if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
- FunctionProtoTypeLoc Proto =
- cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
- Method->setParams(Proto.getParams());
- CheckParmsForFunctionDef(Method->param_begin(),
- Method->param_end(),
- /*CheckParameterNames=*/false);
- }
-
ProcessDeclAttributes(CurScope, Method, ParamInfo);
- // FIXME: There's a bunch of missing checking etc;
- // see ActOnBlockArguments
-
// Introduce the lambda scope.
PushLambdaScope(Class);
@@ -4840,6 +4845,41 @@
PushExpressionEvaluationContext(PotentiallyEvaluated);
PushDeclContext(CurScope, Method);
+
+ LambdaScopeInfo *LSI = getCurLambda();
+
+ // Set the parameters on the decl, if specified.
+ if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
+ FunctionProtoTypeLoc Proto =
+ cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
+ Method->setParams(Proto.getParams());
+ CheckParmsForFunctionDef(Method->param_begin(),
+ Method->param_end(),
+ /*CheckParameterNames=*/false);
+
+ // Introduce our parameters into the function scope
+ for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) {
+ ParmVarDecl *Param = Method->getParamDecl(p);
+ Param->setOwningFunction(Method);
+
+ // If this has an identifier, add it to the scope stack.
+ if (Param->getIdentifier()) {
+ CheckShadow(CurScope, Param);
+
+ PushOnScopeChains(Param, CurScope);
+ }
+ }
+ }
+
+ const FunctionType *Fn = MethodTy->getAs<FunctionType>();
+ QualType RetTy = Fn->getResultType();
+ if (RetTy != Context.DependentTy) {
+ LSI->ReturnType = RetTy;
+ LSI->HasImplicitReturnType = true;
+ }
+
+ // FIXME: Check return type is complete, !isObjCObjectType
+
}
void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index a3b6768..3bdb3b6 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -2378,7 +2378,8 @@
// top-level template type arguments.
bool FreeFunction;
if (!D.getCXXScopeSpec().isSet()) {
- FreeFunction = (D.getContext() != Declarator::MemberContext ||
+ FreeFunction = ((D.getContext() != Declarator::MemberContext &&
+ D.getContext() != Declarator::LambdaExprContext) ||
D.getDeclSpec().isFriendSpecified());
} else {
DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec());