From 36d129435ee8ade44201cddfc2249525d58221ee Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 4 Jan 2012 04:41:38 +0000 Subject: [PATCH] Add an explicit LambdaExprContext to Declarator, to parallel BlockLiteralContext. Use it to ensure semantic analysis of types isn't confused by the lack of a type specifier. llvm-svn: 147522 --- clang/include/clang/Sema/DeclSpec.h | 4 ++++ clang/lib/Parse/ParseExprCXX.cpp | 2 +- clang/lib/Sema/SemaExprCXX.cpp | 6 ++++-- clang/lib/Sema/SemaType.cpp | 13 +++++++++++-- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 7dc8f29455c3..44823c8f93e4 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1416,6 +1416,7 @@ public: CXXCatchContext, // C++ catch exception-declaration ObjCCatchContext, // Objective-C catch exception-declaration BlockLiteralContext, // Block literal declarator. + LambdaExprContext, // Lambda-expression declarator. TemplateTypeArgContext, // Template type argument. AliasDeclContext, // C++0x alias-declaration. AliasTemplateContext // C++0x alias-declaration template. @@ -1582,6 +1583,7 @@ public: case CXXCatchContext: case ObjCCatchContext: case BlockLiteralContext: + case LambdaExprContext: case TemplateTypeArgContext: return true; } @@ -1612,6 +1614,7 @@ public: case ObjCParameterContext: case ObjCResultContext: case BlockLiteralContext: + case LambdaExprContext: case TemplateTypeArgContext: return false; } @@ -1643,6 +1646,7 @@ public: case AliasDeclContext: case AliasTemplateContext: case BlockLiteralContext: + case LambdaExprContext: case TemplateTypeArgContext: return false; } diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 4776ab93c5db..96f8709ba56c 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -715,7 +715,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // Parse lambda-declarator[opt]. DeclSpec DS(AttrFactory); - Declarator D(DS, Declarator::BlockLiteralContext); + Declarator D(DS, Declarator::LambdaExprContext); if (Tok.is(tok::l_paren)) { ParseScope PrototypeScope(this, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 67e1c2fb099e..e53e5cda6216 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4780,7 +4780,6 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc, void Sema::ActOnLambdaStart(SourceLocation StartLoc, Scope *CurScope) { // FIXME: Add lambda-scope - // FIXME: Build lambda-decl // FIXME: PushDeclContext // Enter a new evaluation context to insulate the block from any @@ -4789,7 +4788,10 @@ void Sema::ActOnLambdaStart(SourceLocation StartLoc, Scope *CurScope) { } void Sema::ActOnLambdaArguments(Declarator &ParamInfo, Scope *CurScope) { - // FIXME: Implement + TypeSourceInfo *MethodTyInfo; + MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); + + // FIXME: Build CXXMethodDecl } void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index f4b82fc1cb48..a3b67689611e 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -640,7 +640,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // If this is a missing declspec in a block literal return context, then it // is inferred from the return statements inside the block. - if (isOmittedBlockReturnType(declarator)) { + // The declspec is always missing in a lambda expr context; it is either + // specified with a trailing return type or inferred. + if (declarator.getContext() == Declarator::LambdaExprContext || + isOmittedBlockReturnType(declarator)) { Result = Context.DependentTy; break; } @@ -1785,6 +1788,9 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::KNRTypeListContext: llvm_unreachable("K&R type lists aren't allowed in C++"); break; + case Declarator::LambdaExprContext: + llvm_unreachable("Can't specify a type specifier in lambda grammar"); + break; case Declarator::ObjCParameterContext: case Declarator::ObjCResultContext: case Declarator::PrototypeContext: @@ -1875,6 +1881,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::BlockContext: case Declarator::ForContext: case Declarator::BlockLiteralContext: + case Declarator::LambdaExprContext: // C++0x [dcl.type]p3: // A type-specifier-seq shall not define a class or enumeration unless // it appears in the type-id of an alias-declaration (7.1.3) that is not @@ -2058,7 +2065,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, diag::err_trailing_return_in_parens) << T << D.getDeclSpec().getSourceRange(); D.setInvalidType(true); - } else if (T.hasQualifiers() || !isa(T)) { + } else if (D.getContext() != Declarator::LambdaExprContext && + (T.hasQualifiers() || !isa(T))) { S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_trailing_return_without_auto) << T << D.getDeclSpec().getSourceRange(); @@ -2578,6 +2586,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case Declarator::CXXCatchContext: case Declarator::ObjCCatchContext: case Declarator::BlockLiteralContext: + case Declarator::LambdaExprContext: case Declarator::TemplateTypeArgContext: // FIXME: We may want to allow parameter packs in block-literal contexts // in the future.