Index: head/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h =================================================================== --- head/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h (revision 326775) +++ head/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h (revision 326776) @@ -1,969 +1,970 @@ //===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines FunctionScopeInfo and its subclasses, which contain // information about a single function, block, lambda, or method body. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SEMA_SCOPEINFO_H #define LLVM_CLANG_SEMA_SCOPEINFO_H #include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "clang/Basic/CapturedStmt.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Sema/CleanupInfo.h" #include "clang/Sema/Ownership.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include namespace clang { class Decl; class BlockDecl; class CapturedDecl; class CXXMethodDecl; class FieldDecl; class ObjCPropertyDecl; class IdentifierInfo; class ImplicitParamDecl; class LabelDecl; class ReturnStmt; class Scope; class SwitchStmt; class TemplateTypeParmDecl; class TemplateParameterList; class VarDecl; class ObjCIvarRefExpr; class ObjCPropertyRefExpr; class ObjCMessageExpr; namespace sema { /// \brief Contains information about the compound statement currently being /// parsed. class CompoundScopeInfo { public: CompoundScopeInfo() : HasEmptyLoopBodies(false) { } /// \brief Whether this compound stamement contains `for' or `while' loops /// with empty bodies. bool HasEmptyLoopBodies; void setHasEmptyLoopBodies() { HasEmptyLoopBodies = true; } }; class PossiblyUnreachableDiag { public: PartialDiagnostic PD; SourceLocation Loc; const Stmt *stmt; PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, const Stmt *stmt) : PD(PD), Loc(Loc), stmt(stmt) {} }; /// \brief Retains information about a function, method, or block that is /// currently being parsed. class FunctionScopeInfo { protected: enum ScopeKind { SK_Function, SK_Block, SK_Lambda, SK_CapturedRegion }; public: /// \brief What kind of scope we are describing. /// ScopeKind Kind : 3; /// \brief Whether this function contains a VLA, \@try, try, C++ /// initializer, or anything else that can't be jumped past. bool HasBranchProtectedScope : 1; /// \brief Whether this function contains any switches or direct gotos. bool HasBranchIntoScope : 1; /// \brief Whether this function contains any indirect gotos. bool HasIndirectGoto : 1; /// \brief Whether a statement was dropped because it was invalid. bool HasDroppedStmt : 1; /// \brief True if current scope is for OpenMP declare reduction combiner. bool HasOMPDeclareReductionCombiner : 1; /// \brief Whether there is a fallthrough statement in this function. bool HasFallthroughStmt : 1; /// \brief Whether we make reference to a declaration that could be /// unavailable. bool HasPotentialAvailabilityViolations : 1; /// A flag that is set when parsing a method that must call super's /// implementation, such as \c -dealloc, \c -finalize, or any method marked /// with \c __attribute__((objc_requires_super)). bool ObjCShouldCallSuper : 1; /// True when this is a method marked as a designated initializer. bool ObjCIsDesignatedInit : 1; /// This starts true for a method marked as designated initializer and will /// be set to false if there is an invocation to a designated initializer of /// the super class. bool ObjCWarnForNoDesignatedInitChain : 1; /// True when this is an initializer method not marked as a designated /// initializer within a class that has at least one initializer marked as a /// designated initializer. bool ObjCIsSecondaryInit : 1; /// This starts true for a secondary initializer method and will be set to /// false if there is an invocation of an initializer on 'self'. bool ObjCWarnForNoInitDelegation : 1; /// \brief True only when this function has not already built, or attempted /// to build, the initial and final coroutine suspend points bool NeedsCoroutineSuspends : 1; /// \brief An enumeration represeting the kind of the first coroutine statement /// in the function. One of co_return, co_await, or co_yield. unsigned char FirstCoroutineStmtKind : 2; /// First coroutine statement in the current function. /// (ex co_return, co_await, co_yield) SourceLocation FirstCoroutineStmtLoc; /// First 'return' statement in the current function. SourceLocation FirstReturnLoc; /// First C++ 'try' statement in the current function. SourceLocation FirstCXXTryLoc; /// First SEH '__try' statement in the current function. SourceLocation FirstSEHTryLoc; /// \brief Used to determine if errors occurred in this function or block. DiagnosticErrorTrap ErrorTrap; /// SwitchStack - This is the current set of active switch statements in the /// block. SmallVector SwitchStack; /// \brief The list of return statements that occur within the function or /// block, if there is any chance of applying the named return value /// optimization, or if we need to infer a return type. SmallVector Returns; /// \brief The promise object for this coroutine, if any. VarDecl *CoroutinePromise = nullptr; /// \brief The initial and final coroutine suspend points. std::pair CoroutineSuspends; /// \brief The stack of currently active compound stamement scopes in the /// function. SmallVector CompoundScopes; /// \brief A list of PartialDiagnostics created but delayed within the /// current function scope. These diagnostics are vetted for reachability /// prior to being emitted. SmallVector PossiblyUnreachableDiags; /// \brief A list of parameters which have the nonnull attribute and are /// modified in the function. llvm::SmallPtrSet ModifiedNonNullParams; public: /// Represents a simple identification of a weak object. /// /// Part of the implementation of -Wrepeated-use-of-weak. /// /// This is used to determine if two weak accesses refer to the same object. /// Here are some examples of how various accesses are "profiled": /// /// Access Expression | "Base" Decl | "Property" Decl /// :---------------: | :-----------------: | :------------------------------: /// self.property | self (VarDecl) | property (ObjCPropertyDecl) /// self.implicitProp | self (VarDecl) | -implicitProp (ObjCMethodDecl) /// self->ivar.prop | ivar (ObjCIvarDecl) | prop (ObjCPropertyDecl) /// cxxObj.obj.prop | obj (FieldDecl) | prop (ObjCPropertyDecl) /// [self foo].prop | 0 (unknown) | prop (ObjCPropertyDecl) /// self.prop1.prop2 | prop1 (ObjCPropertyDecl) | prop2 (ObjCPropertyDecl) /// MyClass.prop | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl) /// MyClass.foo.prop | +foo (ObjCMethodDecl) | -prop (ObjCPropertyDecl) /// weakVar | 0 (known) | weakVar (VarDecl) /// self->weakIvar | self (VarDecl) | weakIvar (ObjCIvarDecl) /// /// Objects are identified with only two Decls to make it reasonably fast to /// compare them. class WeakObjectProfileTy { /// The base object decl, as described in the class documentation. /// /// The extra flag is "true" if the Base and Property are enough to uniquely /// identify the object in memory. /// /// \sa isExactProfile() typedef llvm::PointerIntPair BaseInfoTy; BaseInfoTy Base; /// The "property" decl, as described in the class documentation. /// /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the /// case of "implicit" properties (regular methods accessed via dot syntax). const NamedDecl *Property; /// Used to find the proper base profile for a given base expression. static BaseInfoTy getBaseInfo(const Expr *BaseE); inline WeakObjectProfileTy(); static inline WeakObjectProfileTy getSentinel(); public: WeakObjectProfileTy(const ObjCPropertyRefExpr *RE); WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property); WeakObjectProfileTy(const DeclRefExpr *RE); WeakObjectProfileTy(const ObjCIvarRefExpr *RE); const NamedDecl *getBase() const { return Base.getPointer(); } const NamedDecl *getProperty() const { return Property; } /// Returns true if the object base specifies a known object in memory, /// rather than, say, an instance variable or property of another object. /// /// Note that this ignores the effects of aliasing; that is, \c foo.bar is /// considered an exact profile if \c foo is a local variable, even if /// another variable \c foo2 refers to the same object as \c foo. /// /// For increased precision, accesses with base variables that are /// properties or ivars of 'self' (e.g. self.prop1.prop2) are considered to /// be exact, though this is not true for arbitrary variables /// (foo.prop1.prop2). bool isExactProfile() const { return Base.getInt(); } bool operator==(const WeakObjectProfileTy &Other) const { return Base == Other.Base && Property == Other.Property; } // For use in DenseMap. // We can't specialize the usual llvm::DenseMapInfo at the end of the file // because by that point the DenseMap in FunctionScopeInfo has already been // instantiated. class DenseMapInfo { public: static inline WeakObjectProfileTy getEmptyKey() { return WeakObjectProfileTy(); } static inline WeakObjectProfileTy getTombstoneKey() { return WeakObjectProfileTy::getSentinel(); } static unsigned getHashValue(const WeakObjectProfileTy &Val) { typedef std::pair Pair; return llvm::DenseMapInfo::getHashValue(Pair(Val.Base, Val.Property)); } static bool isEqual(const WeakObjectProfileTy &LHS, const WeakObjectProfileTy &RHS) { return LHS == RHS; } }; }; /// Represents a single use of a weak object. /// /// Stores both the expression and whether the access is potentially unsafe /// (i.e. it could potentially be warned about). /// /// Part of the implementation of -Wrepeated-use-of-weak. class WeakUseTy { llvm::PointerIntPair Rep; public: WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {} const Expr *getUseExpr() const { return Rep.getPointer(); } bool isUnsafe() const { return Rep.getInt(); } void markSafe() { Rep.setInt(false); } bool operator==(const WeakUseTy &Other) const { return Rep == Other.Rep; } }; /// Used to collect uses of a particular weak object in a function body. /// /// Part of the implementation of -Wrepeated-use-of-weak. typedef SmallVector WeakUseVector; /// Used to collect all uses of weak objects in a function body. /// /// Part of the implementation of -Wrepeated-use-of-weak. typedef llvm::SmallDenseMap WeakObjectUseMap; private: /// Used to collect all uses of weak objects in this function body. /// /// Part of the implementation of -Wrepeated-use-of-weak. WeakObjectUseMap WeakObjectUses; protected: FunctionScopeInfo(const FunctionScopeInfo&) = default; public: /// Record that a weak object was accessed. /// /// Part of the implementation of -Wrepeated-use-of-weak. template inline void recordUseOfWeak(const ExprT *E, bool IsRead = true); void recordUseOfWeak(const ObjCMessageExpr *Msg, const ObjCPropertyDecl *Prop); /// Record that a given expression is a "safe" access of a weak object (e.g. /// assigning it to a strong variable.) /// /// Part of the implementation of -Wrepeated-use-of-weak. void markSafeWeakUse(const Expr *E); const WeakObjectUseMap &getWeakObjectUses() const { return WeakObjectUses; } void setHasBranchIntoScope() { HasBranchIntoScope = true; } void setHasBranchProtectedScope() { HasBranchProtectedScope = true; } void setHasIndirectGoto() { HasIndirectGoto = true; } void setHasDroppedStmt() { HasDroppedStmt = true; } void setHasOMPDeclareReductionCombiner() { HasOMPDeclareReductionCombiner = true; } void setHasFallthroughStmt() { HasFallthroughStmt = true; } void setHasCXXTry(SourceLocation TryLoc) { setHasBranchProtectedScope(); FirstCXXTryLoc = TryLoc; } void setHasSEHTry(SourceLocation TryLoc) { setHasBranchProtectedScope(); FirstSEHTryLoc = TryLoc; } bool NeedsScopeChecking() const { return !HasDroppedStmt && (HasIndirectGoto || (HasBranchProtectedScope && HasBranchIntoScope)); } bool isCoroutine() const { return !FirstCoroutineStmtLoc.isInvalid(); } void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) { assert(FirstCoroutineStmtLoc.isInvalid() && "first coroutine statement location already set"); FirstCoroutineStmtLoc = Loc; FirstCoroutineStmtKind = llvm::StringSwitch(Keyword) .Case("co_return", 0) .Case("co_await", 1) .Case("co_yield", 2); } StringRef getFirstCoroutineStmtKeyword() const { assert(FirstCoroutineStmtLoc.isValid() && "no coroutine statement available"); switch (FirstCoroutineStmtKind) { case 0: return "co_return"; case 1: return "co_await"; case 2: return "co_yield"; default: llvm_unreachable("FirstCoroutineStmtKind has an invalid value"); }; } void setNeedsCoroutineSuspends(bool value = true) { assert((!value || CoroutineSuspends.first == nullptr) && "we already have valid suspend points"); NeedsCoroutineSuspends = value; } bool hasInvalidCoroutineSuspends() const { return !NeedsCoroutineSuspends && CoroutineSuspends.first == nullptr; } void setCoroutineSuspends(Stmt *Initial, Stmt *Final) { assert(Initial && Final && "suspend points cannot be null"); assert(CoroutineSuspends.first == nullptr && "suspend points already set"); NeedsCoroutineSuspends = false; CoroutineSuspends.first = Initial; CoroutineSuspends.second = Final; } FunctionScopeInfo(DiagnosticsEngine &Diag) : Kind(SK_Function), HasBranchProtectedScope(false), HasBranchIntoScope(false), HasIndirectGoto(false), HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false), HasFallthroughStmt(false), HasPotentialAvailabilityViolations(false), ObjCShouldCallSuper(false), ObjCIsDesignatedInit(false), ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false), NeedsCoroutineSuspends(true), ErrorTrap(Diag) { } virtual ~FunctionScopeInfo(); /// \brief Clear out the information in this function scope, making it /// suitable for reuse. void Clear(); }; class CapturingScopeInfo : public FunctionScopeInfo { protected: CapturingScopeInfo(const CapturingScopeInfo&) = default; public: enum ImplicitCaptureStyle { ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block, ImpCap_CapturedRegion }; ImplicitCaptureStyle ImpCaptureStyle; class Capture { // There are three categories of capture: capturing 'this', capturing // local variables, and C++1y initialized captures (which can have an // arbitrary initializer, and don't really capture in the traditional // sense at all). // // There are three ways to capture a local variable: // - capture by copy in the C++11 sense, // - capture by reference in the C++11 sense, and // - __block capture. // Lambdas explicitly specify capture by copy or capture by reference. // For blocks, __block capture applies to variables with that annotation, // variables of reference type are captured by reference, and other // variables are captured by copy. enum CaptureKind { Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA }; enum { IsNestedCapture = 0x1, IsThisCaptured = 0x2 }; /// The variable being captured (if we are not capturing 'this') and whether /// this is a nested capture, and whether we are capturing 'this' llvm::PointerIntPair VarAndNestedAndThis; /// Expression to initialize a field of the given type, and the kind of /// capture (if this is a capture and not an init-capture). The expression /// is only required if we are capturing ByVal and the variable's type has /// a non-trivial copy constructor. llvm::PointerIntPair InitExprAndCaptureKind; /// \brief The source location at which the first capture occurred. SourceLocation Loc; /// \brief The location of the ellipsis that expands a parameter pack. SourceLocation EllipsisLoc; /// \brief The type as it was captured, which is in effect the type of the /// non-static data member that would hold the capture. QualType CaptureType; /// \brief Whether an explicit capture has been odr-used in the body of the /// lambda. bool ODRUsed; /// \brief Whether an explicit capture has been non-odr-used in the body of /// the lambda. bool NonODRUsed; public: Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, SourceLocation Loc, SourceLocation EllipsisLoc, QualType CaptureType, Expr *Cpy) : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0), InitExprAndCaptureKind( Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef : Cap_ByCopy), Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType), ODRUsed(false), NonODRUsed(false) {} enum IsThisCapture { ThisCapture }; Capture(IsThisCapture, bool IsNested, SourceLocation Loc, QualType CaptureType, Expr *Cpy, const bool ByCopy) : VarAndNestedAndThis( nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))), InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef), Loc(Loc), EllipsisLoc(), CaptureType(CaptureType), ODRUsed(false), NonODRUsed(false) {} bool isThisCapture() const { return VarAndNestedAndThis.getInt() & IsThisCaptured; } bool isVariableCapture() const { return !isThisCapture() && !isVLATypeCapture(); } bool isCopyCapture() const { return InitExprAndCaptureKind.getInt() == Cap_ByCopy; } bool isReferenceCapture() const { return InitExprAndCaptureKind.getInt() == Cap_ByRef; } bool isBlockCapture() const { return InitExprAndCaptureKind.getInt() == Cap_Block; } bool isVLATypeCapture() const { return InitExprAndCaptureKind.getInt() == Cap_VLA; } bool isNested() const { return VarAndNestedAndThis.getInt() & IsNestedCapture; } bool isODRUsed() const { return ODRUsed; } bool isNonODRUsed() const { return NonODRUsed; } void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; } VarDecl *getVariable() const { + assert(isVariableCapture()); return VarAndNestedAndThis.getPointer(); } /// \brief Retrieve the location at which this variable was captured. SourceLocation getLocation() const { return Loc; } /// \brief Retrieve the source location of the ellipsis, whose presence /// indicates that the capture is a pack expansion. SourceLocation getEllipsisLoc() const { return EllipsisLoc; } /// \brief Retrieve the capture type for this capture, which is effectively /// the type of the non-static data member in the lambda/block structure /// that would store this capture. QualType getCaptureType() const { assert(!isThisCapture()); return CaptureType; } Expr *getInitExpr() const { assert(!isVLATypeCapture() && "no init expression for type capture"); return static_cast(InitExprAndCaptureKind.getPointer()); } }; CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0), HasImplicitReturnType(false) {} /// CaptureMap - A map of captured variables to (index+1) into Captures. llvm::DenseMap CaptureMap; /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; /// zero if 'this' is not captured. unsigned CXXThisCaptureIndex; /// Captures - The captures. SmallVector Captures; /// \brief - Whether the target type of return statements in this context /// is deduced (e.g. a lambda or block with omitted return type). bool HasImplicitReturnType; /// ReturnType - The target type of return statements in this context, /// or null if unknown. QualType ReturnType; void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested, SourceLocation Loc, SourceLocation EllipsisLoc, QualType CaptureType, Expr *Cpy) { Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, EllipsisLoc, CaptureType, Cpy)); CaptureMap[Var] = Captures.size(); } void addVLATypeCapture(SourceLocation Loc, QualType CaptureType) { Captures.push_back(Capture(/*Var*/ nullptr, /*isBlock*/ false, /*isByref*/ false, /*isNested*/ false, Loc, /*EllipsisLoc*/ SourceLocation(), CaptureType, /*Cpy*/ nullptr)); } // Note, we do not need to add the type of 'this' since that is always // retrievable from Sema::getCurrentThisType - and is also encoded within the // type of the corresponding FieldDecl. void addThisCapture(bool isNested, SourceLocation Loc, Expr *Cpy, bool ByCopy); /// \brief Determine whether the C++ 'this' is captured. bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } /// \brief Retrieve the capture of C++ 'this', if it has been captured. Capture &getCXXThisCapture() { assert(isCXXThisCaptured() && "this has not been captured"); return Captures[CXXThisCaptureIndex - 1]; } /// \brief Determine whether the given variable has been captured. bool isCaptured(VarDecl *Var) const { return CaptureMap.count(Var); } /// \brief Determine whether the given variable-array type has been captured. bool isVLATypeCaptured(const VariableArrayType *VAT) const; /// \brief Retrieve the capture of the given variable, if it has been /// captured already. Capture &getCapture(VarDecl *Var) { assert(isCaptured(Var) && "Variable has not been captured"); return Captures[CaptureMap[Var] - 1]; } const Capture &getCapture(VarDecl *Var) const { llvm::DenseMap::const_iterator Known = CaptureMap.find(Var); assert(Known != CaptureMap.end() && "Variable has not been captured"); return Captures[Known->second - 1]; } static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda || FSI->Kind == SK_CapturedRegion; } }; /// \brief Retains information about a block that is currently being parsed. class BlockScopeInfo final : public CapturingScopeInfo { public: BlockDecl *TheDecl; /// TheScope - This is the scope for the block itself, which contains /// arguments etc. Scope *TheScope; /// BlockType - The function type of the block, if one was given. /// Its return type may be BuiltinType::Dependent. QualType FunctionType; BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), TheScope(BlockScope) { Kind = SK_Block; } ~BlockScopeInfo() override; static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_Block; } }; /// \brief Retains information about a captured region. class CapturedRegionScopeInfo final : public CapturingScopeInfo { public: /// \brief The CapturedDecl for this statement. CapturedDecl *TheCapturedDecl; /// \brief The captured record type. RecordDecl *TheRecordDecl; /// \brief This is the enclosing scope of the captured region. Scope *TheScope; /// \brief The implicit parameter for the captured variables. ImplicitParamDecl *ContextParam; /// \brief The kind of captured region. unsigned short CapRegionKind; unsigned short OpenMPLevel; CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD, RecordDecl *RD, ImplicitParamDecl *Context, CapturedRegionKind K, unsigned OpenMPLevel) : CapturingScopeInfo(Diag, ImpCap_CapturedRegion), TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S), ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel) { Kind = SK_CapturedRegion; } ~CapturedRegionScopeInfo() override; /// \brief A descriptive name for the kind of captured region this is. StringRef getRegionName() const { switch (CapRegionKind) { case CR_Default: return "default captured statement"; case CR_OpenMP: return "OpenMP region"; } llvm_unreachable("Invalid captured region kind!"); } static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_CapturedRegion; } }; class LambdaScopeInfo final : public CapturingScopeInfo { public: /// \brief The class that describes the lambda. CXXRecordDecl *Lambda; /// \brief The lambda's compiler-generated \c operator(). CXXMethodDecl *CallOperator; /// \brief Source range covering the lambda introducer [...]. SourceRange IntroducerRange; /// \brief Source location of the '&' or '=' specifying the default capture /// type, if any. SourceLocation CaptureDefaultLoc; /// \brief The number of captures in the \c Captures list that are /// explicit captures. unsigned NumExplicitCaptures; /// \brief Whether this is a mutable lambda. bool Mutable; /// \brief Whether the (empty) parameter list is explicit. bool ExplicitParams; /// \brief Whether any of the capture expressions requires cleanups. CleanupInfo Cleanup; /// \brief Whether the lambda contains an unexpanded parameter pack. bool ContainsUnexpandedParameterPack; /// \brief If this is a generic lambda, use this as the depth of /// each 'auto' parameter, during initial AST construction. unsigned AutoTemplateParameterDepth; /// \brief Store the list of the auto parameters for a generic lambda. /// 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. SmallVector AutoTemplateParams; /// If this is a generic lambda, and the template parameter /// list has been created (from the AutoTemplateParams) then /// store a reference to it (cache it to avoid reconstructing it). TemplateParameterList *GLTemplateParameterList; /// \brief Contains all variable-referring-expressions (i.e. DeclRefExprs /// or MemberExprs) that refer to local variables in a generic lambda /// or a lambda in a potentially-evaluated-if-used context. /// /// Potentially capturable variables of a nested lambda that might need /// to be captured by the lambda are housed here. /// This is specifically useful for generic lambdas or /// lambdas within a a potentially evaluated-if-used context. /// If an enclosing variable is named in an expression of a lambda nested /// within a generic lambda, we don't always know know whether the variable /// will truly be odr-used (i.e. need to be captured) by that nested lambda, /// until its instantiation. But we still need to capture it in the /// enclosing lambda if all intervening lambdas can capture the variable. llvm::SmallVector PotentiallyCapturingExprs; /// \brief Contains all variable-referring-expressions that refer /// to local variables that are usable as constant expressions and /// do not involve an odr-use (they may still need to be captured /// if the enclosing full-expression is instantiation dependent). llvm::SmallSet NonODRUsedCapturingExprs; /// Contains all of the variables defined in this lambda that shadow variables /// that were defined in parent contexts. Used to avoid warnings when the /// shadowed variables are uncaptured by this lambda. struct ShadowedOuterDecl { const VarDecl *VD; const VarDecl *ShadowedDecl; }; llvm::SmallVector ShadowingDecls; SourceLocation PotentialThisCaptureLocation; LambdaScopeInfo(DiagnosticsEngine &Diag) : CapturingScopeInfo(Diag, ImpCap_None), Lambda(nullptr), CallOperator(nullptr), NumExplicitCaptures(0), Mutable(false), ExplicitParams(false), Cleanup{}, ContainsUnexpandedParameterPack(false), AutoTemplateParameterDepth(0), GLTemplateParameterList(nullptr) { Kind = SK_Lambda; } /// \brief Note when all explicit captures have been added. void finishedExplicitCaptures() { NumExplicitCaptures = Captures.size(); } static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_Lambda; } /// /// \brief Add a variable that might potentially be captured by the /// lambda and therefore the enclosing lambdas. /// /// This is also used by enclosing lambda's to speculatively capture /// variables that nested lambda's - depending on their enclosing /// specialization - might need to capture. /// Consider: /// void f(int, int); <-- don't capture /// void f(const int&, double); <-- capture /// void foo() { /// const int x = 10; /// auto L = [=](auto a) { // capture 'x' /// return [=](auto b) { /// f(x, a); // we may or may not need to capture 'x' /// }; /// }; /// } void addPotentialCapture(Expr *VarExpr) { assert(isa(VarExpr) || isa(VarExpr)); PotentiallyCapturingExprs.push_back(VarExpr); } void addPotentialThisCapture(SourceLocation Loc) { PotentialThisCaptureLocation = Loc; } bool hasPotentialThisCapture() const { return PotentialThisCaptureLocation.isValid(); } /// \brief Mark a variable's reference in a lambda as non-odr using. /// /// For generic lambdas, if a variable is named in a potentially evaluated /// expression, where the enclosing full expression is dependent then we /// must capture the variable (given a default capture). /// This is accomplished by recording all references to variables /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of /// PotentialCaptures. All such variables have to be captured by that lambda, /// except for as described below. /// If that variable is usable as a constant expression and is named in a /// manner that does not involve its odr-use (e.g. undergoes /// lvalue-to-rvalue conversion, or discarded) record that it is so. Upon the /// act of analyzing the enclosing full expression (ActOnFinishFullExpr) /// if we can determine that the full expression is not instantiation- /// dependent, then we can entirely avoid its capture. /// /// const int n = 0; /// [&] (auto x) { /// (void)+n + x; /// }; /// Interestingly, this strategy would involve a capture of n, even though /// it's obviously not odr-used here, because the full-expression is /// instantiation-dependent. It could be useful to avoid capturing such /// variables, even when they are referred to in an instantiation-dependent /// expression, if we can unambiguously determine that they shall never be /// odr-used. This would involve removal of the variable-referring-expression /// from the array of PotentialCaptures during the lvalue-to-rvalue /// conversions. But per the working draft N3797, (post-chicago 2013) we must /// capture such variables. /// Before anyone is tempted to implement a strategy for not-capturing 'n', /// consider the insightful warning in: /// /cfe-commits/Week-of-Mon-20131104/092596.html /// "The problem is that the set of captures for a lambda is part of the ABI /// (since lambda layout can be made visible through inline functions and the /// like), and there are no guarantees as to which cases we'll manage to build /// an lvalue-to-rvalue conversion in, when parsing a template -- some /// seemingly harmless change elsewhere in Sema could cause us to start or stop /// building such a node. So we need a rule that anyone can implement and get /// exactly the same result". /// void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) { assert(isa(CapturingVarExpr) || isa(CapturingVarExpr)); NonODRUsedCapturingExprs.insert(CapturingVarExpr); } bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const { assert(isa(CapturingVarExpr) || isa(CapturingVarExpr)); return NonODRUsedCapturingExprs.count(CapturingVarExpr); } void removePotentialCapture(Expr *E) { PotentiallyCapturingExprs.erase( std::remove(PotentiallyCapturingExprs.begin(), PotentiallyCapturingExprs.end(), E), PotentiallyCapturingExprs.end()); } void clearPotentialCaptures() { PotentiallyCapturingExprs.clear(); PotentialThisCaptureLocation = SourceLocation(); } unsigned getNumPotentialVariableCaptures() const { return PotentiallyCapturingExprs.size(); } bool hasPotentialCaptures() const { return getNumPotentialVariableCaptures() || PotentialThisCaptureLocation.isValid(); } // When passed the index, returns the VarDecl and Expr associated // with the index. void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) const; }; FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy() : Base(nullptr, false), Property(nullptr) {} FunctionScopeInfo::WeakObjectProfileTy FunctionScopeInfo::WeakObjectProfileTy::getSentinel() { FunctionScopeInfo::WeakObjectProfileTy Result; Result.Base.setInt(true); return Result; } template void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { assert(E); WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)]; Uses.push_back(WeakUseTy(E, IsRead)); } inline void CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc, Expr *Cpy, const bool ByCopy) { Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, QualType(), Cpy, ByCopy)); CXXThisCaptureIndex = Captures.size(); } } // end namespace sema } // end namespace clang #endif Index: head/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp =================================================================== --- head/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp (revision 326775) +++ head/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp (revision 326776) @@ -1,1717 +1,1720 @@ //===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements semantic analysis for C++ lambda expressions. // //===----------------------------------------------------------------------===// #include "clang/Sema/DeclSpec.h" #include "TypeLocBuilder.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaLambda.h" using namespace clang; using namespace sema; /// \brief Examines the FunctionScopeInfo stack to determine the nearest /// enclosing lambda (to the current lambda) that is 'capture-ready' for /// the variable referenced in the current lambda (i.e. \p VarToCapture). /// If successful, returns the index into Sema's FunctionScopeInfo stack /// of the capture-ready lambda's LambdaScopeInfo. /// /// Climbs down the stack of lambdas (deepest nested lambda - i.e. current /// lambda - is on top) to determine the index of the nearest enclosing/outer /// lambda that is ready to capture the \p VarToCapture being referenced in /// the current lambda. /// As we climb down the stack, we want the index of the first such lambda - /// that is the lambda with the highest index that is 'capture-ready'. /// /// A lambda 'L' is capture-ready for 'V' (var or this) if: /// - its enclosing context is non-dependent /// - and if the chain of lambdas between L and the lambda in which /// V is potentially used (i.e. the lambda at the top of the scope info /// stack), can all capture or have already captured V. /// If \p VarToCapture is 'null' then we are trying to capture 'this'. /// /// Note that a lambda that is deemed 'capture-ready' still needs to be checked /// for whether it is 'capture-capable' (see /// getStackIndexOfNearestEnclosingCaptureCapableLambda), before it can truly /// capture. /// /// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a /// LambdaScopeInfo inherits from). The current/deepest/innermost lambda /// is at the top of the stack and has the highest index. /// \param VarToCapture - the variable to capture. If NULL, capture 'this'. /// /// \returns An Optional Index that if evaluates to 'true' contains /// the index (into Sema's FunctionScopeInfo stack) of the innermost lambda /// which is capture-ready. If the return value evaluates to 'false' then /// no lambda is capture-ready for \p VarToCapture. static inline Optional getStackIndexOfNearestEnclosingCaptureReadyLambda( ArrayRef FunctionScopes, VarDecl *VarToCapture) { // Label failure to capture. const Optional NoLambdaIsCaptureReady; // Ignore all inner captured regions. unsigned CurScopeIndex = FunctionScopes.size() - 1; while (CurScopeIndex > 0 && isa( FunctionScopes[CurScopeIndex])) --CurScopeIndex; assert( isa(FunctionScopes[CurScopeIndex]) && "The function on the top of sema's function-info stack must be a lambda"); // If VarToCapture is null, we are attempting to capture 'this'. const bool IsCapturingThis = !VarToCapture; const bool IsCapturingVariable = !IsCapturingThis; // Start with the current lambda at the top of the stack (highest index). DeclContext *EnclosingDC = cast(FunctionScopes[CurScopeIndex])->CallOperator; do { const clang::sema::LambdaScopeInfo *LSI = cast(FunctionScopes[CurScopeIndex]); // IF we have climbed down to an intervening enclosing lambda that contains // the variable declaration - it obviously can/must not capture the // variable. // Since its enclosing DC is dependent, all the lambdas between it and the // innermost nested lambda are dependent (otherwise we wouldn't have // arrived here) - so we don't yet have a lambda that can capture the // variable. if (IsCapturingVariable && VarToCapture->getDeclContext()->Equals(EnclosingDC)) return NoLambdaIsCaptureReady; // For an enclosing lambda to be capture ready for an entity, all // intervening lambda's have to be able to capture that entity. If even // one of the intervening lambda's is not capable of capturing the entity // then no enclosing lambda can ever capture that entity. // For e.g. // const int x = 10; // [=](auto a) { #1 // [](auto b) { #2 <-- an intervening lambda that can never capture 'x' // [=](auto c) { #3 // f(x, c); <-- can not lead to x's speculative capture by #1 or #2 // }; }; }; // If they do not have a default implicit capture, check to see // if the entity has already been explicitly captured. // If even a single dependent enclosing lambda lacks the capability // to ever capture this variable, there is no further enclosing // non-dependent lambda that can capture this variable. if (LSI->ImpCaptureStyle == sema::LambdaScopeInfo::ImpCap_None) { if (IsCapturingVariable && !LSI->isCaptured(VarToCapture)) return NoLambdaIsCaptureReady; if (IsCapturingThis && !LSI->isCXXThisCaptured()) return NoLambdaIsCaptureReady; } EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC); assert(CurScopeIndex); --CurScopeIndex; } while (!EnclosingDC->isTranslationUnit() && EnclosingDC->isDependentContext() && isLambdaCallOperator(EnclosingDC)); assert(CurScopeIndex < (FunctionScopes.size() - 1)); // If the enclosingDC is not dependent, then the immediately nested lambda // (one index above) is capture-ready. if (!EnclosingDC->isDependentContext()) return CurScopeIndex + 1; return NoLambdaIsCaptureReady; } /// \brief Examines the FunctionScopeInfo stack to determine the nearest /// enclosing lambda (to the current lambda) that is 'capture-capable' for /// the variable referenced in the current lambda (i.e. \p VarToCapture). /// If successful, returns the index into Sema's FunctionScopeInfo stack /// of the capture-capable lambda's LambdaScopeInfo. /// /// Given the current stack of lambdas being processed by Sema and /// the variable of interest, to identify the nearest enclosing lambda (to the /// current lambda at the top of the stack) that can truly capture /// a variable, it has to have the following two properties: /// a) 'capture-ready' - be the innermost lambda that is 'capture-ready': /// - climb down the stack (i.e. starting from the innermost and examining /// each outer lambda step by step) checking if each enclosing /// lambda can either implicitly or explicitly capture the variable. /// Record the first such lambda that is enclosed in a non-dependent /// context. If no such lambda currently exists return failure. /// b) 'capture-capable' - make sure the 'capture-ready' lambda can truly /// capture the variable by checking all its enclosing lambdas: /// - check if all outer lambdas enclosing the 'capture-ready' lambda /// identified above in 'a' can also capture the variable (this is done /// via tryCaptureVariable for variables and CheckCXXThisCapture for /// 'this' by passing in the index of the Lambda identified in step 'a') /// /// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a /// LambdaScopeInfo inherits from). The current/deepest/innermost lambda /// is at the top of the stack. /// /// \param VarToCapture - the variable to capture. If NULL, capture 'this'. /// /// /// \returns An Optional Index that if evaluates to 'true' contains /// the index (into Sema's FunctionScopeInfo stack) of the innermost lambda /// which is capture-capable. If the return value evaluates to 'false' then /// no lambda is capture-capable for \p VarToCapture. Optional clang::getStackIndexOfNearestEnclosingCaptureCapableLambda( ArrayRef FunctionScopes, VarDecl *VarToCapture, Sema &S) { const Optional NoLambdaIsCaptureCapable; const Optional OptionalStackIndex = getStackIndexOfNearestEnclosingCaptureReadyLambda(FunctionScopes, VarToCapture); if (!OptionalStackIndex) return NoLambdaIsCaptureCapable; const unsigned IndexOfCaptureReadyLambda = OptionalStackIndex.getValue(); assert(((IndexOfCaptureReadyLambda != (FunctionScopes.size() - 1)) || S.getCurGenericLambda()) && "The capture ready lambda for a potential capture can only be the " "current lambda if it is a generic lambda"); const sema::LambdaScopeInfo *const CaptureReadyLambdaLSI = cast(FunctionScopes[IndexOfCaptureReadyLambda]); // If VarToCapture is null, we are attempting to capture 'this' const bool IsCapturingThis = !VarToCapture; const bool IsCapturingVariable = !IsCapturingThis; if (IsCapturingVariable) { // Check if the capture-ready lambda can truly capture the variable, by // checking whether all enclosing lambdas of the capture-ready lambda allow // the capture - i.e. make sure it is capture-capable. QualType CaptureType, DeclRefType; const bool CanCaptureVariable = !S.tryCaptureVariable(VarToCapture, /*ExprVarIsUsedInLoc*/ SourceLocation(), clang::Sema::TryCapture_Implicit, /*EllipsisLoc*/ SourceLocation(), /*BuildAndDiagnose*/ false, CaptureType, DeclRefType, &IndexOfCaptureReadyLambda); if (!CanCaptureVariable) return NoLambdaIsCaptureCapable; } else { // Check if the capture-ready lambda can truly capture 'this' by checking // whether all enclosing lambdas of the capture-ready lambda can capture // 'this'. const bool CanCaptureThis = !S.CheckCXXThisCapture( CaptureReadyLambdaLSI->PotentialThisCaptureLocation, /*Explicit*/ false, /*BuildAndDiagnose*/ false, &IndexOfCaptureReadyLambda); if (!CanCaptureThis) return NoLambdaIsCaptureCapable; } return IndexOfCaptureReadyLambda; } static inline TemplateParameterList * getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { if (LSI->GLTemplateParameterList) return LSI->GLTemplateParameterList; if (!LSI->AutoTemplateParams.empty()) { SourceRange IntroRange = LSI->IntroducerRange; SourceLocation LAngleLoc = IntroRange.getBegin(); SourceLocation RAngleLoc = IntroRange.getEnd(); LSI->GLTemplateParameterList = TemplateParameterList::Create( SemaRef.Context, /*Template kw loc*/ SourceLocation(), LAngleLoc, llvm::makeArrayRef((NamedDecl *const *)LSI->AutoTemplateParams.data(), LSI->AutoTemplateParams.size()), RAngleLoc, nullptr); } return LSI->GLTemplateParameterList; } CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info, bool KnownDependent, LambdaCaptureDefault CaptureDefault) { DeclContext *DC = CurContext; while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) DC = DC->getParent(); bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(), *this); // Start constructing the lambda class. CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info, IntroducerRange.getBegin(), KnownDependent, IsGenericLambda, CaptureDefault); DC->addDecl(Class); return Class; } /// \brief Determine whether the given context is or is enclosed in an inline /// function. static bool isInInlineFunction(const DeclContext *DC) { while (!DC->isFileContext()) { if (const FunctionDecl *FD = dyn_cast(DC)) if (FD->isInlined()) return true; DC = DC->getLexicalParent(); } return false; } MangleNumberingContext * Sema::getCurrentMangleNumberContext(const DeclContext *DC, Decl *&ManglingContextDecl) { // Compute the context for allocating mangling numbers in the current // expression, if the ABI requires them. ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl; enum ContextKind { Normal, DefaultArgument, DataMember, StaticDataMember } Kind = Normal; // Default arguments of member function parameters that appear in a class // definition, as well as the initializers of data members, receive special // treatment. Identify them. if (ManglingContextDecl) { if (ParmVarDecl *Param = dyn_cast(ManglingContextDecl)) { if (const DeclContext *LexicalDC = Param->getDeclContext()->getLexicalParent()) if (LexicalDC->isRecord()) Kind = DefaultArgument; } else if (VarDecl *Var = dyn_cast(ManglingContextDecl)) { if (Var->getDeclContext()->isRecord()) Kind = StaticDataMember; } else if (isa(ManglingContextDecl)) { Kind = DataMember; } } // Itanium ABI [5.1.7]: // In the following contexts [...] the one-definition rule requires closure // types in different translation units to "correspond": bool IsInNonspecializedTemplate = inTemplateInstantiation() || CurContext->isDependentContext(); switch (Kind) { case Normal: { // -- the bodies of non-exported nonspecialized template functions // -- the bodies of inline functions if ((IsInNonspecializedTemplate && !(ManglingContextDecl && isa(ManglingContextDecl))) || isInInlineFunction(CurContext)) { ManglingContextDecl = nullptr; while (auto *CD = dyn_cast(DC)) DC = CD->getParent(); return &Context.getManglingNumberContext(DC); } ManglingContextDecl = nullptr; return nullptr; } case StaticDataMember: // -- the initializers of nonspecialized static members of template classes if (!IsInNonspecializedTemplate) { ManglingContextDecl = nullptr; return nullptr; } // Fall through to get the current context. LLVM_FALLTHROUGH; case DataMember: // -- the in-class initializers of class members case DefaultArgument: // -- default arguments appearing in class definitions return &ExprEvalContexts.back().getMangleNumberingContext(Context); } llvm_unreachable("unexpected context"); } MangleNumberingContext & Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext( ASTContext &Ctx) { assert(ManglingContextDecl && "Need to have a context declaration"); if (!MangleNumbering) MangleNumbering = Ctx.createMangleNumberingContext(); return *MangleNumbering; } CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc, ArrayRef Params, const bool IsConstexprSpecified) { QualType MethodType = MethodTypeInfo->getType(); TemplateParameterList *TemplateParams = getGenericLambdaTemplateParameterList(getCurLambda(), *this); // If a lambda appears in a dependent context or is a generic lambda (has // template parameters) and has an 'auto' return type, deduce it to a // dependent type. if (Class->isDependentContext() || TemplateParams) { const FunctionProtoType *FPT = MethodType->castAs(); QualType Result = FPT->getReturnType(); if (Result->isUndeducedType()) { Result = SubstAutoType(Result, Context.DependentTy); MethodType = Context.getFunctionType(Result, FPT->getParamTypes(), FPT->getExtProtoInfo()); } } // 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 // the lambda-expression's parameter-declaration-clause and // trailing-return-type respectively. DeclarationName MethodName = Context.DeclarationNames.getCXXOperatorName(OO_Call); DeclarationNameLoc MethodNameLoc; MethodNameLoc.CXXOperatorName.BeginOpNameLoc = IntroducerRange.getBegin().getRawEncoding(); MethodNameLoc.CXXOperatorName.EndOpNameLoc = IntroducerRange.getEnd().getRawEncoding(); CXXMethodDecl *Method = CXXMethodDecl::Create(Context, Class, EndLoc, DeclarationNameInfo(MethodName, IntroducerRange.getBegin(), MethodNameLoc), MethodType, MethodTypeInfo, SC_None, /*isInline=*/true, IsConstexprSpecified, EndLoc); Method->setAccess(AS_public); // 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) : nullptr; if (TemplateMethod) { TemplateMethod->setLexicalDeclContext(CurContext); TemplateMethod->setAccess(AS_public); Method->setDescribedFunctionTemplate(TemplateMethod); } // Add parameters. if (!Params.empty()) { Method->setParams(Params); CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false); for (auto P : Method->parameters()) P->setOwningFunction(Method); } Decl *ManglingContextDecl; if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext(Class->getDeclContext(), ManglingContextDecl)) { unsigned ManglingNumber = MCtx->getManglingNumber(Method); Class->setLambdaMangling(ManglingNumber, ManglingContextDecl); } return Method; } void Sema::buildLambdaScope(LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, bool ExplicitParams, bool ExplicitResultType, bool Mutable) { LSI->CallOperator = CallOperator; CXXRecordDecl *LambdaClass = CallOperator->getParent(); LSI->Lambda = LambdaClass; if (CaptureDefault == LCD_ByCopy) LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; else if (CaptureDefault == LCD_ByRef) LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref; LSI->CaptureDefaultLoc = CaptureDefaultLoc; LSI->IntroducerRange = IntroducerRange; LSI->ExplicitParams = ExplicitParams; LSI->Mutable = Mutable; if (ExplicitResultType) { LSI->ReturnType = CallOperator->getReturnType(); if (!LSI->ReturnType->isDependentType() && !LSI->ReturnType->isVoidType()) { if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType, diag::err_lambda_incomplete_result)) { // Do nothing. } } } else { LSI->HasImplicitReturnType = true; } } void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { LSI->finishedExplicitCaptures(); } void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { // Introduce our parameters into the function scope for (unsigned p = 0, NumParams = CallOperator->getNumParams(); p < NumParams; ++p) { ParmVarDecl *Param = CallOperator->getParamDecl(p); // If this has an identifier, add it to the scope stack. if (CurScope && Param->getIdentifier()) { CheckShadow(CurScope, Param); PushOnScopeChains(Param, CurScope); } } } /// If this expression is an enumerator-like expression of some type /// T, return the type T; otherwise, return null. /// /// Pointer comparisons on the result here should always work because /// it's derived from either the parent of an EnumConstantDecl /// (i.e. the definition) or the declaration returned by /// EnumType::getDecl() (i.e. the definition). static EnumDecl *findEnumForBlockReturn(Expr *E) { // An expression is an enumerator-like expression of type T if, // ignoring parens and parens-like expressions: E = E->IgnoreParens(); // - it is an enumerator whose enum type is T or if (DeclRefExpr *DRE = dyn_cast(E)) { if (EnumConstantDecl *D = dyn_cast(DRE->getDecl())) { return cast(D->getDeclContext()); } return nullptr; } // - it is a comma expression whose RHS is an enumerator-like // expression of type T or if (BinaryOperator *BO = dyn_cast(E)) { if (BO->getOpcode() == BO_Comma) return findEnumForBlockReturn(BO->getRHS()); return nullptr; } // - it is a statement-expression whose value expression is an // enumerator-like expression of type T or if (StmtExpr *SE = dyn_cast(E)) { if (Expr *last = dyn_cast_or_null(SE->getSubStmt()->body_back())) return findEnumForBlockReturn(last); return nullptr; } // - it is a ternary conditional operator (not the GNU ?: // extension) whose second and third operands are // enumerator-like expressions of type T or if (ConditionalOperator *CO = dyn_cast(E)) { if (EnumDecl *ED = findEnumForBlockReturn(CO->getTrueExpr())) if (ED == findEnumForBlockReturn(CO->getFalseExpr())) return ED; return nullptr; } // (implicitly:) // - it is an implicit integral conversion applied to an // enumerator-like expression of type T or if (ImplicitCastExpr *ICE = dyn_cast(E)) { // We can sometimes see integral conversions in valid // enumerator-like expressions. if (ICE->getCastKind() == CK_IntegralCast) return findEnumForBlockReturn(ICE->getSubExpr()); // Otherwise, just rely on the type. } // - it is an expression of that formal enum type. if (const EnumType *ET = E->getType()->getAs()) { return ET->getDecl(); } // Otherwise, nope. return nullptr; } /// Attempt to find a type T for which the returned expression of the /// given statement is an enumerator-like expression of that type. static EnumDecl *findEnumForBlockReturn(ReturnStmt *ret) { if (Expr *retValue = ret->getRetValue()) return findEnumForBlockReturn(retValue); return nullptr; } /// Attempt to find a common type T for which all of the returned /// expressions in a block are enumerator-like expressions of that /// type. static EnumDecl *findCommonEnumForBlockReturns(ArrayRef returns) { ArrayRef::iterator i = returns.begin(), e = returns.end(); // Try to find one for the first return. EnumDecl *ED = findEnumForBlockReturn(*i); if (!ED) return nullptr; // Check that the rest of the returns have the same enum. for (++i; i != e; ++i) { if (findEnumForBlockReturn(*i) != ED) return nullptr; } // Never infer an anonymous enum type. if (!ED->hasNameForLinkage()) return nullptr; return ED; } /// Adjust the given return statements so that they formally return /// the given type. It should require, at most, an IntegralCast. static void adjustBlockReturnsToEnum(Sema &S, ArrayRef returns, QualType returnType) { for (ArrayRef::iterator i = returns.begin(), e = returns.end(); i != e; ++i) { ReturnStmt *ret = *i; Expr *retValue = ret->getRetValue(); if (S.Context.hasSameType(retValue->getType(), returnType)) continue; // Right now we only support integral fixup casts. assert(returnType->isIntegralOrUnscopedEnumerationType()); assert(retValue->getType()->isIntegralOrUnscopedEnumerationType()); ExprWithCleanups *cleanups = dyn_cast(retValue); Expr *E = (cleanups ? cleanups->getSubExpr() : retValue); E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, E, /*base path*/ nullptr, VK_RValue); if (cleanups) { cleanups->setSubExpr(E); } else { ret->setRetValue(E); } } } void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { assert(CSI.HasImplicitReturnType); // If it was ever a placeholder, it had to been deduced to DependentTy. assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType()); assert((!isa(CSI) || !getLangOpts().CPlusPlus14) && "lambda expressions use auto deduction in C++14 onwards"); // C++ core issue 975: // If a lambda-expression does not include a trailing-return-type, // it is as if the trailing-return-type denotes the following type: // - if there are no return statements in the compound-statement, // or all return statements return either an expression of type // void or no expression or braced-init-list, the type void; // - otherwise, if all return statements return an expression // and the types of the returned expressions after // lvalue-to-rvalue conversion (4.1 [conv.lval]), // array-to-pointer conversion (4.2 [conv.array]), and // function-to-pointer conversion (4.3 [conv.func]) are the // same, that common type; // - otherwise, the program is ill-formed. // // C++ core issue 1048 additionally removes top-level cv-qualifiers // from the types of returned expressions to match the C++14 auto // deduction rules. // // In addition, in blocks in non-C++ modes, if all of the return // statements are enumerator-like expressions of some type T, where // T has a name for linkage, then we infer the return type of the // block to be that type. // First case: no return statements, implicit void return type. ASTContext &Ctx = getASTContext(); if (CSI.Returns.empty()) { // It's possible there were simply no /valid/ return statements. // In this case, the first one we found may have at least given us a type. if (CSI.ReturnType.isNull()) CSI.ReturnType = Ctx.VoidTy; return; } // 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()) return; // Try to apply the enum-fuzz rule. if (!getLangOpts().CPlusPlus) { assert(isa(CSI)); const EnumDecl *ED = findCommonEnumForBlockReturns(CSI.Returns); if (ED) { CSI.ReturnType = Context.getTypeDeclType(ED); adjustBlockReturnsToEnum(*this, CSI.Returns, CSI.ReturnType); return; } } // Third case: only one return statement. Don't bother doing extra work! SmallVectorImpl::iterator I = CSI.Returns.begin(), E = CSI.Returns.end(); if (I+1 == E) return; // General case: many return statements. // Check that they all have compatible return types. // We require the return types to strictly match here. // Note that we've already done the required promotions as part of // processing the return statement. for (; I != E; ++I) { const ReturnStmt *RS = *I; const Expr *RetE = RS->getRetValue(); QualType ReturnType = (RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType(); if (Context.getCanonicalFunctionResultType(ReturnType) == Context.getCanonicalFunctionResultType(CSI.ReturnType)) continue; // FIXME: This is a poor diagnostic for ReturnStmts without expressions. // TODO: It's possible that the *first* return is the divergent one. Diag(RS->getLocStart(), diag::err_typecheck_missing_return_type_incompatible) << ReturnType << CSI.ReturnType << isa(CSI); // Continue iterating so that we keep emitting diagnostics. } } QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, bool ByRef, IdentifierInfo *Id, bool IsDirectInit, Expr *&Init) { // Create an 'auto' or 'auto&' TypeSourceInfo that we can use to // deduce against. QualType DeductType = Context.getAutoDeductType(); TypeLocBuilder TLB; TLB.pushTypeSpec(DeductType).setNameLoc(Loc); if (ByRef) { DeductType = BuildReferenceType(DeductType, true, Loc, Id); assert(!DeductType.isNull() && "can't build reference to auto"); TLB.push(DeductType).setSigilLoc(Loc); } TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType); // Deduce the type of the init capture. QualType DeducedType = deduceVarTypeFromInitializer( /*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI, SourceRange(Loc, Loc), IsDirectInit, Init); if (DeducedType.isNull()) return QualType(); // Are we a non-list direct initialization? ParenListExpr *CXXDirectInit = dyn_cast(Init); // Perform initialization analysis and ensure any implicit conversions // (such as lvalue-to-rvalue) are enforced. InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture(Id, DeducedType, Loc); InitializationKind Kind = IsDirectInit ? (CXXDirectInit ? InitializationKind::CreateDirect( Loc, Init->getLocStart(), Init->getLocEnd()) : InitializationKind::CreateDirectList(Loc)) : InitializationKind::CreateCopy(Loc, Init->getLocStart()); MultiExprArg Args = Init; if (CXXDirectInit) Args = MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs()); QualType DclT; InitializationSequence InitSeq(*this, Entity, Kind, Args); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT); if (Result.isInvalid()) return QualType(); Init = Result.getAs(); // The init-capture initialization is a full-expression that must be // processed as one before we enter the declcontext of the lambda's // call-operator. Result = ActOnFinishFullExpr(Init, Loc, /*DiscardedValue*/ false, /*IsConstexpr*/ false, /*IsLambdaInitCaptureInitializer*/ true); if (Result.isInvalid()) return QualType(); Init = Result.getAs(); return DeducedType; } VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, QualType InitCaptureType, IdentifierInfo *Id, unsigned InitStyle, Expr *Init) { TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType, Loc); // Create a dummy variable representing the init-capture. This is not actually // used as a variable, and only exists as a way to name and refer to the // init-capture. // FIXME: Pass in separate source locations for '&' and identifier. VarDecl *NewVD = VarDecl::Create(Context, CurContext, Loc, Loc, Id, InitCaptureType, TSI, SC_Auto); NewVD->setInitCapture(true); NewVD->setReferenced(true); // FIXME: Pass in a VarDecl::InitializationStyle. NewVD->setInitStyle(static_cast(InitStyle)); NewVD->markUsed(Context); NewVD->setInit(Init); return NewVD; } FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) { FieldDecl *Field = FieldDecl::Create( Context, LSI->Lambda, Var->getLocation(), Var->getLocation(), nullptr, Var->getType(), Var->getTypeSourceInfo(), nullptr, false, ICIS_NoInit); Field->setImplicit(true); Field->setAccess(AS_private); LSI->Lambda->addDecl(Field); LSI->addCapture(Var, /*isBlock*/false, Var->getType()->isReferenceType(), /*isNested*/false, Var->getLocation(), SourceLocation(), Var->getType(), Var->getInit()); return Field; } void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, 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!"); // The lambda-expression's closure type might be dependent even if its // semantic context isn't, if it appears within a default argument of a // function template. if (CurScope->getTemplateParamParent()) KnownDependent = true; // Determine the signature of the call operator. TypeSourceInfo *MethodTyInfo; bool ExplicitParams = true; bool ExplicitResultType = true; bool ContainsUnexpandedParameterPack = false; SourceLocation EndLoc; SmallVector Params; if (ParamInfo.getNumTypeObjects() == 0) { // C++11 [expr.prim.lambda]p4: // If a lambda-expression does not include a lambda-declarator, it is as // if the lambda-declarator were (). FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); EPI.HasTrailingReturn = true; EPI.TypeQuals |= DeclSpec::TQ_const; // C++1y [expr.prim.lambda]: // The lambda return type is 'auto', which is replaced by the // trailing-return type if provided and/or deduced from 'return' // statements // We don't do this before C++1y, because we don't support deduced return // types there. QualType DefaultTypeForNoTrailingReturn = getLangOpts().CPlusPlus14 ? Context.getAutoDeductType() : Context.DependentTy; QualType MethodTy = Context.getFunctionType(DefaultTypeForNoTrailingReturn, None, EPI); MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); ExplicitParams = false; ExplicitResultType = false; EndLoc = Intro.Range.getEnd(); } else { assert(ParamInfo.isFunctionDeclarator() && "lambda-declarator is a function"); DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo(); // C++11 [expr.prim.lambda]p5: // This function call operator is declared const (9.3.1) if and only if // the lambda-expression's parameter-declaration-clause is not followed // by mutable. It is neither virtual nor declared volatile. [...] if (!FTI.hasMutableQualifier()) FTI.TypeQuals |= DeclSpec::TQ_const; MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); assert(MethodTyInfo && "no type from lambda-declarator"); EndLoc = ParamInfo.getSourceRange().getEnd(); ExplicitResultType = FTI.hasTrailingReturnType(); if (FTIHasNonVoidParameters(FTI)) { Params.reserve(FTI.NumParams); for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) Params.push_back(cast(FTI.Params[i].Param)); } // Check for unexpanded parameter packs in the method type. if (MethodTyInfo->getType()->containsUnexpandedParameterPack()) ContainsUnexpandedParameterPack = true; } CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo, KnownDependent, Intro.Default); CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params, ParamInfo.getDeclSpec().isConstexprSpecified()); if (ExplicitParams) CheckCXXDefaultArguments(Method); // Attributes on the lambda apply to the method. ProcessDeclAttributes(CurScope, Method, ParamInfo); // CUDA lambdas get implicit attributes based on the scope in which they're // declared. if (getLangOpts().CUDA) CUDASetLambdaAttrs(Method); // Introduce the function call operator as the current declaration context. PushDeclContext(CurScope, Method); // Build the lambda scope. buildLambdaScope(LSI, Method, Intro.Range, Intro.Default, Intro.DefaultLoc, ExplicitParams, ExplicitResultType, !Method->isConst()); // C++11 [expr.prim.lambda]p9: // A lambda-expression whose smallest enclosing scope is a block scope is a // local lambda expression; any other lambda expression shall not have a // capture-default or simple-capture in its lambda-introducer. // // For simple-captures, this is covered by the check below that any named // entity is a variable that can be captured. // // For DR1632, we also allow a capture-default in any context where we can // odr-use 'this' (in particular, in a default initializer for a non-static // data member). if (Intro.Default != LCD_None && !Class->getParent()->isFunctionOrMethod() && (getCurrentThisType().isNull() || CheckCXXThisCapture(SourceLocation(), /*Explicit*/true, /*BuildAndDiagnose*/false))) Diag(Intro.DefaultLoc, diag::err_capture_default_non_local); // Distinct capture names, for diagnostics. llvm::SmallSet CaptureNames; // Handle explicit captures. SourceLocation PrevCaptureLoc = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc; for (auto C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E; PrevCaptureLoc = C->Loc, ++C) { if (C->Kind == LCK_This || C->Kind == LCK_StarThis) { if (C->Kind == LCK_StarThis) Diag(C->Loc, !getLangOpts().CPlusPlus1z ? diag::ext_star_this_lambda_capture_cxx1z : diag::warn_cxx14_compat_star_this_lambda_capture); // C++11 [expr.prim.lambda]p8: // An identifier or this shall not appear more than once in a // lambda-capture. if (LSI->isCXXThisCaptured()) { Diag(C->Loc, diag::err_capture_more_than_once) << "'this'" << SourceRange(LSI->getCXXThisCapture().getLocation()) << FixItHint::CreateRemoval( SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); continue; } // C++1z [expr.prim.lambda]p8: // If a lambda-capture includes a capture-default that is =, each // simple-capture of that lambda-capture shall be of the form "& // identifier" or "* this". [ Note: The form [&,this] is redundant but // accepted for compatibility with ISO C++14. --end note ] if (Intro.Default == LCD_ByCopy && C->Kind != LCK_StarThis) { Diag(C->Loc, diag::err_this_capture_with_copy_default) << FixItHint::CreateRemoval( SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); continue; } // C++11 [expr.prim.lambda]p12: // If this is captured by a local lambda expression, its nearest // enclosing function shall be a non-static member function. QualType ThisCaptureType = getCurrentThisType(); if (ThisCaptureType.isNull()) { Diag(C->Loc, diag::err_this_capture) << true; continue; } CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true, /*FunctionScopeIndexToStopAtPtr*/ nullptr, C->Kind == LCK_StarThis); continue; } assert(C->Id && "missing identifier for capture"); if (C->Init.isInvalid()) continue; VarDecl *Var = nullptr; if (C->Init.isUsable()) { Diag(C->Loc, getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_init_capture : diag::ext_init_capture); if (C->Init.get()->containsUnexpandedParameterPack()) ContainsUnexpandedParameterPack = true; // If the initializer expression is usable, but the InitCaptureType // is not, then an error has occurred - so ignore the capture for now. // for e.g., [n{0}] { }; <-- if no is included. // FIXME: we should create the init capture variable and mark it invalid // in this case. if (C->InitCaptureType.get().isNull()) continue; unsigned InitStyle; switch (C->InitKind) { case LambdaCaptureInitKind::NoInit: llvm_unreachable("not an init-capture?"); case LambdaCaptureInitKind::CopyInit: InitStyle = VarDecl::CInit; break; case LambdaCaptureInitKind::DirectInit: InitStyle = VarDecl::CallInit; break; case LambdaCaptureInitKind::ListInit: InitStyle = VarDecl::ListInit; break; } Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(), C->Id, InitStyle, C->Init.get()); // C++1y [expr.prim.lambda]p11: // An init-capture behaves as if it declares and explicitly // captures a variable [...] whose declarative region is the // lambda-expression's compound-statement if (Var) PushOnScopeChains(Var, CurScope, false); } else { assert(C->InitKind == LambdaCaptureInitKind::NoInit && "init capture has valid but null init?"); // C++11 [expr.prim.lambda]p8: // If a lambda-capture includes a capture-default that is &, the // identifiers in the lambda-capture shall not be preceded by &. // If a lambda-capture includes a capture-default that is =, [...] // each identifier it contains shall be preceded by &. if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) { Diag(C->Loc, diag::err_reference_capture_with_reference_default) << FixItHint::CreateRemoval( SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); continue; } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) { Diag(C->Loc, diag::err_copy_capture_with_copy_default) << FixItHint::CreateRemoval( SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); continue; } // C++11 [expr.prim.lambda]p10: // The identifiers in a capture-list are looked up using the usual // rules for unqualified name lookup (3.4.1) DeclarationNameInfo Name(C->Id, C->Loc); LookupResult R(*this, Name, LookupOrdinaryName); LookupName(R, CurScope); if (R.isAmbiguous()) continue; if (R.empty()) { // FIXME: Disable corrections that would add qualification? CXXScopeSpec ScopeSpec; if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, llvm::make_unique>())) continue; } Var = R.getAsSingle(); if (Var && DiagnoseUseOfDecl(Var, C->Loc)) continue; } // C++11 [expr.prim.lambda]p8: // An identifier or this shall not appear more than once in a // lambda-capture. if (!CaptureNames.insert(C->Id).second) { if (Var && LSI->isCaptured(Var)) { Diag(C->Loc, diag::err_capture_more_than_once) << C->Id << SourceRange(LSI->getCapture(Var).getLocation()) << FixItHint::CreateRemoval( SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); } else // Previous capture captured something different (one or both was // an init-cpature): no fixit. Diag(C->Loc, diag::err_capture_more_than_once) << C->Id; continue; } // C++11 [expr.prim.lambda]p10: // [...] each such lookup shall find a variable with automatic storage // duration declared in the reaching scope of the local lambda expression. // Note that the 'reaching scope' check happens in tryCaptureVariable(). if (!Var) { Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id; continue; } // Ignore invalid decls; they'll just confuse the code later. if (Var->isInvalidDecl()) continue; if (!Var->hasLocalStorage()) { Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id; Diag(Var->getLocation(), diag::note_previous_decl) << C->Id; continue; } // C++11 [expr.prim.lambda]p23: // A capture followed by an ellipsis is a pack expansion (14.5.3). SourceLocation EllipsisLoc; if (C->EllipsisLoc.isValid()) { if (Var->isParameterPack()) { EllipsisLoc = C->EllipsisLoc; } else { Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << SourceRange(C->Loc); // Just ignore the ellipsis. } } else if (Var->isParameterPack()) { ContainsUnexpandedParameterPack = true; } if (C->Init.isUsable()) { buildInitCaptureField(LSI, Var); } else { TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : TryCapture_ExplicitByVal; tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); } } finishLambdaExplicitCaptures(LSI); LSI->ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; // Add lambda parameters into scope. addLambdaParameters(Method, CurScope); // Enter a new evaluation context to insulate the lambda from any // cleanups from the enclosing full-expression. PushExpressionEvaluationContext( ExpressionEvaluationContext::PotentiallyEvaluated); } void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, bool IsInstantiation) { LambdaScopeInfo *LSI = cast(FunctionScopes.back()); // Leave the expression-evaluation context. DiscardCleanupsInEvaluationContext(); PopExpressionEvaluationContext(); // Leave the context of the lambda. if (!IsInstantiation) PopDeclContext(); // Finalize the lambda. CXXRecordDecl *Class = LSI->Lambda; Class->setInvalidDecl(); SmallVector Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), SourceLocation(), nullptr); CheckCompletedCXXClass(Class); PopFunctionScopeInfo(); } /// \brief Add a lambda's conversion to function pointer, as described in /// C++11 [expr.prim.lambda]p6. static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { // This conversion is explicitly disabled if the lambda's function has // pass_object_size attributes on any of its parameters. auto HasPassObjectSizeAttr = [](const ParmVarDecl *P) { return P->hasAttr(); }; if (llvm::any_of(CallOperator->parameters(), HasPassObjectSizeAttr)) return; // Add the conversion to function pointer. const FunctionProtoType *CallOpProto = CallOperator->getType()->getAs(); const FunctionProtoType::ExtProtoInfo CallOpExtInfo = CallOpProto->getExtProtoInfo(); QualType PtrToFunctionTy; QualType InvokerFunctionTy; { FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo; CallingConv CC = S.Context.getDefaultCallingConvention( CallOpProto->isVariadic(), /*IsCXXMethod=*/false); InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC); InvokerExtInfo.TypeQuals = 0; assert(InvokerExtInfo.RefQualifier == RQ_None && "Lambda's call operator should not have a reference qualifier"); InvokerFunctionTy = S.Context.getFunctionType(CallOpProto->getReturnType(), CallOpProto->getParamTypes(), InvokerExtInfo); PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy); } // Create the type of the conversion function. FunctionProtoType::ExtProtoInfo ConvExtInfo( S.Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); // The conversion function is always const. ConvExtInfo.TypeQuals = Qualifiers::Const; QualType ConvTy = S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo); SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName ConversionName = S.Context.DeclarationNames.getCXXConversionFunctionName( S.Context.getCanonicalType(PtrToFunctionTy)); DeclarationNameLoc ConvNameLoc; // Construct a TypeSourceInfo for the conversion function, and wire // all the parameters appropriately for the FunctionProtoTypeLoc // so that everything works during transformation/instantiation of // generic lambdas. // The main reason for wiring up the parameters of the conversion // function with that of the call operator is so that constructs // like the following work: // auto L = [](auto b) { <-- 1 // return [](auto a) -> decltype(a) { <-- 2 // return a; // }; // }; // int (*fp)(int) = L(5); // Because the trailing return type can contain DeclRefExprs that refer // to the original call operator's variables, we hijack the call // operators ParmVarDecls below. TypeSourceInfo *ConvNamePtrToFunctionTSI = S.Context.getTrivialTypeSourceInfo(PtrToFunctionTy, Loc); ConvNameLoc.NamedType.TInfo = ConvNamePtrToFunctionTSI; // The conversion function is a conversion to a pointer-to-function. TypeSourceInfo *ConvTSI = S.Context.getTrivialTypeSourceInfo(ConvTy, Loc); FunctionProtoTypeLoc ConvTL = ConvTSI->getTypeLoc().getAs(); // Get the result of the conversion function which is a pointer-to-function. PointerTypeLoc PtrToFunctionTL = ConvTL.getReturnLoc().getAs(); // Do the same for the TypeSourceInfo that is used to name the conversion // operator. PointerTypeLoc ConvNamePtrToFunctionTL = ConvNamePtrToFunctionTSI->getTypeLoc().getAs(); // Get the underlying function types that the conversion function will // be converting to (should match the type of the call operator). FunctionProtoTypeLoc CallOpConvTL = PtrToFunctionTL.getPointeeLoc().getAs(); FunctionProtoTypeLoc CallOpConvNameTL = ConvNamePtrToFunctionTL.getPointeeLoc().getAs(); // Wire up the FunctionProtoTypeLocs with the call operator's parameters. // These parameter's are essentially used to transform the name and // the type of the conversion operator. By using the same parameters // as the call operator's we don't have to fix any back references that // the trailing return type of the call operator's uses (such as // decltype(some_type::type{} + decltype(a){}) etc.) // - we can simply use the return type of the call operator, and // everything should work. SmallVector InvokerParams; for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { ParmVarDecl *From = CallOperator->getParamDecl(I); InvokerParams.push_back(ParmVarDecl::Create(S.Context, // Temporarily add to the TU. This is set to the invoker below. S.Context.getTranslationUnitDecl(), From->getLocStart(), From->getLocation(), From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), /*DefaultArg=*/nullptr)); CallOpConvTL.setParam(I, From); CallOpConvNameTL.setParam(I, From); } CXXConversionDecl *Conversion = CXXConversionDecl::Create(S.Context, Class, Loc, DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI, /*isInline=*/true, /*isExplicit=*/false, /*isConstexpr=*/S.getLangOpts().CPlusPlus1z, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); if (Class->isGenericLambda()) { // Create a template version of the conversion operator, using the template // parameter list of the function call operator. FunctionTemplateDecl *TemplateCallOperator = CallOperator->getDescribedFunctionTemplate(); FunctionTemplateDecl *ConversionTemplate = FunctionTemplateDecl::Create(S.Context, Class, Loc, ConversionName, TemplateCallOperator->getTemplateParameters(), Conversion); ConversionTemplate->setAccess(AS_public); ConversionTemplate->setImplicit(true); Conversion->setDescribedFunctionTemplate(ConversionTemplate); Class->addDecl(ConversionTemplate); } else Class->addDecl(Conversion); // Add a non-static member function that will be the result of // the conversion with a certain unique ID. DeclarationName InvokerName = &S.Context.Idents.get( getLambdaStaticInvokerName()); // FIXME: Instead of passing in the CallOperator->getTypeSourceInfo() // we should get a prebuilt TrivialTypeSourceInfo from Context // using FunctionTy & Loc and get its TypeLoc as a FunctionProtoTypeLoc // then rewire the parameters accordingly, by hoisting up the InvokeParams // loop below and then use its Params to set Invoke->setParams(...) below. // This would avoid the 'const' qualifier of the calloperator from // contaminating the type of the invoker, which is currently adjusted // in SemaTemplateDeduction.cpp:DeduceTemplateArguments. Fixing the // trailing return type of the invoker would require a visitor to rebuild // the trailing return type and adjusting all back DeclRefExpr's to refer // to the new static invoker parameters - not the call operator's. CXXMethodDecl *Invoke = CXXMethodDecl::Create(S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc), InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static, /*IsInline=*/true, /*IsConstexpr=*/false, CallOperator->getBody()->getLocEnd()); for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) InvokerParams[I]->setOwningFunction(Invoke); Invoke->setParams(InvokerParams); Invoke->setAccess(AS_private); Invoke->setImplicit(true); if (Class->isGenericLambda()) { FunctionTemplateDecl *TemplateCallOperator = CallOperator->getDescribedFunctionTemplate(); FunctionTemplateDecl *StaticInvokerTemplate = FunctionTemplateDecl::Create( S.Context, Class, Loc, InvokerName, TemplateCallOperator->getTemplateParameters(), Invoke); StaticInvokerTemplate->setAccess(AS_private); StaticInvokerTemplate->setImplicit(true); Invoke->setDescribedFunctionTemplate(StaticInvokerTemplate); Class->addDecl(StaticInvokerTemplate); } else Class->addDecl(Invoke); } /// \brief Add a lambda's conversion to block pointer. static void addBlockPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { const FunctionProtoType *Proto = CallOperator->getType()->getAs(); // The function type inside the block pointer type is the same as the call // operator with some tweaks. The calling convention is the default free // function convention, and the type qualifications are lost. FunctionProtoType::ExtProtoInfo BlockEPI = Proto->getExtProtoInfo(); BlockEPI.ExtInfo = BlockEPI.ExtInfo.withCallingConv(S.Context.getDefaultCallingConvention( Proto->isVariadic(), /*IsCXXMethod=*/false)); BlockEPI.TypeQuals = 0; QualType FunctionTy = S.Context.getFunctionType( Proto->getReturnType(), Proto->getParamTypes(), BlockEPI); QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); FunctionProtoType::ExtProtoInfo ConversionEPI( S.Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); ConversionEPI.TypeQuals = Qualifiers::Const; QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI); SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName Name = S.Context.DeclarationNames.getCXXConversionFunctionName( S.Context.getCanonicalType(BlockPtrTy)); DeclarationNameLoc NameLoc; NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc); CXXConversionDecl *Conversion = CXXConversionDecl::Create(S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), /*isInline=*/true, /*isExplicit=*/false, /*isConstexpr=*/false, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); Class->addDecl(Conversion); } static ExprResult performLambdaVarCaptureInitialization( Sema &S, const LambdaScopeInfo::Capture &Capture, FieldDecl *Field) { assert(Capture.isVariableCapture() && "not a variable capture"); auto *Var = Capture.getVariable(); SourceLocation Loc = Capture.getLocation(); // C++11 [expr.prim.lambda]p21: // When the lambda-expression is evaluated, the entities that // are captured by copy are used to direct-initialize each // corresponding non-static data member of the resulting closure // object. (For array members, the array elements are // direct-initialized in increasing subscript order.) These // initializations are performed in the (unspecified) order in // which the non-static data members are declared. // C++ [expr.prim.lambda]p12: // An entity captured by a lambda-expression is odr-used (3.2) in // the scope containing the lambda-expression. ExprResult RefResult = S.BuildDeclarationNameExpr( CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var); if (RefResult.isInvalid()) return ExprError(); Expr *Ref = RefResult.get(); auto Entity = InitializedEntity::InitializeLambdaCapture( Var->getIdentifier(), Field->getType(), Loc); InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); InitializationSequence Init(S, Entity, InitKind, Ref); return Init.Perform(S, Entity, InitKind, Ref); } ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope) { LambdaScopeInfo LSI = *cast(FunctionScopes.back()); ActOnFinishFunctionBody(LSI.CallOperator, Body); return BuildLambdaExpr(StartLoc, Body->getLocEnd(), &LSI); } static LambdaCaptureDefault mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) { switch (ICS) { case CapturingScopeInfo::ImpCap_None: return LCD_None; case CapturingScopeInfo::ImpCap_LambdaByval: return LCD_ByCopy; case CapturingScopeInfo::ImpCap_CapturedRegion: case CapturingScopeInfo::ImpCap_LambdaByref: return LCD_ByRef; case CapturingScopeInfo::ImpCap_Block: llvm_unreachable("block capture in lambda"); } llvm_unreachable("Unknown implicit capture style"); } bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) { if (!From.isVLATypeCapture()) { Expr *Init = From.getInitExpr(); if (Init && Init->HasSideEffects(Context)) return true; } if (!From.isCopyCapture()) return false; const QualType T = From.isThisCapture() ? getCurrentThisType()->getPointeeType() : From.getCaptureType(); if (T.isVolatileQualified()) return true; const Type *BaseT = T->getBaseElementTypeUnsafe(); if (const CXXRecordDecl *RD = BaseT->getAsCXXRecordDecl()) return !RD->isCompleteDefinition() || !RD->hasTrivialCopyConstructor() || !RD->hasTrivialDestructor(); return false; } void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) { if (CaptureHasSideEffects(From)) return; + if (From.isVLATypeCapture()) + return; + auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture); if (From.isThisCapture()) diag << "'this'"; else diag << From.getVariable(); diag << From.isNonODRUsed(); } ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, LambdaScopeInfo *LSI) { // Collect information from the lambda scope. SmallVector Captures; SmallVector CaptureInits; SourceLocation CaptureDefaultLoc = LSI->CaptureDefaultLoc; LambdaCaptureDefault CaptureDefault = mapImplicitCaptureStyle(LSI->ImpCaptureStyle); CXXRecordDecl *Class; CXXMethodDecl *CallOperator; SourceRange IntroducerRange; bool ExplicitParams; bool ExplicitResultType; CleanupInfo LambdaCleanup; bool ContainsUnexpandedParameterPack; bool IsGenericLambda; { CallOperator = LSI->CallOperator; Class = LSI->Lambda; IntroducerRange = LSI->IntroducerRange; ExplicitParams = LSI->ExplicitParams; ExplicitResultType = !LSI->HasImplicitReturnType; LambdaCleanup = LSI->Cleanup; ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack; IsGenericLambda = Class->isGenericLambda(); CallOperator->setLexicalDeclContext(Class); Decl *TemplateOrNonTemplateCallOperatorDecl = CallOperator->getDescribedFunctionTemplate() ? CallOperator->getDescribedFunctionTemplate() : cast(CallOperator); TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class); Class->addDecl(TemplateOrNonTemplateCallOperatorDecl); PopExpressionEvaluationContext(); // Translate captures. auto CurField = Class->field_begin(); for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) { const LambdaScopeInfo::Capture &From = LSI->Captures[I]; assert(!From.isBlockCapture() && "Cannot capture __block variables"); bool IsImplicit = I >= LSI->NumExplicitCaptures; // Warn about unused explicit captures. if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) { // Initialized captures that are non-ODR used may not be eliminated. bool NonODRUsedInitCapture = IsGenericLambda && From.isNonODRUsed() && From.getInitExpr(); if (!NonODRUsedInitCapture) DiagnoseUnusedLambdaCapture(From); } // Handle 'this' capture. if (From.isThisCapture()) { Captures.push_back( LambdaCapture(From.getLocation(), IsImplicit, From.isCopyCapture() ? LCK_StarThis : LCK_This)); CaptureInits.push_back(From.getInitExpr()); continue; } if (From.isVLATypeCapture()) { Captures.push_back( LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType)); CaptureInits.push_back(nullptr); continue; } VarDecl *Var = From.getVariable(); LambdaCaptureKind Kind = From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef; Captures.push_back(LambdaCapture(From.getLocation(), IsImplicit, Kind, Var, From.getEllipsisLoc())); Expr *Init = From.getInitExpr(); if (!Init) { auto InitResult = performLambdaVarCaptureInitialization(*this, From, *CurField); if (InitResult.isInvalid()) return ExprError(); Init = InitResult.get(); } CaptureInits.push_back(Init); } // C++11 [expr.prim.lambda]p6: // The closure type for a lambda-expression with no lambda-capture // has a public non-virtual non-explicit const conversion function // to pointer to function having the same parameter and return // types as the closure type's function call operator. if (Captures.empty() && CaptureDefault == LCD_None) addFunctionPointerConversion(*this, IntroducerRange, Class, CallOperator); // Objective-C++: // The closure type for a lambda-expression has a public non-virtual // non-explicit const conversion function to a block pointer having the // same parameter and return types as the closure type's function call // operator. // FIXME: Fix generic lambda to block conversions. if (getLangOpts().Blocks && getLangOpts().ObjC1 && !IsGenericLambda) addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); // Finalize the lambda class. SmallVector Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), SourceLocation(), nullptr); CheckCompletedCXXClass(Class); } Cleanup.mergeFrom(LambdaCleanup); LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, CaptureDefault, CaptureDefaultLoc, Captures, ExplicitParams, ExplicitResultType, CaptureInits, EndLoc, ContainsUnexpandedParameterPack); // If the lambda expression's call operator is not explicitly marked constexpr // and we are not in a dependent context, analyze the call operator to infer // its constexpr-ness, suppressing diagnostics while doing so. if (getLangOpts().CPlusPlus1z && !CallOperator->isInvalidDecl() && !CallOperator->isConstexpr() && !isa(CallOperator->getBody()) && !Class->getDeclContext()->isDependentContext()) { TentativeAnalysisScope DiagnosticScopeGuard(*this); CallOperator->setConstexpr( CheckConstexprFunctionDecl(CallOperator) && CheckConstexprFunctionBody(CallOperator, CallOperator->getBody())); } // Emit delayed shadowing warnings now that the full capture list is known. DiagnoseShadowingLambdaDecls(LSI); if (!CurContext->isDependentContext()) { switch (ExprEvalContexts.back().Context) { // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand // (Clause 5). case ExpressionEvaluationContext::Unevaluated: case ExpressionEvaluationContext::UnevaluatedList: case ExpressionEvaluationContext::UnevaluatedAbstract: // C++1y [expr.const]p2: // A conditional-expression e is a core constant expression unless the // evaluation of e, following the rules of the abstract machine, would // evaluate [...] a lambda-expression. // // This is technically incorrect, there are some constant evaluated contexts // where this should be allowed. We should probably fix this when DR1607 is // ratified, it lays out the exact set of conditions where we shouldn't // allow a lambda-expression. case ExpressionEvaluationContext::ConstantEvaluated: // We don't actually diagnose this case immediately, because we // could be within a context where we might find out later that // the expression is potentially evaluated (e.g., for typeid). ExprEvalContexts.back().Lambdas.push_back(Lambda); break; case ExpressionEvaluationContext::DiscardedStatement: case ExpressionEvaluationContext::PotentiallyEvaluated: case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed: break; } } return MaybeBindToTemporary(Lambda); } ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, SourceLocation ConvLocation, CXXConversionDecl *Conv, Expr *Src) { // Make sure that the lambda call operator is marked used. CXXRecordDecl *Lambda = Conv->getParent(); CXXMethodDecl *CallOperator = cast( Lambda->lookup( Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); CallOperator->setReferenced(); CallOperator->markUsed(Context); ExprResult Init = PerformCopyInitialization( InitializedEntity::InitializeLambdaToBlock(ConvLocation, Src->getType(), /*NRVO=*/false), CurrentLocation, Src); if (!Init.isInvalid()) Init = ActOnFinishFullExpr(Init.get()); if (Init.isInvalid()) return ExprError(); // Create the new block to be returned. BlockDecl *Block = BlockDecl::Create(Context, CurContext, ConvLocation); // Set the type information. Block->setSignatureAsWritten(CallOperator->getTypeSourceInfo()); Block->setIsVariadic(CallOperator->isVariadic()); Block->setBlockMissingReturnType(false); // Add parameters. SmallVector BlockParams; for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { ParmVarDecl *From = CallOperator->getParamDecl(I); BlockParams.push_back(ParmVarDecl::Create(Context, Block, From->getLocStart(), From->getLocation(), From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), /*DefaultArg=*/nullptr)); } Block->setParams(BlockParams); Block->setIsConversionFromLambda(true); // Add capture. The capture uses a fake variable, which doesn't correspond // to any actual memory location. However, the initializer copy-initializes // the lambda object. TypeSourceInfo *CapVarTSI = Context.getTrivialTypeSourceInfo(Src->getType()); VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation, ConvLocation, nullptr, Src->getType(), CapVarTSI, SC_None); BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false, /*Nested=*/false, /*Copy=*/Init.get()); Block->setCaptures(Context, Capture, /*CapturesCXXThis=*/false); // Add a fake function body to the block. IR generation is responsible // for filling in the actual body, which cannot be expressed as an AST. Block->setBody(new (Context) CompoundStmt(ConvLocation)); // Create the block literal expression. Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType()); ExprCleanupObjects.push_back(Block); Cleanup.setExprNeedsCleanups(true); return BuildBlock; }