From 152b4e4652baedfceba1cd8115515629225e713f Mon Sep 17 00:00:00 2001 From: Manuel Klimek Date: Thu, 22 Aug 2013 12:12:24 +0000 Subject: [PATCH] Revert "Implement a rudimentary form of generic lambdas." This reverts commit 606f5d7a99b11957e057e4cd1f55f931f66a42c7. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189004 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 2 +- include/clang/AST/DeclCXX.h | 40 +---- include/clang/AST/ExprCXX.h | 7 - include/clang/AST/Type.h | 12 +- include/clang/Basic/DiagnosticSemaKinds.td | 4 - include/clang/Sema/DeclSpec.h | 10 +- include/clang/Sema/ScopeInfo.h | 33 +--- include/clang/Sema/Sema.h | 41 ++--- include/clang/Sema/SemaLambda.h | 44 ----- lib/AST/ASTContext.cpp | 17 +- lib/AST/ASTImporter.cpp | 4 +- lib/AST/DeclCXX.cpp | 45 +---- lib/AST/ExprCXX.cpp | 14 +- lib/AST/Type.cpp | 4 - lib/CodeGen/CodeGenFunction.cpp | 2 +- lib/Parse/ParseDecl.cpp | 35 ++-- lib/Parse/ParseExprCXX.cpp | 17 +- lib/Parse/Parser.cpp | 1 + lib/Sema/Sema.cpp | 25 +-- lib/Sema/SemaDecl.cpp | 45 +---- lib/Sema/SemaDeclCXX.cpp | 15 +- lib/Sema/SemaLambda.cpp | 159 ++++-------------- lib/Sema/SemaOverload.cpp | 4 - lib/Sema/SemaStmt.cpp | 66 +++----- lib/Sema/SemaTemplateDeduction.cpp | 15 +- lib/Sema/SemaType.cpp | 43 +---- lib/Sema/TreeTransform.h | 26 +-- lib/Serialization/ASTReader.cpp | 4 +- lib/Serialization/ASTReaderDecl.cpp | 1 - lib/Serialization/ASTWriter.cpp | 2 - .../dcl.spec.auto/p3-generic-lambda-1y.cpp | 75 --------- .../generic-lambda-unimplemented-1y.cpp | 50 ------ .../expr.prim.lambda/p2-generic-lambda-1y.cpp | 23 --- .../expr/expr.prim/expr.prim.lambda/p4-1y.cpp | 57 ------- .../expr/expr.prim/expr.prim.lambda/p4.cpp | 4 +- .../expr.prim.lambda/p5-generic-lambda-1y.cpp | 135 --------------- 36 files changed, 150 insertions(+), 931 deletions(-) delete mode 100644 include/clang/Sema/SemaLambda.h delete mode 100644 test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp delete mode 100644 test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp delete mode 100644 test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp delete mode 100644 test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 2244d081c4..0e0a62be97 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1115,7 +1115,7 @@ public: /// \brief C++11 deduced auto type. QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto, - bool IsDependent, bool IsParameterPack) const; + bool IsDependent = false) const; /// \brief C++11 deduction pattern for 'auto' type. QualType getAutoDeductType() const; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 98990204ae..f96032c61b 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -516,8 +516,8 @@ class CXXRecordDecl : public RecordDecl { LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent) : DefinitionData(D), Dependent(Dependent), NumCaptures(0), - NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), - Captures(0), MethodTyInfo(Info), TheLambdaExpr(0) + NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0), + MethodTyInfo(Info) { IsLambda = true; } @@ -529,7 +529,7 @@ class CXXRecordDecl : public RecordDecl { /// within the default argument of a function template, because the /// lambda will have been created with the enclosing context as its /// declaration context, rather than function. This is an unfortunate - /// artifact of having to parse the default arguments before. + /// artifact of having to parse the default arguments before unsigned Dependent : 1; /// \brief The number of captures in this lambda. @@ -554,10 +554,6 @@ class CXXRecordDecl : public RecordDecl { /// \brief The type of the call method. TypeSourceInfo *MethodTyInfo; - - /// \brief The AST node of the lambda expression. - LambdaExpr *TheLambdaExpr; - }; struct DefinitionData &data() { @@ -993,36 +989,6 @@ public: /// \brief Determine whether this class describes a lambda function object. bool isLambda() const { return hasDefinition() && data().IsLambda; } - /// \brief Determine whether this class describes a generic - /// lambda function object (i.e. function call operator is - /// a template). - bool isGenericLambda() const; - - /// \brief Retrieve the lambda call operator of the closure type - /// if this is a closure type. - CXXMethodDecl* getLambdaCallOperator() const; - - /// \brief Retrieve the lambda static invoker, the address of which - /// is returned by the conversion operator, and the body of which - /// is forwarded to the lambda call operator. - CXXMethodDecl* getLambdaStaticInvoker() const; - - /// \brief Retrieve the generic lambda's template parameter list. - /// Returns null if the class does not represent a lambda or a generic - /// lambda. - TemplateParameterList* getGenericLambdaTemplateParameterList() const; - - /// \brief Assign the member call operator of the lambda. - void setLambdaExpr(LambdaExpr *E) { - getLambdaData().TheLambdaExpr = E; - } - - /// \brief Retrieve the parent lambda expression. - LambdaExpr* getLambdaExpr() const { - return isLambda() ? getLambdaData().TheLambdaExpr : 0; - } - - /// \brief For a closure type, retrieve the mapping from captured /// variables and \c this to the non-static data members that store the /// values or references of the captures. diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 39112b3642..1dfa3b5244 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1604,13 +1604,6 @@ public: /// lambda expression. CXXMethodDecl *getCallOperator() const; - /// \brief If this is a generic lambda expression, retrieve the template - /// parameter list associated with it, or else return null. - TemplateParameterList *getTemplateParameterList() const; - - /// \brief Whether this is a generic lambda. - bool isGenericLambda() const { return !!getTemplateParameterList(); } - /// \brief Retrieve the body of the lambda. CompoundStmt *getBody() const; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 246d3e14a4..6e2246ba37 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -3614,11 +3614,10 @@ public: /// is no deduced type and an auto type is canonical. In the latter case, it is /// also a dependent type. class AutoType : public Type, public llvm::FoldingSetNode { - AutoType(QualType DeducedType, bool IsDecltypeAuto, - bool IsDependent, bool IsParameterPack) + AutoType(QualType DeducedType, bool IsDecltypeAuto, bool IsDependent) : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType, /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent, - /*VariablyModified=*/false, /*ContainsParameterPack=*/IsParameterPack) { + /*VariablyModified=*/false, /*ContainsParameterPack=*/false) { assert((DeducedType.isNull() || !IsDependent) && "auto deduced to dependent type"); AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto; @@ -3642,17 +3641,14 @@ public: } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getDeducedType(), isDecltypeAuto(), - isDependentType(), containsUnexpandedParameterPack()); + Profile(ID, getDeducedType(), isDecltypeAuto(), isDependentType()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced, - bool IsDecltypeAuto, bool IsDependent, - bool IsParameterPack) { + bool IsDecltypeAuto, bool IsDependent) { ID.AddPointer(Deduced.getAsOpaquePtr()); ID.AddBoolean(IsDecltypeAuto); ID.AddBoolean(IsDependent); - ID.AddBoolean(IsParameterPack); } static bool classof(const Type *T) { diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7a0431bc40..dd0c540cbb 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5050,10 +5050,6 @@ let CategoryName = "Lambda Issue" in { "cannot deduce type for lambda capture %0 from initializer list">; } -// C++1y Generic Lambdas -def err_glambda_not_fully_implemented : Error< - "unimplemented generic lambda feature: %0">; - def err_return_in_captured_stmt : Error< "cannot return from %0">; def err_capture_block_variable : Error< diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index dfb79325f2..5924a15b7e 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1502,7 +1502,6 @@ public: ObjCCatchContext, // Objective-C catch exception-declaration BlockLiteralContext, // Block literal declarator. LambdaExprContext, // Lambda-expression declarator. - LambdaExprParameterContext, // Lambda-expression parameter declarator. ConversionIdContext, // C++ conversion-type-id. TrailingReturnContext, // C++11 trailing-type-specifier. TemplateTypeArgContext, // Template type argument. @@ -1578,6 +1577,7 @@ public: ~Declarator() { clear(); } + /// getDeclSpec - Return the declaration-specifier that this declarator was /// declared with. const DeclSpec &getDeclSpec() const { return DS; } @@ -1606,8 +1606,7 @@ public: bool isPrototypeContext() const { return (Context == PrototypeContext || Context == ObjCParameterContext || - Context == ObjCResultContext || - Context == LambdaExprParameterContext); + Context == ObjCResultContext); } /// \brief Get the source range that spans this declarator. @@ -1671,7 +1670,6 @@ public: case AliasDeclContext: case AliasTemplateContext: case PrototypeContext: - case LambdaExprParameterContext: case ObjCParameterContext: case ObjCResultContext: case TemplateParamContext: @@ -1700,7 +1698,6 @@ public: case ForContext: case ConditionContext: case PrototypeContext: - case LambdaExprParameterContext: case TemplateParamContext: case CXXCatchContext: case ObjCCatchContext: @@ -1733,7 +1730,6 @@ public: case ForContext: case ConditionContext: case PrototypeContext: - case LambdaExprParameterContext: case TemplateParamContext: case CXXCatchContext: case ObjCCatchContext: @@ -1786,7 +1782,6 @@ public: case KNRTypeListContext: case MemberContext: case PrototypeContext: - case LambdaExprParameterContext: case ObjCParameterContext: case ObjCResultContext: case TemplateParamContext: @@ -1973,7 +1968,6 @@ public: case AliasDeclContext: case AliasTemplateContext: case PrototypeContext: - case LambdaExprParameterContext: case ObjCParameterContext: case ObjCResultContext: case TemplateParamContext: diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index d3f866bb1e..86725e1cb1 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -35,8 +35,6 @@ class LabelDecl; class ReturnStmt; class Scope; class SwitchStmt; -class TemplateTypeParmDecl; -class TemplateParameterList; class VarDecl; class DeclRefExpr; class ObjCIvarRefExpr; @@ -615,27 +613,12 @@ public: /// \brief Offsets into the ArrayIndexVars array at which each capture starts /// its list of array index variables. SmallVector ArrayIndexStarts; - - /// \brief If this is a generic lambda, use this as the depth of - /// each 'auto' parameter, during initial AST construction. - unsigned AutoTemplateParameterDepth; - - // If this is a generic lambda, store the list of the auto - // parameters converted into TemplateTypeParmDecls into a vector - // that can be used to construct the generic lambda's template - // parameter list, during initial AST construction. - /// \brief Store the list of the auto parameters for a generic lambda. - SmallVector AutoTemplateParams; - - // If this is a generic lambda, store its template parameter list. - TemplateParameterList *GLTemplateParameterList; - - LambdaScopeInfo(DiagnosticsEngine &Diag) - : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0), - CallOperator(0), NumExplicitCaptures(0), Mutable(false), - ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false), - AutoTemplateParameterDepth(0), - GLTemplateParameterList(0) + + LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda, + CXXMethodDecl *CallOperator) + : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda), + CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false), + ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false) { Kind = SK_Lambda; } @@ -648,10 +631,8 @@ public: } static bool classof(const FunctionScopeInfo *FSI) { - return FSI->Kind == SK_Lambda; + return FSI->Kind == SK_Lambda; } - - }; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 70d4ce493f..749c64d958 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -969,13 +969,7 @@ public: void PushFunctionScope(); void PushBlockScope(Scope *BlockScope, BlockDecl *Block); - void PushLambdaScope(); - - // This is used to inform Sema what the current TemplateParameterDepth - // is during Parsing. Currently it is used to pass on the depth - // when parsing generic lambda 'auto' parameters. - void RecordParsingTemplateParameterDepth(unsigned Depth); - + void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator); void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD, RecordDecl *RD, CapturedRegionKind K); @@ -1002,12 +996,9 @@ public: /// \brief Retrieve the current block, if any. sema::BlockScopeInfo *getCurBlock(); - /// \brief Retrieve the current lambda scope info, if any. + /// \brief Retrieve the current lambda expression, if any. sema::LambdaScopeInfo *getCurLambda(); - /// \brief Retrieve the current generic lambda info, if any. - sema::LambdaScopeInfo *getCurGenericLambda(); - /// \brief Retrieve the current captured region, if any. sema::CapturedRegionScopeInfo *getCurCapturedRegion(); @@ -4410,10 +4401,6 @@ public: /// initializer for the declaration 'Dcl'. void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl); - /// \brief Invoked when an auto parameter is parsed - /// in a lambda's parameter declaration clause. - ParmVarDecl *ActOnLambdaAutoParameter(ParmVarDecl *P); - /// \brief Create a new lambda closure type. CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info, @@ -4426,15 +4413,14 @@ public: SourceLocation EndLoc, ArrayRef Params); - /// \brief Endow the lambda scope info with the relevant properties. - void buildLambdaScope(sema::LambdaScopeInfo *LSI, - CXXMethodDecl *CallOperator, - SourceRange IntroducerRange, - LambdaCaptureDefault CaptureDefault, - SourceLocation CaptureDefaultLoc, - bool ExplicitParams, - bool ExplicitResultType, - bool Mutable); + /// \brief Introduce the scope for a lambda expression. + sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator, + SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + SourceLocation CaptureDefaultLoc, + bool ExplicitParams, + bool ExplicitResultType, + bool Mutable); /// \brief Check and build an init-capture with the specified name and /// initializer. @@ -5819,12 +5805,6 @@ public: sema::TemplateDeductionInfo &Info, bool InOverloadResolution = false); - /// \brief Substitute Replacement for \p auto in \p TypeWithAuto - QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement); - /// \brief Substitute Replacement for auto in TypeWithAuto - TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, - QualType Replacement); - /// \brief Result type of DeduceAutoType. enum DeduceAutoResult { DAR_Succeeded, @@ -5836,6 +5816,7 @@ public: QualType &Result); DeduceAutoResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer, QualType &Result); + QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement); void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init); bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, bool Diagnose = true); diff --git a/include/clang/Sema/SemaLambda.h b/include/clang/Sema/SemaLambda.h deleted file mode 100644 index e01dc35b5e..0000000000 --- a/include/clang/Sema/SemaLambda.h +++ /dev/null @@ -1,44 +0,0 @@ -//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief This file provides some common utility functions for processing -/// Lambdas. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_SEMA_LAMBDA_H -#define LLVM_CLANG_SEMA_LAMBDA_H - -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/Sema/ScopeInfo.h" - -namespace clang { -static inline const char *getLambdaStaticInvokerName() { - return "__invoke"; -} -static inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) { - if (MD) { - CXXRecordDecl *LambdaClass = MD->getParent(); - if (LambdaClass && LambdaClass->isGenericLambda()) { - return LambdaClass->getLambdaCallOperator() - == MD->getTemplateInstantiationPattern(); - } - } - return false; -} - -static inline bool isGenericLambdaCallOperatorSpecialization(Decl *D) { - return isGenericLambdaCallOperatorSpecialization( - dyn_cast(D)); -} -} // clang - -#endif // LLVM_CLANG_SEMA_LAMBDA_H diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b1b52fb1c5..29ddb37525 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3649,24 +3649,20 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType, /// deduced to the given type, or to the canonical undeduced 'auto' type, or the /// canonical deduced-but-dependent 'auto' type. QualType ASTContext::getAutoType(QualType DeducedType, bool IsDecltypeAuto, - bool IsDependent, bool IsParameterPack) const { - if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent && - !IsParameterPack) + bool IsDependent) const { + if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent) return getAutoDeductType(); - assert(!IsParameterPack || DeducedType.isNull() - && "Auto parameter pack: auto ... a should always be undeduced!"); + // Look in the folding set for an existing type. void *InsertPos = 0; llvm::FoldingSetNodeID ID; - AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent, - IsParameterPack); + AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent); if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(AT, 0); AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType, IsDecltypeAuto, - IsDependent, - IsParameterPack); + IsDependent); Types.push_back(AT); if (InsertPos) AutoTypes.InsertNode(AT, InsertPos); @@ -3706,8 +3702,7 @@ QualType ASTContext::getAutoDeductType() const { if (AutoDeductTy.isNull()) AutoDeductTy = QualType( new (*this, TypeAlignment) AutoType(QualType(), /*decltype(auto)*/false, - /*dependent*/false, - /*IsParameterPack*/false), + /*dependent*/false), 0); return AutoDeductTy; } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index f03b66dfd8..922172701f 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1709,9 +1709,7 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) { return QualType(); } - return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(), - /*IsDependent*/false, - T->containsUnexpandedParameterPack()); + return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto()); } QualType ASTNodeImporter::VisitRecordType(const RecordType *T) { diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index b50aa9337f..ccd8220a68 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -20,7 +20,6 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/IdentifierTable.h" -#include "clang/Sema/SemaLambda.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" using namespace clang; @@ -931,40 +930,6 @@ bool CXXRecordDecl::isCLike() const { return isPOD() && data().HasOnlyCMembers; } -bool CXXRecordDecl::isGenericLambda() const { - return isLambda() && - getLambdaCallOperator()->getDescribedFunctionTemplate(); -} - -CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { - if (!isLambda()) return 0; - DeclarationName Name = - getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); - DeclContext::lookup_const_result Calls = lookup(Name); - - assert(!Calls.empty() && "Missing lambda call operator!"); - assert(Calls.size() == 1 && "More than one lambda call operator!"); - - NamedDecl *CallOp = Calls.front(); - if (FunctionTemplateDecl *CallOpTmpl = - dyn_cast(CallOp)) - return cast(CallOpTmpl->getTemplatedDecl()); - - return cast(CallOp); -} - -CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const { - if (!isLambda()) return 0; - DeclarationName Name = - &getASTContext().Idents.get(getLambdaStaticInvokerName()); - DeclContext::lookup_const_result Invoker = lookup(Name); - if (Invoker.empty()) return 0; - assert(Invoker.size() == 1 && "More than one static invoker operator!"); - CXXMethodDecl *Result = cast(Invoker.front()); - return Result; - -} - void CXXRecordDecl::getCaptureFields( llvm::DenseMap &Captures, FieldDecl *&ThisCapture) const { @@ -982,14 +947,6 @@ void CXXRecordDecl::getCaptureFields( } } -TemplateParameterList* - CXXRecordDecl::getGenericLambdaTemplateParameterList() const { - if (!isLambda()) return 0; - CXXMethodDecl *CallOp = getLambdaCallOperator(); - if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate()) - return Tmpl->getTemplateParameters(); - return 0; -} static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { QualType T; @@ -1536,7 +1493,7 @@ bool CXXMethodDecl::hasInlineBody() const { bool CXXMethodDecl::isLambdaStaticInvoker() const { return getParent()->isLambda() && - getParent()->getLambdaStaticInvoker() == this; + getIdentifier() && getIdentifier()->getName() == "__invoke"; } diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 684853492e..b76bc2f284 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -1027,13 +1027,13 @@ CXXRecordDecl *LambdaExpr::getLambdaClass() const { CXXMethodDecl *LambdaExpr::getCallOperator() const { CXXRecordDecl *Record = getLambdaClass(); - return Record->getLambdaCallOperator(); -} - -TemplateParameterList *LambdaExpr::getTemplateParameterList() const { - CXXRecordDecl *Record = getLambdaClass(); - return Record->getGenericLambdaTemplateParameterList(); - + DeclarationName Name + = Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); + DeclContext::lookup_result Calls = Record->lookup(Name); + assert(!Calls.empty() && "Missing lambda call operator!"); + assert(Calls.size() == 1 && "More than one lambda call operator!"); + CXXMethodDecl *Result = cast(Calls.front()); + return Result; } CompoundStmt *LambdaExpr::getBody() const { diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 6b639dba67..ef423eba87 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -589,10 +589,6 @@ namespace { AutoType *VisitAttributedType(const AttributedType *T) { return Visit(T->getModifiedType()); } - AutoType *VisitPackExpansionType(const PackExpansionType *T) { - return Visit(T->getPattern()); - } - }; } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index c271d7c626..da8db172f5 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -700,7 +700,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, EmitLambdaToBlockPointerBody(Args); } else if (isa(FD) && cast(FD)->isLambdaStaticInvoker()) { - // The lambda static invoker function is special, because it forwards or + // The lambda "__invoke" function is special, because it forwards or // clones the body of the function call operator (but is actually static). EmitLambdaStaticInvokeFunction(cast(FD)); } else if (FD->isDefaulted() && isa(FD) && diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4c4ce87482..392535acef 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4670,7 +4670,6 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // as part of the parameter-declaration-clause. if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() && !((D.getContext() == Declarator::PrototypeContext || - D.getContext() == Declarator::LambdaExprParameterContext || D.getContext() == Declarator::BlockLiteralContext) && NextToken().is(tok::r_paren) && !D.hasGroupingParens() && @@ -4989,6 +4988,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, TypeResult TrailingReturnType; Actions.ActOnStartFunctionDeclarator(); + /* LocalEndLoc is the end location for the local FunctionTypeLoc. EndLoc is the end location for the function declarator. They differ for trailing return types. */ @@ -5009,8 +5009,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, EndLoc = RParenLoc; } else { if (Tok.isNot(tok::r_paren)) - ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, - EllipsisLoc); + ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc); else if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); @@ -5241,6 +5240,7 @@ void Parser::ParseParameterDeclarationClause( ParsedAttributes &FirstArgAttrs, SmallVectorImpl &ParamInfo, SourceLocation &EllipsisLoc) { + while (1) { if (Tok.is(tok::ellipsis)) { // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq @@ -5270,21 +5270,16 @@ void Parser::ParseParameterDeclarationClause( ParseDeclarationSpecifiers(DS); - - // Parse the declarator. This is "PrototypeContext" or - // "LambdaExprParameterContext", because we must accept either - // 'declarator' or 'abstract-declarator' here. - Declarator ParmDeclarator(DS, - D.getContext() == Declarator::LambdaExprContext ? - Declarator::LambdaExprParameterContext : - Declarator::PrototypeContext); - ParseDeclarator(ParmDeclarator); + // Parse the declarator. This is "PrototypeContext", because we must + // accept either 'declarator' or 'abstract-declarator' here. + Declarator ParmDecl(DS, Declarator::PrototypeContext); + ParseDeclarator(ParmDecl); // Parse GNU attributes, if present. - MaybeParseGNUAttributes(ParmDeclarator); + MaybeParseGNUAttributes(ParmDecl); // Remember this parsed parameter in ParamInfo. - IdentifierInfo *ParmII = ParmDeclarator.getIdentifier(); + IdentifierInfo *ParmII = ParmDecl.getIdentifier(); // DefArgToks is used when the parsing of default arguments needs // to be delayed. @@ -5292,8 +5287,8 @@ void Parser::ParseParameterDeclarationClause( // If no parameter was specified, verify that *something* was specified, // otherwise we have a missing type and identifier. - if (DS.isEmpty() && ParmDeclarator.getIdentifier() == 0 && - ParmDeclarator.getNumTypeObjects() == 0) { + if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 && + ParmDecl.getNumTypeObjects() == 0) { // Completely missing, emit error. Diag(DSStart, diag::err_missing_param); } else { @@ -5302,8 +5297,8 @@ void Parser::ParseParameterDeclarationClause( // Inform the actions module about the parameter declarator, so it gets // added to the current scope. - Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), - ParmDeclarator); + Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl); + // Parse the default argument, if any. We parse the default // arguments in all dialects; the semantic analysis in // ActOnParamDefaultArgument will reject the default argument in @@ -5364,8 +5359,8 @@ void Parser::ParseParameterDeclarationClause( } ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, - ParmDeclarator.getIdentifierLoc(), - Param, DefArgToks)); + ParmDecl.getIdentifierLoc(), Param, + DefArgToks)); } // If the next token is a comma, consume it and keep reading arguments. diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 1ab70475e5..9ac6d43506 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -20,7 +20,6 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "llvm/Support/ErrorHandling.h" -#include "clang/AST/DeclTemplate.h" using namespace clang; @@ -909,16 +908,12 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc, "lambda expression parsing"); - - // FIXME: Call into Actions to add any init-capture declarations to the // scope while parsing the lambda-declarator and compound-statement. // Parse lambda-declarator[opt]. DeclSpec DS(AttrFactory); Declarator D(DS, Declarator::LambdaExprContext); - TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); - Actions.PushLambdaScope(); if (Tok.is(tok::l_paren)) { ParseScope PrototypeScope(this, @@ -936,17 +931,9 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( SmallVector ParamInfo; SourceLocation EllipsisLoc; - - if (Tok.isNot(tok::r_paren)) { - sema::LambdaScopeInfo *LSI = Actions.getCurLambda(); - if (getLangOpts().CPlusPlus1y) - Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth); + if (Tok.isNot(tok::r_paren)) ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc); - // For a generic lambda, each 'auto' within the parameter declaration - // clause creates a template type parameter, so increment the depth. - if (getLangOpts().CPlusPlus1y && Actions.getCurGenericLambda()) - ++CurTemplateDepthTracker; - } + T.consumeClose(); SourceLocation RParenLoc = T.getCloseLocation(); DeclEndLoc = RParenLoc; diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 6ee97d4936..866572ceab 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1175,6 +1175,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // Ask the actions module to compute the type for this declarator. Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator); + if (Param && // A missing identifier has already been diagnosed. ParmDeclarator.getIdentifier()) { diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index aab0389796..6cc596cec1 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1007,17 +1007,10 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { BlockScope, Block)); } -void Sema::PushLambdaScope() { - FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics())); -} - -void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) { - if (LambdaScopeInfo *const LSI = getCurLambda()) { - LSI->AutoTemplateParameterDepth = Depth; - return; - } - assert(false && - "Remove assertion if intentionally called in a non-lambda context."); +void Sema::PushLambdaScope(CXXRecordDecl *Lambda, + CXXMethodDecl *CallOperator) { + FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda, + CallOperator)); } void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, @@ -1073,16 +1066,6 @@ LambdaScopeInfo *Sema::getCurLambda() { return dyn_cast(FunctionScopes.back()); } -// We have a generic lambda if we parsed auto parameters, or we have -// an associated template parameter list. -LambdaScopeInfo *Sema::getCurGenericLambda() { - if (LambdaScopeInfo *LSI = getCurLambda()) { - return (LSI->AutoTemplateParams.size() || - LSI->GLTemplateParameterList) ? LSI : 0; - } - return 0; -} - void Sema::ActOnComment(SourceRange Comment) { if (!LangOpts.RetainCommentsFromSystemHeaders && diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d5d890456e..80863e35e2 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -35,7 +35,6 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Initialization.h" -#include "clang/Sema/SemaLambda.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -8910,7 +8909,6 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. - // C++03 [dcl.stc]p2 also permits 'auto'. VarDecl::StorageClass StorageClass = SC_None; if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { @@ -9017,14 +9015,6 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (New->hasAttr()) { Diag(New->getLocation(), diag::err_block_on_nonlocal); } - - // Handle 'auto' within a generic lambda. - QualType ParamType = New->getType(); - if (getLangOpts().CPlusPlus1y && ParamType->getContainedAutoType()) { - assert(getCurLambda() && - "'auto' in parameter type only allowed in lambdas!"); - New = ActOnLambdaAutoParameter(New); - } return New; } @@ -9278,38 +9268,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { FD = FunTmpl->getTemplatedDecl(); else FD = cast(D); - // If we are instantiating a generic lambda call operator, push - // a LambdaScopeInfo onto the function stack. But use the information - // that's already been calculated (ActOnLambdaExpr) when analyzing the - // template version, to prime the current LambdaScopeInfo. - if (getLangOpts().CPlusPlus1y - && isGenericLambdaCallOperatorSpecialization(D)) { - CXXMethodDecl *CallOperator = cast(D); - CXXRecordDecl *LambdaClass = CallOperator->getParent(); - LambdaExpr *LE = LambdaClass->getLambdaExpr(); - assert(LE && - "No LambdaExpr of closure class when instantiating a generic lambda!"); - assert(ActiveTemplateInstantiations.size() && - "There should be an active template instantiation on the stack " - "when instantiating a generic lambda!"); - PushLambdaScope(); - LambdaScopeInfo *LSI = getCurLambda(); - LSI->CallOperator = CallOperator; - LSI->Lambda = LambdaClass; - LSI->ReturnType = CallOperator->getResultType(); - - if (LE->getCaptureDefault() == LCD_None) - LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None; - else if (LE->getCaptureDefault() == LCD_ByCopy) - LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval; - else if (LE->getCaptureDefault() == LCD_ByRef) - LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref; - - LSI->IntroducerRange = LE->getIntroducerRange(); - } - else - // Enter a new function scope - PushFunctionScope(); + + // Enter a new function scope + PushFunctionScope(); // See if this is a redefinition. if (!FD->isLateTemplateParsed()) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index bde9c15c99..6ebfb57974 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -32,7 +32,6 @@ #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" -#include "clang/Sema/SemaLambda.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -10016,27 +10015,29 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( SourceLocation CurrentLocation, CXXConversionDecl *Conv) { - CXXRecordDecl *LambdaClass = Conv->getParent(); + CXXRecordDecl *Lambda = Conv->getParent(); // Make sure that the lambda call operator is marked used. - markLambdaCallOperatorUsed(*this, LambdaClass); + markLambdaCallOperatorUsed(*this, Lambda); Conv->setUsed(); SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); - CXXMethodDecl *Invoke = LambdaClass->getLambdaStaticInvoker(); - + // Return the address of the __invoke function. + DeclarationName InvokeName = &Context.Idents.get("__invoke"); + CXXMethodDecl *Invoke + = cast(Lambda->lookup(InvokeName).front()); Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(), VK_LValue, Conv->getLocation()).take(); - assert(FunctionRef && "Can't refer to lambda static invoker function?"); + assert(FunctionRef && "Can't refer to __invoke function?"); Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take(); Conv->setBody(new (Context) CompoundStmt(Context, Return, Conv->getLocation(), Conv->getLocation())); - // Fill in the invoke function with a dummy implementation. IR generation + // Fill in the __invoke function with a dummy implementation. IR generation // will fill in the actual details. Invoke->setUsed(); Invoke->setReferenced(); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index bed71a676f..ae3a938333 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -14,7 +14,6 @@ #include "clang/AST/ExprCXX.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" -#include "clang/Sema/SemaLambda.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" @@ -121,69 +120,11 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC, llvm_unreachable("unexpected context"); } - -ParmVarDecl *Sema::ActOnLambdaAutoParameter(ParmVarDecl *PVD) { - LambdaScopeInfo *LSI = getCurLambda(); - assert(LSI && "No LambdaScopeInfo on the stack!"); - const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth; - const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size(); - // Invent a template type parameter corresponding to the auto - // containing parameter. - TemplateTypeParmDecl *TemplateParam = - TemplateTypeParmDecl::Create(Context, - // Temporarily add to the TranslationUnit DeclContext. When the - // associated TemplateParameterList is attached to a template - // declaration (such as FunctionTemplateDecl), the DeclContext - // for each template parameter gets updated appropriately via - // a call to AdoptTemplateParameterList. - Context.getTranslationUnitDecl(), - SourceLocation(), - PVD->getLocation(), - TemplateParameterDepth, - AutoParameterPosition, // our template param index - /* Identifier*/ 0, false, PVD->isParameterPack()); - LSI->AutoTemplateParams.push_back(TemplateParam); - QualType AutoTy = PVD->getType(); - // Now replace the 'auto' in the function parameter with this invented - // template type parameter. - QualType TemplParamType = QualType(TemplateParam->getTypeForDecl(), 0); - - TypeSourceInfo *AutoTSI = PVD->getTypeSourceInfo(); - TypeSourceInfo *NewTSI = SubstAutoTypeSourceInfo(AutoTSI, TemplParamType); - PVD->setType(NewTSI->getType()); - PVD->setTypeSourceInfo(NewTSI); - return PVD; -} - - -static inline TemplateParameterList * - getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, - Sema &SemaRef) { - if (LSI->GLTemplateParameterList) - return LSI->GLTemplateParameterList; - else if (LSI->AutoTemplateParams.size()) { - SourceRange IntroRange = LSI->IntroducerRange; - SourceLocation LAngleLoc = IntroRange.getBegin(); - SourceLocation RAngleLoc = IntroRange.getEnd(); - LSI->GLTemplateParameterList = - TemplateParameterList::Create(SemaRef.Context, - /* Template kw loc */ SourceLocation(), - LAngleLoc, - (NamedDecl**)LSI->AutoTemplateParams.data(), - LSI->AutoTemplateParams.size(), RAngleLoc); - } - return LSI->GLTemplateParameterList; -} - - - CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodType, SourceLocation EndLoc, ArrayRef Params) { - TemplateParameterList *TemplateParams = - getGenericLambdaTemplateParameterList(getCurLambda(), *this); // C++11 [expr.prim.lambda]p5: // The closure type for a lambda-expression has a public inline function // call operator (13.5.4) whose parameters and return type are described by @@ -211,17 +152,6 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, // Temporarily set the lexical declaration context to the current // context, so that the Scope stack matches the lexical nesting. Method->setLexicalDeclContext(CurContext); - // Create a function template if we have a template parameter list - FunctionTemplateDecl *const TemplateMethod = TemplateParams ? - FunctionTemplateDecl::Create(Context, Class, - Method->getLocation(), MethodName, - TemplateParams, - Method) : 0; - if (TemplateMethod) { - TemplateMethod->setLexicalDeclContext(CurContext); - TemplateMethod->setAccess(AS_public); - Method->setDescribedFunctionTemplate(TemplateMethod); - } // Add parameters. if (!Params.empty()) { @@ -247,16 +177,15 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, return Method; } -void Sema::buildLambdaScope(LambdaScopeInfo *LSI, - CXXMethodDecl *CallOperator, +LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, bool ExplicitParams, bool ExplicitResultType, bool Mutable) { - LSI->CallOperator = CallOperator; - LSI->Lambda = CallOperator->getParent(); + PushLambdaScope(CallOperator->getParent(), CallOperator); + LambdaScopeInfo *LSI = getCurLambda(); if (CaptureDefault == LCD_ByCopy) LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; else if (CaptureDefault == LCD_ByRef) @@ -279,6 +208,8 @@ void Sema::buildLambdaScope(LambdaScopeInfo *LSI, } else { LSI->HasImplicitReturnType = true; } + + return LSI; } void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { @@ -427,7 +358,7 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef returns, } void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { - assert(CSI.HasImplicitReturnType || CSI.ReturnType->isUndeducedType()); + assert(CSI.HasImplicitReturnType); // C++ Core Issue #975, proposed resolution: // If a lambda-expression does not include a trailing-return-type, @@ -461,7 +392,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { // Second case: at least one return statement has dependent type. // Delay type checking until instantiation. assert(!CSI.ReturnType.isNull() && "We should have a tentative return type."); - if (CSI.ReturnType->isDependentType() || CSI.ReturnType->isUndeducedType()) + if (CSI.ReturnType->isDependentType()) return; // Try to apply the enum-fuzz rule. @@ -588,25 +519,15 @@ FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef, } void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, - Declarator &ParamInfo, Scope *CurScope) { + Declarator &ParamInfo, + Scope *CurScope) { // Determine if we're within a context where we know that the lambda will // be dependent, because there are template parameters in scope. bool KnownDependent = false; - LambdaScopeInfo *const LSI = getCurLambda(); - assert(LSI && "LambdaScopeInfo should be on stack!"); - TemplateParameterList *TemplateParams = - getGenericLambdaTemplateParameterList(LSI, *this); - - if (Scope *TmplScope = CurScope->getTemplateParamParent()) { - // Since we have our own TemplateParams, so check if an outer scope - // has template params, only then are we in a dependent scope. - if (TemplateParams) { - TmplScope = TmplScope->getParent(); - TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0; - } - if (TmplScope && !TmplScope->decl_empty()) + if (Scope *TmplScope = CurScope->getTemplateParamParent()) + if (!TmplScope->decl_empty()) KnownDependent = true; - } + // Determine the signature of the call operator. TypeSourceInfo *MethodTyInfo; bool ExplicitParams = true; @@ -621,11 +542,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, FunctionProtoType::ExtProtoInfo EPI; EPI.HasTrailingReturn = true; EPI.TypeQuals |= DeclSpec::TQ_const; - // For C++1y, use the new return type deduction machinery, by imaginging - // 'auto' if no trailing return type. - QualType DefaultTypeForNoTrailingReturn = getLangOpts().CPlusPlus1y ? - Context.getAutoDeductType() : Context.DependentTy; - QualType MethodTy = Context.getFunctionType(DefaultTypeForNoTrailingReturn, None, + QualType MethodTy = Context.getFunctionType(Context.DependentTy, None, EPI); MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); ExplicitParams = false; @@ -643,15 +560,14 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (!FTI.hasMutableQualifier()) FTI.TypeQuals |= DeclSpec::TQ_const; - ExplicitResultType = FTI.hasTrailingReturnType(); - // In C++11 if there is no explicit return type, the return type is - // artificially set to DependentTy, whereas in C++1y it is set to AutoTy - // (through ConvertDeclSpecToType) which allows us to support both - // C++11 and C++1y return type deduction semantics. MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); assert(MethodTyInfo && "no type from lambda-declarator"); EndLoc = ParamInfo.getSourceRange().getEnd(); + ExplicitResultType + = MethodTyInfo->getType()->getAs()->getResultType() + != Context.DependentTy; + if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && cast(FTI.ArgInfo[0].Param)->getType()->isVoidType()) { // Empty arg list, don't push any params. @@ -672,6 +588,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params); + if (ExplicitParams) CheckCXXDefaultArguments(Method); @@ -681,8 +598,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // Introduce the function call operator as the current declaration context. PushDeclContext(CurScope, Method); - // Build the lambda scope. - buildLambdaScope(LSI, Method, + // Introduce the lambda scope. + LambdaScopeInfo *LSI + = enterLambdaScope(Method, Intro.Range, Intro.Default, Intro.DefaultLoc, ExplicitParams, @@ -894,8 +812,6 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { - // FIXME: The conversion operator needs to be fixed for generic lambdas. - if (Class->isGenericLambda()) return; // Add the conversion to function pointer. const FunctionProtoType *Proto = CallOperator->getType()->getAs(); @@ -933,9 +849,10 @@ static void addFunctionPointerConversion(Sema &S, Conversion->setAccess(AS_public); Conversion->setImplicit(true); Class->addDecl(Conversion); - // Add a non-static member function that will be the result of - // the conversion with a certain unique ID. - Name = &S.Context.Idents.get(getLambdaStaticInvokerName()); + + // Add a non-static member function "__invoke" that will be the result of + // the conversion. + Name = &S.Context.Idents.get("__invoke"); CXXMethodDecl *Invoke = CXXMethodDecl::Create(S.Context, Class, Loc, DeclarationNameInfo(Name, Loc), FunctionTy, @@ -1083,11 +1000,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, // If a lambda-expression does not include a // trailing-return-type, it is as if the trailing-return-type // denotes the following type: - // Skip for C++1y return type deduction semantics which uses - // different machinery currently. - // FIXME: Refactor and Merge the return type deduction machinery. // FIXME: Assumes current resolution to core issue 975. - if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) { + if (LSI->HasImplicitReturnType) { deduceClosureReturnType(*LSI); // - if there are no return statements in the @@ -1105,18 +1019,13 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, LSI->ReturnType, Proto->getArgTypes(), Proto->getExtProtoInfo()); CallOperator->setType(FunctionTy); } + // C++ [expr.prim.lambda]p7: // The lambda-expression's compound-statement yields the // function-body (8.4) of the function call operator [...]. ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation); CallOperator->setLexicalDeclContext(Class); - Decl *TemplateOrNonTemplateCallOperatorDecl = - !CallOperator->getDescribedFunctionTemplate() ? cast(CallOperator) - : CallOperator->getDescribedFunctionTemplate(); - - TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class); - Class->addDecl(TemplateOrNonTemplateCallOperatorDecl); - + Class->addDecl(CallOperator); PopExpressionEvaluationContext(); // C++11 [expr.prim.lambda]p6: @@ -1156,7 +1065,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, CaptureInits, ArrayIndexVars, ArrayIndexStarts, Body->getLocEnd(), ContainsUnexpandedParameterPack); - Class->setLambdaExpr(Lambda); + // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand // (Clause 5). @@ -1176,15 +1085,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, break; } } - // TODO: Implement capturing. - if (Lambda->isGenericLambda()) { - if (Lambda->getCaptureDefault() != LCD_None) { - Diag(Lambda->getIntroducerRange().getBegin(), - diag::err_glambda_not_fully_implemented) - << " capturing not implemented yet"; - return ExprError(); - } - } + return MaybeBindToTemporary(Lambda); } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 33dbf14580..06d1f0b0e2 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -8670,10 +8670,6 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, } } } - // FIXME: For generic lambda parameters, check if the function is a lambda - // call operator, and if so, emit a prettier and more informative - // diagnostic that mentions 'auto' and lambda in addition to - // (or instead of?) the canonical template type parameters. S.Diag(Templated->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch) << FirstTA << SecondTA; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index c53b31a692..8f907460c4 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2487,31 +2487,12 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // [expr.prim.lambda]p4 in C++11; block literals follow the same rules. CapturingScopeInfo *CurCap = cast(getCurFunction()); QualType FnRetType = CurCap->ReturnType; - LambdaScopeInfo *const LambdaSI = getCurLambda(); - // In C++1y, an implicit return type behaves as if 'auto' was - // the return type. - if (FnRetType.isNull() && getLangOpts().CPlusPlus1y) { - if (LambdaSI) { - FunctionDecl *CallOp = LambdaSI->CallOperator; - FnRetType = CallOp->getResultType(); - assert(FnRetType->getContainedAutoType()); - } - } - - // For blocks/lambdas with implicit return types in C++11, we check each - // return statement individually, and deduce the common return type when - // the block or lambda is completed. In C++1y, the return type deduction - // of a lambda is specified in terms of auto. - // Notably, in C++11, we take the type of the expression after decay and - // lvalue-to-rvalue conversion, so a class type can be cv-qualified. - // In C++1y, we perform template argument deduction as if the return - // type were 'auto', so an implicit return type is never cv-qualified. - // i.e if (getLangOpts().CPlusPlus1y && FnRetType.hasQualifiers()) - // FnRetType = FnRetType.getUnqualifiedType(); - // Return type deduction is unchanged for blocks in C++1y. - // FIXME: Fold this into the 'auto' codepath below. - if (CurCap->HasImplicitReturnType && - (!LambdaSI || !getLangOpts().CPlusPlus1y)) { + + // For blocks/lambdas with implicit return types, we check each return + // statement individually, and deduce the common return type when the block + // or lambda is completed. + if (CurCap->HasImplicitReturnType) { + // FIXME: Fold this into the 'auto' codepath below. if (RetValExp && !isa(RetValExp)) { ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp); if (Result.isInvalid()) @@ -2519,7 +2500,13 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { RetValExp = Result.take(); if (!CurContext->isDependentContext()) { - FnRetType = RetValExp->getType(); + FnRetType = RetValExp->getType(); + // In C++11, we take the type of the expression after decay and + // lvalue-to-rvalue conversion, so a class type can be cv-qualified. + // In C++1y, we perform template argument deduction as if the return + // type were 'auto', so an implicit return type is never cv-qualified. + if (getLangOpts().CPlusPlus1y && FnRetType.hasQualifiers()) + FnRetType = FnRetType.getUnqualifiedType(); } else FnRetType = CurCap->ReturnType = Context.DependentTy; } else { @@ -2530,6 +2517,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { Diag(ReturnLoc, diag::err_lambda_return_init_list) << RetValExp->getSourceRange(); } + FnRetType = Context.VoidTy; } @@ -2538,8 +2526,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (CurCap->ReturnType.isNull()) CurCap->ReturnType = FnRetType; } else if (AutoType *AT = - (FnRetType.isNull() || !LambdaSI) ? 0 - : FnRetType->getContainedAutoType()) { + FnRetType.isNull() ? 0 : FnRetType->getContainedAutoType()) { // In C++1y, the return type may involve 'auto'. FunctionDecl *FD = cast(CurCap)->CallOperator; if (CurContext->isDependentContext()) { @@ -2547,7 +2534,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // Return type deduction [...] occurs when the definition is // instantiated even if the function body contains a return // statement with a non-type-dependent operand. - CurCap->ReturnType = FnRetType; + CurCap->ReturnType = FnRetType = Context.DependentTy; } else if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { FD->setInvalidDecl(); return StmtError(); @@ -2577,7 +2564,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // pickier with blocks than for normal functions because we don't have GCC // compatibility to worry about here. const VarDecl *NRVOCandidate = 0; - if (FnRetType->isDependentType() || FnRetType->isUndeducedType()) { + if (FnRetType->isDependentType()) { // Delay processing for now. TODO: there are lots of dependent // types we can conclusively prove aren't void. } else if (FnRetType->isVoidType()) { @@ -2637,6 +2624,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return Owned(Result); } + /// Deduce the return type for a function from a returned expression, per /// C++1y [dcl.spec.auto]p6. bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, @@ -2646,6 +2634,7 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, TypeLoc OrigResultType = FD->getTypeSourceInfo()->getTypeLoc(). IgnoreParens().castAs().getResultLoc(); QualType Deduced; + if (RetExpr && isa(RetExpr)) { // If the deduction is for a return statement and the initializer is // a braced-init-list, the program is ill-formed. @@ -2703,18 +2692,9 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, AutoType *NewAT = Deduced->getContainedAutoType(); if (!FD->isDependentContext() && !Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) { - LambdaScopeInfo *const LambdaSI = getCurLambda(); - if (LambdaSI && LambdaSI->HasImplicitReturnType) { - Diag(ReturnLoc, - diag::err_typecheck_missing_return_type_incompatible) - << NewAT->getDeducedType() << AT->getDeducedType() - << true /*IsLambda*/; - } - else { - Diag(ReturnLoc, diag::err_auto_fn_different_deductions) - << (AT->isDecltypeAuto() ? 1 : 0) - << NewAT->getDeducedType() << AT->getDeducedType(); - } + Diag(ReturnLoc, diag::err_auto_fn_different_deductions) + << (AT->isDecltypeAuto() ? 1 : 0) + << NewAT->getDeducedType() << AT->getDeducedType(); return true; } } else if (!FD->isInvalidDecl()) { @@ -2730,8 +2710,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // Check for unexpanded parameter packs. if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) return StmtError(); + if (isa(getCurFunction())) return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp); + QualType FnRetType; QualType RelatedRetType; if (const FunctionDecl *FD = getCurFunctionDecl()) { diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 813f71d40d..c8669ae7b8 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -3766,8 +3766,7 @@ namespace { QualType Result = SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement, TL.getTypePtr()->isDecltypeAuto(), - Dependent, TL.getTypePtr()-> - containsUnexpandedParameterPack()); + Dependent); AutoTypeLoc NewTL = TLB.push(Result); NewTL.setNameLoc(TL.getNameLoc()); return Result; @@ -3908,16 +3907,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) { return DAR_Succeeded; } -QualType Sema::SubstAutoType(QualType TypeWithAuto, - QualType TypeToReplaceAuto) { - return SubstituteAutoTransform(*this, TypeToReplaceAuto). - TransformType(TypeWithAuto); -} - -TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, - QualType TypeToReplaceAuto) { - return SubstituteAutoTransform(*this, TypeToReplaceAuto). - TransformType(TypeWithAuto); +QualType Sema::SubstAutoType(QualType Type, QualType Deduced) { + return SubstituteAutoTransform(*this, Deduced).TransformType(Type); } void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) { diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 2dabfb2bbc..6998827e16 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -781,13 +781,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // specified with a trailing return type or inferred. if (declarator.getContext() == Declarator::LambdaExprContext || isOmittedBlockReturnType(declarator)) { - // In C++1y (n3690 CD), 5.1.2 [expr.prim.lambda]/4 : The lambda return - // type is auto, which is replaced by the trailing-return-type if - // provided and/or deduced from return statements as described - // in 7.1.6.4. - Result = S.getLangOpts().CPlusPlus1y && - declarator.getContext() == Declarator::LambdaExprContext - ? Context.getAutoDeductType() : Context.DependentTy; + Result = Context.DependentTy; break; } @@ -1012,17 +1006,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { case DeclSpec::TST_auto: // TypeQuals handled by caller. - Result = Context.getAutoType(QualType(), - /*decltype(auto)*/false, - /*IsDependent*/ false, - /*IsParameterPack*/ declarator.hasEllipsis()); + Result = Context.getAutoType(QualType(), /*decltype(auto)*/false); break; case DeclSpec::TST_decltype_auto: - Result = Context.getAutoType(QualType(), - /*decltype(auto)*/true, - /*IsDependent*/ false, - /*IsParameterPack*/ false); + Result = Context.getAutoType(QualType(), /*decltype(auto)*/true); break; case DeclSpec::TST_unknown_anytype: @@ -1569,7 +1557,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, ASM = ArrayType::Normal; } } else if (!T->isDependentType() && !T->isVariablyModifiedType() && - !T->isIncompleteType() && !T->isUndeducedType()) { + !T->isIncompleteType()) { // Is the array too large? unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal); @@ -2109,7 +2097,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // In C++11, a function declarator using 'auto' must have a trailing return // type (this is checked later) and we can skip this. In other languages // using auto, we need to check regardless. - // Generic Lambdas (C++14) allow 'auto' in their parameters. if (ContainsPlaceholderType && (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) { int Error = -1; @@ -2122,12 +2109,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::ObjCParameterContext: case Declarator::ObjCResultContext: case Declarator::PrototypeContext: - Error = 0; - break; - case Declarator::LambdaExprParameterContext: - if (!(SemaRef.getLangOpts().CPlusPlus1y - && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto)) - Error = 0; + Error = 0; // Function prototype break; case Declarator::MemberContext: if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static) @@ -2207,13 +2189,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, AutoRange = D.getName().getSourceRange(); if (Error != -1) { - if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto) { - SemaRef.Diag(AutoRange.getBegin(), - diag::err_decltype_auto_function_declarator_not_declaration); - } else { SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed) << Error << AutoRange; - } T = SemaRef.Context.IntTy; D.setInvalidType(true); } else @@ -2263,7 +2240,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, D.setInvalidType(true); break; case Declarator::PrototypeContext: - case Declarator::LambdaExprParameterContext: case Declarator::ObjCParameterContext: case Declarator::ObjCResultContext: case Declarator::KNRTypeListContext: @@ -2637,11 +2613,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } } - const AutoType *AT = T->getContainedAutoType(); - // Allow arrays of auto if we are a generic lambda parameter. - // i.e. [](auto (&array)[5]) { return array[0]; }; OK - if (AT && !(S.getLangOpts().CPlusPlus1y && - D.getContext() == Declarator::LambdaExprParameterContext)) { + + if (const AutoType *AT = T->getContainedAutoType()) { // We've already diagnosed this for decltype(auto). if (!AT->isDecltypeAuto()) S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto) @@ -3137,7 +3110,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // is a parameter pack (14.5.3). [...] switch (D.getContext()) { case Declarator::PrototypeContext: - case Declarator::LambdaExprParameterContext: // C++0x [dcl.fct]p13: // [...] When it is part of a parameter-declaration-clause, the // parameter pack is a function parameter pack (14.5.3). The type T @@ -3156,6 +3128,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, T = Context.getPackExpansionType(T, None); } break; + case Declarator::TemplateParamContext: // C++0x [temp.param]p15: // If a template-parameter is a [...] is a parameter-declaration that diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 164bb89d0b..a627944ef4 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -782,10 +782,7 @@ 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. - // FIXME: Can we assume the same about IsParameterPack? - return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto, - /*IsDependent*/ false, - /*IsParameterPack*/ false); + return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto); } /// \brief Build a new template specialization type. @@ -3496,9 +3493,7 @@ TreeTransform::TransformQualifiedType(TypeLocBuilder &TLB, Qs.removeObjCLifetime(); Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(), Qs); - Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(), - AutoTy->isDependentType(), - AutoTy->containsUnexpandedParameterPack()); + Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto()); TLB.TypeWasModifiedSafely(Result); } else { // Otherwise, complain about the addition of a qualifier to an @@ -8197,14 +8192,6 @@ TreeTransform::TransformCXXTemporaryObjectExpr( template ExprResult TreeTransform::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 @@ -8227,10 +8214,7 @@ TreeTransform::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(), @@ -8265,9 +8249,9 @@ TreeTransform::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. - getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(), + sema::LambdaScopeInfo *LSI + = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(), E->getCaptureDefault(), E->getCaptureDefaultLoc(), E->hasExplicitParameters(), diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 5b1a608e60..462c2d3db9 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4740,9 +4740,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) { QualType Deduced = readType(*Loc.F, Record, Idx); bool IsDecltypeAuto = Record[Idx++]; bool IsDependent = Deduced.isNull() ? Record[Idx++] : false; - bool IsParameterPack = Record[Idx++]; - return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent, - IsParameterPack); + return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent); } case TYPE_RECORD: { diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 74e99379a4..7099d32b3d 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1201,7 +1201,6 @@ void ASTDeclReader::ReadCXXDefinitionData( = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures); Capture *ToCapture = Lambda.Captures; Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx); - Lambda.TheLambdaExpr = cast(Reader.ReadExpr(F)); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { SourceLocation Loc = ReadSourceLocation(Record, Idx); bool IsImplicit = Record[Idx++]; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 01bc9cbc37..d8485300be 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -253,7 +253,6 @@ void ASTTypeWriter::VisitAutoType(const AutoType *T) { Record.push_back(T->isDecltypeAuto()); if (T->getDeducedType().isNull()) Record.push_back(T->isDependentType()); - Record.push_back(T->containsUnexpandedParameterPack()); Code = TYPE_AUTO; } @@ -5137,7 +5136,6 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Lambda.ManglingNumber); AddDeclRef(Lambda.ContextDecl, Record); AddTypeSourceInfo(Lambda.MethodTyInfo, Record); - AddStmt(Lambda.TheLambdaExpr); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { LambdaExpr::Capture &Capture = Lambda.Captures[I]; AddSourceLocation(Capture.getLocation(), Record); diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp deleted file mode 100644 index 29044f4745..0000000000 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y - -//FIXME: These tests were written when return type deduction had not been implemented -// for generic lambdas, hence -template T id(T t); -template int vfoo(Ts&& ... ts); -auto GL1 = [](auto a, int i) -> int { return id(a); }; - -auto GL2 = [](auto ... As) -> int { return vfoo(As...); }; -auto GL3 = [](int i, char c, auto* ... As) -> int { return vfoo(As...); }; - -auto GL4 = [](int i, char c, auto* ... As) -> int { return vfoo(As...); }; - - -void foo() { - auto GL1 = [](auto a, int i) -> int { return id(a); }; - - auto GL2 = [](auto ... As) -> int { return vfoo(As...); }; -} - - -int main() -{ - auto l1 = [](auto a) -> int { return a + 5; }; - auto l2 = [](auto *p) -> int { return p + 5; }; - - struct A { int i; char f(int) { return 'c'; } }; - auto l3 = [](auto &&ur, - auto &lr, - auto v, - int i, - auto* p, - auto A::*memvar, - auto (A::*memfun)(int), - char c, - decltype (v)* pv - , auto (&array)[5] - ) -> int { return v + i + c - + array[0]; - }; - int arr[5] = {0, 1, 2, 3, 4 }; - int lval = 0; - double d = 3.14; - l3(3, lval, d, lval, &lval, &A::i, &A::f, 'c', &d, arr); - auto l4 = [](decltype(auto) a) -> int { return 0; }; //expected-error{{decltype(auto)}} - { - struct Local { - static int ifi(int i) { return i; } - static char cfi(int) { return 'a'; } - static double dfi(int i) { return i + 3.14; } - static Local localfi(int) { return Local{}; } - }; - auto l4 = [](auto (*fp)(int)) -> int { return fp(3); }; //expected-error{{no viable conversion from 'Local' to 'int'}} - l4(&Local::ifi); - l4(&Local::cfi); - l4(&Local::dfi); - l4(&Local::localfi); //expected-note{{in instantiation of function template specialization}} - } - { - auto unnamed_parameter = [](auto, auto) -> void { }; - unnamed_parameter(3, '4'); - } - { - auto l = [](auto - (*)(auto)) { }; //expected-error{{'auto' not allowed}} - //FIXME: These diagnostics might need some work. - auto l2 = [](char auto::*pm) { }; //expected-error{{cannot combine with previous}}\ - expected-error{{'pm' does not point into a class}} - auto l3 = [](char (auto::*pmf)()) { }; //expected-error{{'auto' not allowed}}\ - expected-error{{'pmf' does not point into a class}}\ - expected-error{{function cannot return function type 'char ()'}} - } -} - - diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp deleted file mode 100644 index fcfd9bcb7d..0000000000 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -emit-llvm -namespace return_type_deduction_ok { -// FIXME: Once return type deduction is implemented for generic lambdas -// this will need to be updated. - auto l = [](auto a) ->auto { return a; }(2); - auto l2 = [](auto a) ->decltype(auto) { return a; }(2); - auto l3 = [](auto a) { return a; }(2); - - -} - -namespace lambda_capturing { -// FIXME: Once return type deduction is implemented for generic lambdas -// this will need to be updated. -void test() { - int i = 10; - auto L = [=](auto a) -> int { //expected-error{{unimplemented}} - return i + a; - }; - L(3); -} - -} - -namespace nested_generic_lambdas { -void test() { - auto L = [](auto a) -> int { - auto M = [](auto b, decltype(a) b2) -> int { //expected-error{{unimplemented}} - return 1; - }; - M(a, a); - }; - L(3); //expected-note{{in instantiation of}} -} -} - -namespace conversion_operator { -void test() { - auto L = [](auto a) -> int { return a; }; - int (*fp)(int) = L; //expected-error{{no viable conversion}} - } -} - -namespace generic_lambda_as_default_argument_ok { - void test(int i = [](auto a)->int { return a; }(3)) { - - } - -} - diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp deleted file mode 100644 index 44656a37e3..0000000000 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y - -// prvalue -void prvalue() { - auto&& x = [](auto a)->void { }; - auto& y = [](auto *a)->void { }; // expected-error{{cannot bind to a temporary of type}} -} - -namespace std { - class type_info; -} - -struct P { - virtual ~P(); -}; - -void unevaluated_operand(P &p, int i) { - // FIXME: this should only emit one error. - int i2 = sizeof([](auto a, auto b)->void{}(3, '4')); // expected-error{{lambda expression in an unevaluated operand}} \ - // expected-error{{invalid application of 'sizeof'}} - const std::type_info &ti1 = typeid([](auto &a) -> P& { static P p; return p; }(i)); - const std::type_info &ti2 = typeid([](auto) -> int { return i; }(i)); // expected-error{{lambda expression in an unevaluated operand}} -} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp index f8461335b7..79ee76f025 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp @@ -7,60 +7,3 @@ int &d = [] (int &r) -> auto & { return r; } (a); int &e = [] (int &r) -> auto { return r; } (a); // expected-error {{cannot bind to a temporary}} int &f = [] (int r) -> decltype(auto) { return r; } (a); // expected-error {{cannot bind to a temporary}} int &g = [] (int r) -> decltype(auto) { return (r); } (a); // expected-warning {{reference to stack}} - - -int test_explicit_auto_return() -{ - struct X {}; - auto L = [](auto F, auto a) { return F(a); }; - auto M = [](auto a) -> auto { return a; }; // OK - auto MRef = [](auto b) -> auto& { return b; }; //expected-warning{{reference to stack}} - auto MPtr = [](auto c) -> auto* { return &c; }; //expected-warning{{address of stack}} - auto MDeclType = [](auto&& d) -> decltype(auto) { return static_cast(d); }; //OK - M(3); - - auto &&x = MDeclType(X{}); - auto &&x1 = M(X{}); - auto &&x2 = MRef(X{});//expected-note{{in instantiation of}} - auto &&x3 = MPtr(X{}); //expected-note{{in instantiation of}} - return 0; -} - -int test_implicit_auto_return() -{ - { - auto M = [](auto a) { return a; }; - struct X {}; - X x = M(X{}); - - } -} - -int test_multiple_returns() { - auto M = [](auto a) { - bool k; - if (k) - return a; - else - return 5; //expected-error{{deduced as 'int' here}} - }; - M(3); // OK - M('a'); //expected-note{{in instantiation of}} - return 0; -} -int test_no_parameter_list() -{ - static int si = 0; - auto M = [] { return 5; }; // OK - auto M2 = [] -> auto&& { return si; }; // expected-error{{lambda requires '()'}} - M(); -} - -int test_conditional_in_return() { - auto Fac = [](auto f, auto n) { - return n <= 0 ? n : f(f, n - 1) * n; - }; - // FIXME: this test causes a recursive limit - need to error more gracefully. - //Fac(Fac, 3); - -} \ No newline at end of file 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 1016cb1d30..c69aa115be 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify -// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -DCPP1Y +// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify void missing_lambda_declarator() { [](){}(); @@ -18,7 +18,7 @@ void infer_void_return_type(int i) { switch (x) { case 0: return get(); case 1: return; - case 2: return { 1, 2.0 }; //expected-error{{cannot deduce}} + case 2: return { 1, 2.0 }; // expected-error{{cannot deduce lambda return type from initializer list}} } }(7); } diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp deleted file mode 100644 index c1311617ef..0000000000 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y -emit-llvm - -namespace test_factorial { - -auto Fact = [](auto Self, unsigned n) -> unsigned { - return !n ? 1 : Self(Self, n - 1) * n; -}; - -auto six = Fact(Fact, 3); - -} - -namespace overload_generic_lambda { - template struct overload : F1, F2 { - using F1::operator(); - using F2::operator(); - overload(F1 f1, F2 f2) : F1(f1), F2(f2) { } - }; - - auto NumParams = [](auto Self, auto h, auto ... rest) -> unsigned { - return 1 + Self(Self, rest...); - }; - auto Base = [](auto Self, auto h) -> unsigned { - return 1; - }; - overload O(Base, NumParams); - int num_params = O(O, 5, 3, "abc", 3.14, 'a'); -} - - -namespace overload_generic_lambda_return_type_deduction { - template struct overload : F1, F2 { - using F1::operator(); - using F2::operator(); - overload(F1 f1, F2 f2) : F1(f1), F2(f2) { } - }; - - auto NumParams = [](auto Self, auto h, auto ... rest) { - return 1 + Self(Self, rest...); - }; - auto Base = [](auto Self, auto h) { - return 1; - }; - overload O(Base, NumParams); - int num_params = O(O, 5, 3, "abc", 3.14, 'a'); -} - -namespace test_standard_p5 { -// FIXME: This test should eventually compile without an explicit trailing return type -auto glambda = [](auto a, auto&& b) ->bool { return a < b; }; -bool b = glambda(3, 3.14); // OK - -} -namespace test_deduction_failure { - int test() { - auto g = [](auto *a) { //expected-note{{candidate template ignored}} - return a; - }; - struct X { }; - X *x; - g(x); - g(3); //expected-error{{no matching function}} - return 0; - } - -} - -namespace test_instantiation_or_sfinae_failure { -int test2() { - { - auto L = [](auto *a) { - return (*a)(a); }; //expected-error{{called object type 'double' is not a function}} - //l(&l); - double d; - L(&d); //expected-note{{in instantiation of}} - auto M = [](auto b) { return b; }; - L(&M); // ok - } - { - auto L = [](auto *a) ->decltype (a->foo()) { //expected-note2{{candidate template ignored:}} - return (*a)(a); }; - //l(&l); - double d; - L(&d); //expected-error{{no matching function for call}} - auto M = [](auto b) { return b; }; - L(&M); //expected-error{{no matching function for call}} - - } - return 0; -} - - -} - -namespace test_misc { -auto GL = [](auto a, decltype(a) b) //expected-note{{candidate function}} - -> int { return a + b; }; - -void test() { - struct X { }; - GL(3, X{}); //expected-error{{no matching function}} -} - -void test2() { - auto l = [](auto *a) -> int { - (*a)(a); return 0; }; //expected-error{{called object type 'double' is not a function}} - l(&l); - double d; - l(&d); //expected-note{{in instantiation of}} -} - -} - -namespace nested_lambdas { - int test() { - auto L = [](auto a) { - return [=](auto b) { //expected-error{{unimplemented}} - return a + b; - }; - }; - // auto M = L(3.14); - // return M('4'); - } - auto get_lambda() { - return [](auto a) { - return a; - }; - }; - - int test2() { - auto L = get_lambda(); - L(3); - } -} - -- 2.40.0