1212795Sdim//===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===// 2212795Sdim// 3212795Sdim// The LLVM Compiler Infrastructure 4212795Sdim// 5212795Sdim// This file is distributed under the University of Illinois Open Source 6212795Sdim// License. See LICENSE.TXT for details. 7212795Sdim// 8212795Sdim//===----------------------------------------------------------------------===// 9212795Sdim// 10243830Sdim// This file defines FunctionScopeInfo and its subclasses, which contain 11243830Sdim// information about a single function, block, lambda, or method body. 12212795Sdim// 13212795Sdim//===----------------------------------------------------------------------===// 14212795Sdim 15212795Sdim#ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H 16212795Sdim#define LLVM_CLANG_SEMA_SCOPE_INFO_H 17212795Sdim 18212795Sdim#include "clang/AST/Type.h" 19251662Sdim#include "clang/Basic/CapturedStmt.h" 20219077Sdim#include "clang/Basic/PartialDiagnostic.h" 21263508Sdim#include "clang/Sema/Ownership.h" 22212795Sdim#include "llvm/ADT/DenseMap.h" 23263508Sdim#include "llvm/ADT/SmallSet.h" 24212795Sdim#include "llvm/ADT/SmallVector.h" 25263508Sdim#include <algorithm> 26212795Sdim 27212795Sdimnamespace clang { 28212795Sdim 29243830Sdimclass Decl; 30212795Sdimclass BlockDecl; 31251662Sdimclass CapturedDecl; 32234353Sdimclass CXXMethodDecl; 33263508Sdimclass FieldDecl; 34243830Sdimclass ObjCPropertyDecl; 35212795Sdimclass IdentifierInfo; 36251662Sdimclass ImplicitParamDecl; 37218893Sdimclass LabelDecl; 38212795Sdimclass ReturnStmt; 39212795Sdimclass Scope; 40212795Sdimclass SwitchStmt; 41263508Sdimclass TemplateTypeParmDecl; 42263508Sdimclass TemplateParameterList; 43234353Sdimclass VarDecl; 44243830Sdimclass DeclRefExpr; 45263508Sdimclass MemberExpr; 46243830Sdimclass ObjCIvarRefExpr; 47243830Sdimclass ObjCPropertyRefExpr; 48243830Sdimclass ObjCMessageExpr; 49212795Sdim 50212795Sdimnamespace sema { 51212795Sdim 52234353Sdim/// \brief Contains information about the compound statement currently being 53234353Sdim/// parsed. 54234353Sdimclass CompoundScopeInfo { 55234353Sdimpublic: 56234353Sdim CompoundScopeInfo() 57234353Sdim : HasEmptyLoopBodies(false) { } 58234353Sdim 59234353Sdim /// \brief Whether this compound stamement contains `for' or `while' loops 60234353Sdim /// with empty bodies. 61234353Sdim bool HasEmptyLoopBodies; 62234353Sdim 63234353Sdim void setHasEmptyLoopBodies() { 64234353Sdim HasEmptyLoopBodies = true; 65234353Sdim } 66234353Sdim}; 67234353Sdim 68219077Sdimclass PossiblyUnreachableDiag { 69219077Sdimpublic: 70219077Sdim PartialDiagnostic PD; 71219077Sdim SourceLocation Loc; 72219077Sdim const Stmt *stmt; 73219077Sdim 74219077Sdim PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, 75219077Sdim const Stmt *stmt) 76219077Sdim : PD(PD), Loc(Loc), stmt(stmt) {} 77219077Sdim}; 78219077Sdim 79212795Sdim/// \brief Retains information about a function, method, or block that is 80212795Sdim/// currently being parsed. 81212795Sdimclass FunctionScopeInfo { 82234353Sdimprotected: 83234353Sdim enum ScopeKind { 84234353Sdim SK_Function, 85234353Sdim SK_Block, 86251662Sdim SK_Lambda, 87251662Sdim SK_CapturedRegion 88234353Sdim }; 89234353Sdim 90212795Sdimpublic: 91234353Sdim /// \brief What kind of scope we are describing. 92234353Sdim /// 93234353Sdim ScopeKind Kind; 94212795Sdim 95239462Sdim /// \brief Whether this function contains a VLA, \@try, try, C++ 96212795Sdim /// initializer, or anything else that can't be jumped past. 97212795Sdim bool HasBranchProtectedScope; 98212795Sdim 99212795Sdim /// \brief Whether this function contains any switches or direct gotos. 100212795Sdim bool HasBranchIntoScope; 101212795Sdim 102212795Sdim /// \brief Whether this function contains any indirect gotos. 103212795Sdim bool HasIndirectGoto; 104212795Sdim 105249423Sdim /// \brief Whether a statement was dropped because it was invalid. 106249423Sdim bool HasDroppedStmt; 107249423Sdim 108243830Sdim /// A flag that is set when parsing a method that must call super's 109243830Sdim /// implementation, such as \c -dealloc, \c -finalize, or any method marked 110243830Sdim /// with \c __attribute__((objc_requires_super)). 111243830Sdim bool ObjCShouldCallSuper; 112239462Sdim 113218893Sdim /// \brief Used to determine if errors occurred in this function or block. 114218893Sdim DiagnosticErrorTrap ErrorTrap; 115212795Sdim 116212795Sdim /// SwitchStack - This is the current set of active switch statements in the 117212795Sdim /// block. 118226633Sdim SmallVector<SwitchStmt*, 8> SwitchStack; 119212795Sdim 120212795Sdim /// \brief The list of return statements that occur within the function or 121212795Sdim /// block, if there is any chance of applying the named return value 122239462Sdim /// optimization, or if we need to infer a return type. 123226633Sdim SmallVector<ReturnStmt*, 4> Returns; 124234353Sdim 125234353Sdim /// \brief The stack of currently active compound stamement scopes in the 126234353Sdim /// function. 127234353Sdim SmallVector<CompoundScopeInfo, 4> CompoundScopes; 128234353Sdim 129219077Sdim /// \brief A list of PartialDiagnostics created but delayed within the 130219077Sdim /// current function scope. These diagnostics are vetted for reachability 131219077Sdim /// prior to being emitted. 132226633Sdim SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; 133212795Sdim 134243830Sdimpublic: 135243830Sdim /// Represents a simple identification of a weak object. 136243830Sdim /// 137243830Sdim /// Part of the implementation of -Wrepeated-use-of-weak. 138243830Sdim /// 139243830Sdim /// This is used to determine if two weak accesses refer to the same object. 140243830Sdim /// Here are some examples of how various accesses are "profiled": 141243830Sdim /// 142243830Sdim /// Access Expression | "Base" Decl | "Property" Decl 143243830Sdim /// :---------------: | :-----------------: | :------------------------------: 144243830Sdim /// self.property | self (VarDecl) | property (ObjCPropertyDecl) 145243830Sdim /// self.implicitProp | self (VarDecl) | -implicitProp (ObjCMethodDecl) 146243830Sdim /// self->ivar.prop | ivar (ObjCIvarDecl) | prop (ObjCPropertyDecl) 147243830Sdim /// cxxObj.obj.prop | obj (FieldDecl) | prop (ObjCPropertyDecl) 148243830Sdim /// [self foo].prop | 0 (unknown) | prop (ObjCPropertyDecl) 149243830Sdim /// self.prop1.prop2 | prop1 (ObjCPropertyDecl) | prop2 (ObjCPropertyDecl) 150243830Sdim /// MyClass.prop | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl) 151243830Sdim /// weakVar | 0 (known) | weakVar (VarDecl) 152243830Sdim /// self->weakIvar | self (VarDecl) | weakIvar (ObjCIvarDecl) 153243830Sdim /// 154243830Sdim /// Objects are identified with only two Decls to make it reasonably fast to 155243830Sdim /// compare them. 156243830Sdim class WeakObjectProfileTy { 157243830Sdim /// The base object decl, as described in the class documentation. 158243830Sdim /// 159243830Sdim /// The extra flag is "true" if the Base and Property are enough to uniquely 160243830Sdim /// identify the object in memory. 161243830Sdim /// 162243830Sdim /// \sa isExactProfile() 163243830Sdim typedef llvm::PointerIntPair<const NamedDecl *, 1, bool> BaseInfoTy; 164243830Sdim BaseInfoTy Base; 165243830Sdim 166243830Sdim /// The "property" decl, as described in the class documentation. 167243830Sdim /// 168243830Sdim /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the 169243830Sdim /// case of "implicit" properties (regular methods accessed via dot syntax). 170243830Sdim const NamedDecl *Property; 171243830Sdim 172243830Sdim /// Used to find the proper base profile for a given base expression. 173243830Sdim static BaseInfoTy getBaseInfo(const Expr *BaseE); 174243830Sdim 175243830Sdim // For use in DenseMap. 176243830Sdim friend class DenseMapInfo; 177243830Sdim inline WeakObjectProfileTy(); 178243830Sdim static inline WeakObjectProfileTy getSentinel(); 179243830Sdim 180243830Sdim public: 181243830Sdim WeakObjectProfileTy(const ObjCPropertyRefExpr *RE); 182243830Sdim WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property); 183243830Sdim WeakObjectProfileTy(const DeclRefExpr *RE); 184243830Sdim WeakObjectProfileTy(const ObjCIvarRefExpr *RE); 185243830Sdim 186243830Sdim const NamedDecl *getBase() const { return Base.getPointer(); } 187243830Sdim const NamedDecl *getProperty() const { return Property; } 188243830Sdim 189243830Sdim /// Returns true if the object base specifies a known object in memory, 190243830Sdim /// rather than, say, an instance variable or property of another object. 191243830Sdim /// 192243830Sdim /// Note that this ignores the effects of aliasing; that is, \c foo.bar is 193243830Sdim /// considered an exact profile if \c foo is a local variable, even if 194243830Sdim /// another variable \c foo2 refers to the same object as \c foo. 195243830Sdim /// 196243830Sdim /// For increased precision, accesses with base variables that are 197243830Sdim /// properties or ivars of 'self' (e.g. self.prop1.prop2) are considered to 198243830Sdim /// be exact, though this is not true for arbitrary variables 199243830Sdim /// (foo.prop1.prop2). 200243830Sdim bool isExactProfile() const { 201243830Sdim return Base.getInt(); 202243830Sdim } 203243830Sdim 204243830Sdim bool operator==(const WeakObjectProfileTy &Other) const { 205243830Sdim return Base == Other.Base && Property == Other.Property; 206243830Sdim } 207243830Sdim 208243830Sdim // For use in DenseMap. 209243830Sdim // We can't specialize the usual llvm::DenseMapInfo at the end of the file 210243830Sdim // because by that point the DenseMap in FunctionScopeInfo has already been 211243830Sdim // instantiated. 212243830Sdim class DenseMapInfo { 213243830Sdim public: 214243830Sdim static inline WeakObjectProfileTy getEmptyKey() { 215243830Sdim return WeakObjectProfileTy(); 216243830Sdim } 217243830Sdim static inline WeakObjectProfileTy getTombstoneKey() { 218243830Sdim return WeakObjectProfileTy::getSentinel(); 219243830Sdim } 220243830Sdim 221243830Sdim static unsigned getHashValue(const WeakObjectProfileTy &Val) { 222243830Sdim typedef std::pair<BaseInfoTy, const NamedDecl *> Pair; 223243830Sdim return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base, 224243830Sdim Val.Property)); 225243830Sdim } 226243830Sdim 227243830Sdim static bool isEqual(const WeakObjectProfileTy &LHS, 228243830Sdim const WeakObjectProfileTy &RHS) { 229243830Sdim return LHS == RHS; 230243830Sdim } 231243830Sdim }; 232243830Sdim }; 233243830Sdim 234243830Sdim /// Represents a single use of a weak object. 235243830Sdim /// 236243830Sdim /// Stores both the expression and whether the access is potentially unsafe 237243830Sdim /// (i.e. it could potentially be warned about). 238243830Sdim /// 239243830Sdim /// Part of the implementation of -Wrepeated-use-of-weak. 240243830Sdim class WeakUseTy { 241243830Sdim llvm::PointerIntPair<const Expr *, 1, bool> Rep; 242243830Sdim public: 243243830Sdim WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {} 244243830Sdim 245243830Sdim const Expr *getUseExpr() const { return Rep.getPointer(); } 246243830Sdim bool isUnsafe() const { return Rep.getInt(); } 247243830Sdim void markSafe() { Rep.setInt(false); } 248243830Sdim 249243830Sdim bool operator==(const WeakUseTy &Other) const { 250243830Sdim return Rep == Other.Rep; 251243830Sdim } 252243830Sdim }; 253243830Sdim 254243830Sdim /// Used to collect uses of a particular weak object in a function body. 255243830Sdim /// 256243830Sdim /// Part of the implementation of -Wrepeated-use-of-weak. 257243830Sdim typedef SmallVector<WeakUseTy, 4> WeakUseVector; 258243830Sdim 259243830Sdim /// Used to collect all uses of weak objects in a function body. 260243830Sdim /// 261243830Sdim /// Part of the implementation of -Wrepeated-use-of-weak. 262243830Sdim typedef llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8, 263243830Sdim WeakObjectProfileTy::DenseMapInfo> 264243830Sdim WeakObjectUseMap; 265243830Sdim 266243830Sdimprivate: 267243830Sdim /// Used to collect all uses of weak objects in this function body. 268243830Sdim /// 269243830Sdim /// Part of the implementation of -Wrepeated-use-of-weak. 270243830Sdim WeakObjectUseMap WeakObjectUses; 271243830Sdim 272243830Sdimpublic: 273243830Sdim /// Record that a weak object was accessed. 274243830Sdim /// 275243830Sdim /// Part of the implementation of -Wrepeated-use-of-weak. 276243830Sdim template <typename ExprT> 277243830Sdim inline void recordUseOfWeak(const ExprT *E, bool IsRead = true); 278243830Sdim 279243830Sdim void recordUseOfWeak(const ObjCMessageExpr *Msg, 280243830Sdim const ObjCPropertyDecl *Prop); 281243830Sdim 282243830Sdim /// Record that a given expression is a "safe" access of a weak object (e.g. 283243830Sdim /// assigning it to a strong variable.) 284243830Sdim /// 285243830Sdim /// Part of the implementation of -Wrepeated-use-of-weak. 286243830Sdim void markSafeWeakUse(const Expr *E); 287243830Sdim 288243830Sdim const WeakObjectUseMap &getWeakObjectUses() const { 289243830Sdim return WeakObjectUses; 290243830Sdim } 291243830Sdim 292212795Sdim void setHasBranchIntoScope() { 293212795Sdim HasBranchIntoScope = true; 294212795Sdim } 295212795Sdim 296212795Sdim void setHasBranchProtectedScope() { 297212795Sdim HasBranchProtectedScope = true; 298212795Sdim } 299212795Sdim 300212795Sdim void setHasIndirectGoto() { 301212795Sdim HasIndirectGoto = true; 302212795Sdim } 303212795Sdim 304249423Sdim void setHasDroppedStmt() { 305249423Sdim HasDroppedStmt = true; 306249423Sdim } 307249423Sdim 308212795Sdim bool NeedsScopeChecking() const { 309249423Sdim return !HasDroppedStmt && 310249423Sdim (HasIndirectGoto || 311249423Sdim (HasBranchProtectedScope && HasBranchIntoScope)); 312212795Sdim } 313212795Sdim 314226633Sdim FunctionScopeInfo(DiagnosticsEngine &Diag) 315234353Sdim : Kind(SK_Function), 316212795Sdim HasBranchProtectedScope(false), 317212795Sdim HasBranchIntoScope(false), 318212795Sdim HasIndirectGoto(false), 319249423Sdim HasDroppedStmt(false), 320243830Sdim ObjCShouldCallSuper(false), 321218893Sdim ErrorTrap(Diag) { } 322212795Sdim 323212795Sdim virtual ~FunctionScopeInfo(); 324212795Sdim 325212795Sdim /// \brief Clear out the information in this function scope, making it 326212795Sdim /// suitable for reuse. 327218893Sdim void Clear(); 328212795Sdim}; 329212795Sdim 330234353Sdimclass CapturingScopeInfo : public FunctionScopeInfo { 331234353Sdimpublic: 332234353Sdim enum ImplicitCaptureStyle { 333251662Sdim ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block, 334251662Sdim ImpCap_CapturedRegion 335234353Sdim }; 336234353Sdim 337234353Sdim ImplicitCaptureStyle ImpCaptureStyle; 338234353Sdim 339234353Sdim class Capture { 340263508Sdim // There are three categories of capture: capturing 'this', capturing 341263508Sdim // local variables, and C++1y initialized captures (which can have an 342263508Sdim // arbitrary initializer, and don't really capture in the traditional 343263508Sdim // sense at all). 344263508Sdim // 345263508Sdim // There are three ways to capture a local variable: 346263508Sdim // - capture by copy in the C++11 sense, 347263508Sdim // - capture by reference in the C++11 sense, and 348263508Sdim // - __block capture. 349263508Sdim // Lambdas explicitly specify capture by copy or capture by reference. 350263508Sdim // For blocks, __block capture applies to variables with that annotation, 351263508Sdim // variables of reference type are captured by reference, and other 352263508Sdim // variables are captured by copy. 353234353Sdim enum CaptureKind { 354263508Sdim Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_This 355234353Sdim }; 356234353Sdim 357263508Sdim /// The variable being captured (if we are not capturing 'this') and whether 358263508Sdim /// this is a nested capture. 359263508Sdim llvm::PointerIntPair<VarDecl*, 1, bool> VarAndNested; 360234353Sdim 361263508Sdim /// Expression to initialize a field of the given type, and the kind of 362263508Sdim /// capture (if this is a capture and not an init-capture). The expression 363263508Sdim /// is only required if we are capturing ByVal and the variable's type has 364263508Sdim /// a non-trivial copy constructor. 365263508Sdim llvm::PointerIntPair<Expr*, 2, CaptureKind> InitExprAndCaptureKind; 366234353Sdim 367263508Sdim /// \brief The source location at which the first capture occurred. 368234353Sdim SourceLocation Loc; 369263508Sdim 370234353Sdim /// \brief The location of the ellipsis that expands a parameter pack. 371234353Sdim SourceLocation EllipsisLoc; 372263508Sdim 373234353Sdim /// \brief The type as it was captured, which is in effect the type of the 374234353Sdim /// non-static data member that would hold the capture. 375234353Sdim QualType CaptureType; 376263508Sdim 377234353Sdim public: 378263508Sdim Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, 379263508Sdim SourceLocation Loc, SourceLocation EllipsisLoc, 380234353Sdim QualType CaptureType, Expr *Cpy) 381263508Sdim : VarAndNested(Var, IsNested), 382263508Sdim InitExprAndCaptureKind(Cpy, Block ? Cap_Block : 383263508Sdim ByRef ? Cap_ByRef : Cap_ByCopy), 384263508Sdim Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {} 385234353Sdim 386234353Sdim enum IsThisCapture { ThisCapture }; 387263508Sdim Capture(IsThisCapture, bool IsNested, SourceLocation Loc, 388234353Sdim QualType CaptureType, Expr *Cpy) 389263508Sdim : VarAndNested(0, IsNested), 390263508Sdim InitExprAndCaptureKind(Cpy, Cap_This), 391263508Sdim Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {} 392234353Sdim 393263508Sdim bool isThisCapture() const { 394263508Sdim return InitExprAndCaptureKind.getInt() == Cap_This; 395263508Sdim } 396263508Sdim bool isVariableCapture() const { 397263508Sdim return InitExprAndCaptureKind.getInt() != Cap_This; 398263508Sdim } 399263508Sdim bool isCopyCapture() const { 400263508Sdim return InitExprAndCaptureKind.getInt() == Cap_ByCopy; 401263508Sdim } 402263508Sdim bool isReferenceCapture() const { 403263508Sdim return InitExprAndCaptureKind.getInt() == Cap_ByRef; 404263508Sdim } 405263508Sdim bool isBlockCapture() const { 406263508Sdim return InitExprAndCaptureKind.getInt() == Cap_Block; 407263508Sdim } 408263508Sdim bool isNested() { return VarAndNested.getInt(); } 409234353Sdim 410234353Sdim VarDecl *getVariable() const { 411263508Sdim return VarAndNested.getPointer(); 412234353Sdim } 413234353Sdim 414234353Sdim /// \brief Retrieve the location at which this variable was captured. 415234353Sdim SourceLocation getLocation() const { return Loc; } 416234353Sdim 417234353Sdim /// \brief Retrieve the source location of the ellipsis, whose presence 418234353Sdim /// indicates that the capture is a pack expansion. 419234353Sdim SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 420234353Sdim 421234353Sdim /// \brief Retrieve the capture type for this capture, which is effectively 422234353Sdim /// the type of the non-static data member in the lambda/block structure 423234353Sdim /// that would store this capture. 424234353Sdim QualType getCaptureType() const { return CaptureType; } 425234353Sdim 426263508Sdim Expr *getInitExpr() const { 427263508Sdim return InitExprAndCaptureKind.getPointer(); 428234353Sdim } 429234353Sdim }; 430234353Sdim 431234353Sdim CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) 432234353Sdim : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0), 433234353Sdim HasImplicitReturnType(false) 434234353Sdim {} 435234353Sdim 436234353Sdim /// CaptureMap - A map of captured variables to (index+1) into Captures. 437234353Sdim llvm::DenseMap<VarDecl*, unsigned> CaptureMap; 438234353Sdim 439234353Sdim /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; 440234353Sdim /// zero if 'this' is not captured. 441234353Sdim unsigned CXXThisCaptureIndex; 442234353Sdim 443234353Sdim /// Captures - The captures. 444234353Sdim SmallVector<Capture, 4> Captures; 445234353Sdim 446234353Sdim /// \brief - Whether the target type of return statements in this context 447234353Sdim /// is deduced (e.g. a lambda or block with omitted return type). 448234353Sdim bool HasImplicitReturnType; 449234353Sdim 450234353Sdim /// ReturnType - The target type of return statements in this context, 451234353Sdim /// or null if unknown. 452234353Sdim QualType ReturnType; 453234353Sdim 454234353Sdim void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested, 455234353Sdim SourceLocation Loc, SourceLocation EllipsisLoc, 456234353Sdim QualType CaptureType, Expr *Cpy) { 457234353Sdim Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, 458234353Sdim EllipsisLoc, CaptureType, Cpy)); 459234353Sdim CaptureMap[Var] = Captures.size(); 460234353Sdim } 461234353Sdim 462234353Sdim void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType, 463243830Sdim Expr *Cpy); 464234353Sdim 465234353Sdim /// \brief Determine whether the C++ 'this' is captured. 466234353Sdim bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } 467234353Sdim 468234353Sdim /// \brief Retrieve the capture of C++ 'this', if it has been captured. 469234353Sdim Capture &getCXXThisCapture() { 470234353Sdim assert(isCXXThisCaptured() && "this has not been captured"); 471234353Sdim return Captures[CXXThisCaptureIndex - 1]; 472234353Sdim } 473234353Sdim 474234353Sdim /// \brief Determine whether the given variable has been captured. 475234353Sdim bool isCaptured(VarDecl *Var) const { 476234353Sdim return CaptureMap.count(Var); 477234353Sdim } 478234353Sdim 479234353Sdim /// \brief Retrieve the capture of the given variable, if it has been 480234353Sdim /// captured already. 481234353Sdim Capture &getCapture(VarDecl *Var) { 482234353Sdim assert(isCaptured(Var) && "Variable has not been captured"); 483234353Sdim return Captures[CaptureMap[Var] - 1]; 484234353Sdim } 485234353Sdim 486234353Sdim const Capture &getCapture(VarDecl *Var) const { 487234353Sdim llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known 488234353Sdim = CaptureMap.find(Var); 489234353Sdim assert(Known != CaptureMap.end() && "Variable has not been captured"); 490234353Sdim return Captures[Known->second - 1]; 491234353Sdim } 492234353Sdim 493234353Sdim static bool classof(const FunctionScopeInfo *FSI) { 494251662Sdim return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda 495251662Sdim || FSI->Kind == SK_CapturedRegion; 496234353Sdim } 497234353Sdim}; 498234353Sdim 499212795Sdim/// \brief Retains information about a block that is currently being parsed. 500234353Sdimclass BlockScopeInfo : public CapturingScopeInfo { 501212795Sdimpublic: 502212795Sdim BlockDecl *TheDecl; 503212795Sdim 504212795Sdim /// TheScope - This is the scope for the block itself, which contains 505212795Sdim /// arguments etc. 506212795Sdim Scope *TheScope; 507212795Sdim 508212795Sdim /// BlockType - The function type of the block, if one was given. 509212795Sdim /// Its return type may be BuiltinType::Dependent. 510212795Sdim QualType FunctionType; 511212795Sdim 512226633Sdim BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) 513234353Sdim : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), 514234353Sdim TheScope(BlockScope) 515212795Sdim { 516234353Sdim Kind = SK_Block; 517212795Sdim } 518212795Sdim 519212795Sdim virtual ~BlockScopeInfo(); 520212795Sdim 521234353Sdim static bool classof(const FunctionScopeInfo *FSI) { 522234353Sdim return FSI->Kind == SK_Block; 523234353Sdim } 524212795Sdim}; 525212795Sdim 526251662Sdim/// \brief Retains information about a captured region. 527251662Sdimclass CapturedRegionScopeInfo: public CapturingScopeInfo { 528251662Sdimpublic: 529251662Sdim /// \brief The CapturedDecl for this statement. 530251662Sdim CapturedDecl *TheCapturedDecl; 531251662Sdim /// \brief The captured record type. 532251662Sdim RecordDecl *TheRecordDecl; 533251662Sdim /// \brief This is the enclosing scope of the captured region. 534251662Sdim Scope *TheScope; 535251662Sdim /// \brief The implicit parameter for the captured variables. 536251662Sdim ImplicitParamDecl *ContextParam; 537251662Sdim /// \brief The kind of captured region. 538251662Sdim CapturedRegionKind CapRegionKind; 539251662Sdim 540251662Sdim CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD, 541251662Sdim RecordDecl *RD, ImplicitParamDecl *Context, 542251662Sdim CapturedRegionKind K) 543251662Sdim : CapturingScopeInfo(Diag, ImpCap_CapturedRegion), 544251662Sdim TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S), 545251662Sdim ContextParam(Context), CapRegionKind(K) 546251662Sdim { 547251662Sdim Kind = SK_CapturedRegion; 548251662Sdim } 549251662Sdim 550251662Sdim virtual ~CapturedRegionScopeInfo(); 551251662Sdim 552251662Sdim /// \brief A descriptive name for the kind of captured region this is. 553251662Sdim StringRef getRegionName() const { 554251662Sdim switch (CapRegionKind) { 555251662Sdim case CR_Default: 556251662Sdim return "default captured statement"; 557263508Sdim case CR_OpenMP: 558263508Sdim return "OpenMP region"; 559251662Sdim } 560251662Sdim llvm_unreachable("Invalid captured region kind!"); 561251662Sdim } 562251662Sdim 563251662Sdim static bool classof(const FunctionScopeInfo *FSI) { 564251662Sdim return FSI->Kind == SK_CapturedRegion; 565251662Sdim } 566251662Sdim}; 567251662Sdim 568234353Sdimclass LambdaScopeInfo : public CapturingScopeInfo { 569234353Sdimpublic: 570234353Sdim /// \brief The class that describes the lambda. 571234353Sdim CXXRecordDecl *Lambda; 572234353Sdim 573263508Sdim /// \brief The lambda's compiler-generated \c operator(). 574234353Sdim CXXMethodDecl *CallOperator; 575234353Sdim 576234353Sdim /// \brief Source range covering the lambda introducer [...]. 577234353Sdim SourceRange IntroducerRange; 578234353Sdim 579263508Sdim /// \brief Source location of the '&' or '=' specifying the default capture 580263508Sdim /// type, if any. 581263508Sdim SourceLocation CaptureDefaultLoc; 582263508Sdim 583263508Sdim /// \brief The number of captures in the \c Captures list that are 584234353Sdim /// explicit captures. 585234353Sdim unsigned NumExplicitCaptures; 586234353Sdim 587234353Sdim /// \brief Whether this is a mutable lambda. 588234353Sdim bool Mutable; 589263508Sdim 590234353Sdim /// \brief Whether the (empty) parameter list is explicit. 591234353Sdim bool ExplicitParams; 592234353Sdim 593234353Sdim /// \brief Whether any of the capture expressions requires cleanups. 594234353Sdim bool ExprNeedsCleanups; 595234353Sdim 596239462Sdim /// \brief Whether the lambda contains an unexpanded parameter pack. 597239462Sdim bool ContainsUnexpandedParameterPack; 598239462Sdim 599234353Sdim /// \brief Variables used to index into by-copy array captures. 600249423Sdim SmallVector<VarDecl *, 4> ArrayIndexVars; 601234353Sdim 602234353Sdim /// \brief Offsets into the ArrayIndexVars array at which each capture starts 603234353Sdim /// its list of array index variables. 604249423Sdim SmallVector<unsigned, 4> ArrayIndexStarts; 605234353Sdim 606263508Sdim /// \brief If this is a generic lambda, use this as the depth of 607263508Sdim /// each 'auto' parameter, during initial AST construction. 608263508Sdim unsigned AutoTemplateParameterDepth; 609263508Sdim 610263508Sdim /// \brief Store the list of the auto parameters for a generic lambda. 611263508Sdim /// If this is a generic lambda, store the list of the auto 612263508Sdim /// parameters converted into TemplateTypeParmDecls into a vector 613263508Sdim /// that can be used to construct the generic lambda's template 614263508Sdim /// parameter list, during initial AST construction. 615263508Sdim SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams; 616263508Sdim 617263508Sdim /// If this is a generic lambda, and the template parameter 618263508Sdim /// list has been created (from the AutoTemplateParams) then 619263508Sdim /// store a reference to it (cache it to avoid reconstructing it). 620263508Sdim TemplateParameterList *GLTemplateParameterList; 621263508Sdim 622263508Sdim /// \brief Contains all variable-referring-expressions (i.e. DeclRefExprs 623263508Sdim /// or MemberExprs) that refer to local variables in a generic lambda 624263508Sdim /// or a lambda in a potentially-evaluated-if-used context. 625263508Sdim /// 626263508Sdim /// Potentially capturable variables of a nested lambda that might need 627263508Sdim /// to be captured by the lambda are housed here. 628263508Sdim /// This is specifically useful for generic lambdas or 629263508Sdim /// lambdas within a a potentially evaluated-if-used context. 630263508Sdim /// If an enclosing variable is named in an expression of a lambda nested 631263508Sdim /// within a generic lambda, we don't always know know whether the variable 632263508Sdim /// will truly be odr-used (i.e. need to be captured) by that nested lambda, 633263508Sdim /// until its instantiation. But we still need to capture it in the 634263508Sdim /// enclosing lambda if all intervening lambdas can capture the variable. 635263508Sdim 636263508Sdim llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs; 637263508Sdim 638263508Sdim /// \brief Contains all variable-referring-expressions that refer 639263508Sdim /// to local variables that are usable as constant expressions and 640263508Sdim /// do not involve an odr-use (they may still need to be captured 641263508Sdim /// if the enclosing full-expression is instantiation dependent). 642263508Sdim llvm::SmallSet<Expr*, 8> NonODRUsedCapturingExprs; 643263508Sdim 644263508Sdim SourceLocation PotentialThisCaptureLocation; 645263508Sdim 646263508Sdim LambdaScopeInfo(DiagnosticsEngine &Diag) 647263508Sdim : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0), 648263508Sdim CallOperator(0), NumExplicitCaptures(0), Mutable(false), 649263508Sdim ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false), 650263508Sdim AutoTemplateParameterDepth(0), GLTemplateParameterList(0) 651234353Sdim { 652234353Sdim Kind = SK_Lambda; 653234353Sdim } 654234353Sdim 655234353Sdim virtual ~LambdaScopeInfo(); 656234353Sdim 657263508Sdim /// \brief Note when all explicit captures have been added. 658234353Sdim void finishedExplicitCaptures() { 659234353Sdim NumExplicitCaptures = Captures.size(); 660234353Sdim } 661243830Sdim 662243830Sdim static bool classof(const FunctionScopeInfo *FSI) { 663263508Sdim return FSI->Kind == SK_Lambda; 664234353Sdim } 665263508Sdim 666263508Sdim /// 667263508Sdim /// \brief Add a variable that might potentially be captured by the 668263508Sdim /// lambda and therefore the enclosing lambdas. 669263508Sdim /// 670263508Sdim /// This is also used by enclosing lambda's to speculatively capture 671263508Sdim /// variables that nested lambda's - depending on their enclosing 672263508Sdim /// specialization - might need to capture. 673263508Sdim /// Consider: 674263508Sdim /// void f(int, int); <-- don't capture 675263508Sdim /// void f(const int&, double); <-- capture 676263508Sdim /// void foo() { 677263508Sdim /// const int x = 10; 678263508Sdim /// auto L = [=](auto a) { // capture 'x' 679263508Sdim /// return [=](auto b) { 680263508Sdim /// f(x, a); // we may or may not need to capture 'x' 681263508Sdim /// }; 682263508Sdim /// }; 683263508Sdim /// } 684263508Sdim void addPotentialCapture(Expr *VarExpr) { 685263508Sdim assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr)); 686263508Sdim PotentiallyCapturingExprs.push_back(VarExpr); 687263508Sdim } 688263508Sdim 689263508Sdim void addPotentialThisCapture(SourceLocation Loc) { 690263508Sdim PotentialThisCaptureLocation = Loc; 691263508Sdim } 692263508Sdim bool hasPotentialThisCapture() const { 693263508Sdim return PotentialThisCaptureLocation.isValid(); 694263508Sdim } 695263508Sdim 696263508Sdim /// \brief Mark a variable's reference in a lambda as non-odr using. 697263508Sdim /// 698263508Sdim /// For generic lambdas, if a variable is named in a potentially evaluated 699263508Sdim /// expression, where the enclosing full expression is dependent then we 700263508Sdim /// must capture the variable (given a default capture). 701263508Sdim /// This is accomplished by recording all references to variables 702263508Sdim /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of 703263508Sdim /// PotentialCaptures. All such variables have to be captured by that lambda, 704263508Sdim /// except for as described below. 705263508Sdim /// If that variable is usable as a constant expression and is named in a 706263508Sdim /// manner that does not involve its odr-use (e.g. undergoes 707263508Sdim /// lvalue-to-rvalue conversion, or discarded) record that it is so. Upon the 708263508Sdim /// act of analyzing the enclosing full expression (ActOnFinishFullExpr) 709263508Sdim /// if we can determine that the full expression is not instantiation- 710263508Sdim /// dependent, then we can entirely avoid its capture. 711263508Sdim /// 712263508Sdim /// const int n = 0; 713263508Sdim /// [&] (auto x) { 714263508Sdim /// (void)+n + x; 715263508Sdim /// }; 716263508Sdim /// Interestingly, this strategy would involve a capture of n, even though 717263508Sdim /// it's obviously not odr-used here, because the full-expression is 718263508Sdim /// instantiation-dependent. It could be useful to avoid capturing such 719263508Sdim /// variables, even when they are referred to in an instantiation-dependent 720263508Sdim /// expression, if we can unambiguously determine that they shall never be 721263508Sdim /// odr-used. This would involve removal of the variable-referring-expression 722263508Sdim /// from the array of PotentialCaptures during the lvalue-to-rvalue 723263508Sdim /// conversions. But per the working draft N3797, (post-chicago 2013) we must 724263508Sdim /// capture such variables. 725263508Sdim /// Before anyone is tempted to implement a strategy for not-capturing 'n', 726263508Sdim /// consider the insightful warning in: 727263508Sdim /// /cfe-commits/Week-of-Mon-20131104/092596.html 728263508Sdim /// "The problem is that the set of captures for a lambda is part of the ABI 729263508Sdim /// (since lambda layout can be made visible through inline functions and the 730263508Sdim /// like), and there are no guarantees as to which cases we'll manage to build 731263508Sdim /// an lvalue-to-rvalue conversion in, when parsing a template -- some 732263508Sdim /// seemingly harmless change elsewhere in Sema could cause us to start or stop 733263508Sdim /// building such a node. So we need a rule that anyone can implement and get 734263508Sdim /// exactly the same result". 735263508Sdim /// 736263508Sdim void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) { 737263508Sdim assert(isa<DeclRefExpr>(CapturingVarExpr) 738263508Sdim || isa<MemberExpr>(CapturingVarExpr)); 739263508Sdim NonODRUsedCapturingExprs.insert(CapturingVarExpr); 740263508Sdim } 741263508Sdim bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) { 742263508Sdim assert(isa<DeclRefExpr>(CapturingVarExpr) 743263508Sdim || isa<MemberExpr>(CapturingVarExpr)); 744263508Sdim return NonODRUsedCapturingExprs.count(CapturingVarExpr); 745263508Sdim } 746263508Sdim void removePotentialCapture(Expr *E) { 747263508Sdim PotentiallyCapturingExprs.erase( 748263508Sdim std::remove(PotentiallyCapturingExprs.begin(), 749263508Sdim PotentiallyCapturingExprs.end(), E), 750263508Sdim PotentiallyCapturingExprs.end()); 751263508Sdim } 752263508Sdim void clearPotentialCaptures() { 753263508Sdim PotentiallyCapturingExprs.clear(); 754263508Sdim PotentialThisCaptureLocation = SourceLocation(); 755263508Sdim } 756263508Sdim unsigned getNumPotentialVariableCaptures() const { 757263508Sdim return PotentiallyCapturingExprs.size(); 758263508Sdim } 759263508Sdim 760263508Sdim bool hasPotentialCaptures() const { 761263508Sdim return getNumPotentialVariableCaptures() || 762263508Sdim PotentialThisCaptureLocation.isValid(); 763263508Sdim } 764263508Sdim 765263508Sdim // When passed the index, returns the VarDecl and Expr associated 766263508Sdim // with the index. 767263508Sdim void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E); 768263508Sdim 769234353Sdim}; 770234353Sdim 771243830Sdim 772243830SdimFunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy() 773243830Sdim : Base(0, false), Property(0) {} 774243830Sdim 775243830SdimFunctionScopeInfo::WeakObjectProfileTy 776243830SdimFunctionScopeInfo::WeakObjectProfileTy::getSentinel() { 777243830Sdim FunctionScopeInfo::WeakObjectProfileTy Result; 778243830Sdim Result.Base.setInt(true); 779243830Sdim return Result; 780212795Sdim} 781243830Sdim 782243830Sdimtemplate <typename ExprT> 783243830Sdimvoid FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { 784243830Sdim assert(E); 785243830Sdim WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)]; 786243830Sdim Uses.push_back(WeakUseTy(E, IsRead)); 787212795Sdim} 788212795Sdim 789243830Sdiminline void 790243830SdimCapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc, 791243830Sdim QualType CaptureType, Expr *Cpy) { 792243830Sdim Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, 793243830Sdim Cpy)); 794243830Sdim CXXThisCaptureIndex = Captures.size(); 795243830Sdim 796243830Sdim if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(this)) 797243830Sdim LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size()); 798243830Sdim} 799243830Sdim 800243830Sdim} // end namespace sema 801243830Sdim} // end namespace clang 802243830Sdim 803212795Sdim#endif 804