1 //===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines FunctionScopeInfo and BlockScopeInfo. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H 15 #define LLVM_CLANG_SEMA_SCOPE_INFO_H 16 17 #include "clang/AST/Type.h" 18 #include "clang/Basic/PartialDiagnostic.h" 19 #include "llvm/ADT/DenseMap.h" 20 #include "llvm/ADT/SmallVector.h" 21 22 namespace clang { 23 24 class BlockDecl; 25 class CXXMethodDecl; 26 class IdentifierInfo; 27 class LabelDecl; 28 class ReturnStmt; 29 class Scope; 30 class SwitchStmt; 31 class VarDecl; 32 33 namespace sema { 34 35 /// \brief Contains information about the compound statement currently being 36 /// parsed. 37 class CompoundScopeInfo { 38 public: CompoundScopeInfo()39 CompoundScopeInfo() 40 : HasEmptyLoopBodies(false) { } 41 42 /// \brief Whether this compound stamement contains `for' or `while' loops 43 /// with empty bodies. 44 bool HasEmptyLoopBodies; 45 setHasEmptyLoopBodies()46 void setHasEmptyLoopBodies() { 47 HasEmptyLoopBodies = true; 48 } 49 }; 50 51 class PossiblyUnreachableDiag { 52 public: 53 PartialDiagnostic PD; 54 SourceLocation Loc; 55 const Stmt *stmt; 56 PossiblyUnreachableDiag(const PartialDiagnostic & PD,SourceLocation Loc,const Stmt * stmt)57 PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, 58 const Stmt *stmt) 59 : PD(PD), Loc(Loc), stmt(stmt) {} 60 }; 61 62 /// \brief Retains information about a function, method, or block that is 63 /// currently being parsed. 64 class FunctionScopeInfo { 65 protected: 66 enum ScopeKind { 67 SK_Function, 68 SK_Block, 69 SK_Lambda 70 }; 71 72 public: 73 /// \brief What kind of scope we are describing. 74 /// 75 ScopeKind Kind; 76 77 /// \brief Whether this function contains a VLA, \@try, try, C++ 78 /// initializer, or anything else that can't be jumped past. 79 bool HasBranchProtectedScope; 80 81 /// \brief Whether this function contains any switches or direct gotos. 82 bool HasBranchIntoScope; 83 84 /// \brief Whether this function contains any indirect gotos. 85 bool HasIndirectGoto; 86 87 /// A flag that is set when parsing a -dealloc method and no [super dealloc] 88 /// call was found yet. 89 bool ObjCShouldCallSuperDealloc; 90 91 /// A flag that is set when parsing a -finalize method and no [super finalize] 92 /// call was found yet. 93 bool ObjCShouldCallSuperFinalize; 94 95 /// \brief Used to determine if errors occurred in this function or block. 96 DiagnosticErrorTrap ErrorTrap; 97 98 /// SwitchStack - This is the current set of active switch statements in the 99 /// block. 100 SmallVector<SwitchStmt*, 8> SwitchStack; 101 102 /// \brief The list of return statements that occur within the function or 103 /// block, if there is any chance of applying the named return value 104 /// optimization, or if we need to infer a return type. 105 SmallVector<ReturnStmt*, 4> Returns; 106 107 /// \brief The stack of currently active compound stamement scopes in the 108 /// function. 109 SmallVector<CompoundScopeInfo, 4> CompoundScopes; 110 111 /// \brief A list of PartialDiagnostics created but delayed within the 112 /// current function scope. These diagnostics are vetted for reachability 113 /// prior to being emitted. 114 SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; 115 setHasBranchIntoScope()116 void setHasBranchIntoScope() { 117 HasBranchIntoScope = true; 118 } 119 setHasBranchProtectedScope()120 void setHasBranchProtectedScope() { 121 HasBranchProtectedScope = true; 122 } 123 setHasIndirectGoto()124 void setHasIndirectGoto() { 125 HasIndirectGoto = true; 126 } 127 NeedsScopeChecking()128 bool NeedsScopeChecking() const { 129 return HasIndirectGoto || 130 (HasBranchProtectedScope && HasBranchIntoScope); 131 } 132 FunctionScopeInfo(DiagnosticsEngine & Diag)133 FunctionScopeInfo(DiagnosticsEngine &Diag) 134 : Kind(SK_Function), 135 HasBranchProtectedScope(false), 136 HasBranchIntoScope(false), 137 HasIndirectGoto(false), 138 ObjCShouldCallSuperDealloc(false), 139 ObjCShouldCallSuperFinalize(false), 140 ErrorTrap(Diag) { } 141 142 virtual ~FunctionScopeInfo(); 143 144 /// \brief Clear out the information in this function scope, making it 145 /// suitable for reuse. 146 void Clear(); 147 classof(const FunctionScopeInfo * FSI)148 static bool classof(const FunctionScopeInfo *FSI) { return true; } 149 }; 150 151 class CapturingScopeInfo : public FunctionScopeInfo { 152 public: 153 enum ImplicitCaptureStyle { 154 ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block 155 }; 156 157 ImplicitCaptureStyle ImpCaptureStyle; 158 159 class Capture { 160 // There are two categories of capture: capturing 'this', and capturing 161 // local variables. There are three ways to capture a local variable: 162 // capture by copy in the C++11 sense, capture by reference 163 // in the C++11 sense, and __block capture. Lambdas explicitly specify 164 // capture by copy or capture by reference. For blocks, __block capture 165 // applies to variables with that annotation, variables of reference type 166 // are captured by reference, and other variables are captured by copy. 167 enum CaptureKind { 168 Cap_This, Cap_ByCopy, Cap_ByRef, Cap_Block 169 }; 170 171 // The variable being captured (if we are not capturing 'this'), 172 // and misc bits descibing the capture. 173 llvm::PointerIntPair<VarDecl*, 2, CaptureKind> VarAndKind; 174 175 // Expression to initialize a field of the given type, and whether this 176 // is a nested capture; the expression is only required if we are 177 // capturing ByVal and the variable's type has a non-trivial 178 // copy constructor. 179 llvm::PointerIntPair<Expr*, 1, bool> CopyExprAndNested; 180 181 /// \brief The source location at which the first capture occurred.. 182 SourceLocation Loc; 183 184 /// \brief The location of the ellipsis that expands a parameter pack. 185 SourceLocation EllipsisLoc; 186 187 /// \brief The type as it was captured, which is in effect the type of the 188 /// non-static data member that would hold the capture. 189 QualType CaptureType; 190 191 public: Capture(VarDecl * Var,bool block,bool byRef,bool isNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,Expr * Cpy)192 Capture(VarDecl *Var, bool block, bool byRef, bool isNested, 193 SourceLocation Loc, SourceLocation EllipsisLoc, 194 QualType CaptureType, Expr *Cpy) 195 : VarAndKind(Var, block ? Cap_Block : byRef ? Cap_ByRef : Cap_ByCopy), 196 CopyExprAndNested(Cpy, isNested), Loc(Loc), EllipsisLoc(EllipsisLoc), 197 CaptureType(CaptureType){} 198 199 enum IsThisCapture { ThisCapture }; Capture(IsThisCapture,bool isNested,SourceLocation Loc,QualType CaptureType,Expr * Cpy)200 Capture(IsThisCapture, bool isNested, SourceLocation Loc, 201 QualType CaptureType, Expr *Cpy) 202 : VarAndKind(0, Cap_This), CopyExprAndNested(Cpy, isNested), Loc(Loc), 203 EllipsisLoc(), CaptureType(CaptureType) { } 204 isThisCapture()205 bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; } isVariableCapture()206 bool isVariableCapture() const { return !isThisCapture(); } isCopyCapture()207 bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; } isReferenceCapture()208 bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; } isBlockCapture()209 bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; } isNested()210 bool isNested() { return CopyExprAndNested.getInt(); } 211 getVariable()212 VarDecl *getVariable() const { 213 return VarAndKind.getPointer(); 214 } 215 216 /// \brief Retrieve the location at which this variable was captured. getLocation()217 SourceLocation getLocation() const { return Loc; } 218 219 /// \brief Retrieve the source location of the ellipsis, whose presence 220 /// indicates that the capture is a pack expansion. getEllipsisLoc()221 SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 222 223 /// \brief Retrieve the capture type for this capture, which is effectively 224 /// the type of the non-static data member in the lambda/block structure 225 /// that would store this capture. getCaptureType()226 QualType getCaptureType() const { return CaptureType; } 227 getCopyExpr()228 Expr *getCopyExpr() const { 229 return CopyExprAndNested.getPointer(); 230 } 231 }; 232 CapturingScopeInfo(DiagnosticsEngine & Diag,ImplicitCaptureStyle Style)233 CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) 234 : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0), 235 HasImplicitReturnType(false) 236 {} 237 238 /// CaptureMap - A map of captured variables to (index+1) into Captures. 239 llvm::DenseMap<VarDecl*, unsigned> CaptureMap; 240 241 /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; 242 /// zero if 'this' is not captured. 243 unsigned CXXThisCaptureIndex; 244 245 /// Captures - The captures. 246 SmallVector<Capture, 4> Captures; 247 248 /// \brief - Whether the target type of return statements in this context 249 /// is deduced (e.g. a lambda or block with omitted return type). 250 bool HasImplicitReturnType; 251 252 /// ReturnType - The target type of return statements in this context, 253 /// or null if unknown. 254 QualType ReturnType; 255 addCapture(VarDecl * Var,bool isBlock,bool isByref,bool isNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,Expr * Cpy)256 void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested, 257 SourceLocation Loc, SourceLocation EllipsisLoc, 258 QualType CaptureType, Expr *Cpy) { 259 Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, 260 EllipsisLoc, CaptureType, Cpy)); 261 CaptureMap[Var] = Captures.size(); 262 } 263 addThisCapture(bool isNested,SourceLocation Loc,QualType CaptureType,Expr * Cpy)264 void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType, 265 Expr *Cpy) { 266 Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, 267 Cpy)); 268 CXXThisCaptureIndex = Captures.size(); 269 } 270 271 /// \brief Determine whether the C++ 'this' is captured. isCXXThisCaptured()272 bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } 273 274 /// \brief Retrieve the capture of C++ 'this', if it has been captured. getCXXThisCapture()275 Capture &getCXXThisCapture() { 276 assert(isCXXThisCaptured() && "this has not been captured"); 277 return Captures[CXXThisCaptureIndex - 1]; 278 } 279 280 /// \brief Determine whether the given variable has been captured. isCaptured(VarDecl * Var)281 bool isCaptured(VarDecl *Var) const { 282 return CaptureMap.count(Var); 283 } 284 285 /// \brief Retrieve the capture of the given variable, if it has been 286 /// captured already. getCapture(VarDecl * Var)287 Capture &getCapture(VarDecl *Var) { 288 assert(isCaptured(Var) && "Variable has not been captured"); 289 return Captures[CaptureMap[Var] - 1]; 290 } 291 getCapture(VarDecl * Var)292 const Capture &getCapture(VarDecl *Var) const { 293 llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known 294 = CaptureMap.find(Var); 295 assert(Known != CaptureMap.end() && "Variable has not been captured"); 296 return Captures[Known->second - 1]; 297 } 298 classof(const FunctionScopeInfo * FSI)299 static bool classof(const FunctionScopeInfo *FSI) { 300 return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; 301 } classof(const CapturingScopeInfo * BSI)302 static bool classof(const CapturingScopeInfo *BSI) { return true; } 303 }; 304 305 /// \brief Retains information about a block that is currently being parsed. 306 class BlockScopeInfo : public CapturingScopeInfo { 307 public: 308 BlockDecl *TheDecl; 309 310 /// TheScope - This is the scope for the block itself, which contains 311 /// arguments etc. 312 Scope *TheScope; 313 314 /// BlockType - The function type of the block, if one was given. 315 /// Its return type may be BuiltinType::Dependent. 316 QualType FunctionType; 317 BlockScopeInfo(DiagnosticsEngine & Diag,Scope * BlockScope,BlockDecl * Block)318 BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) 319 : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), 320 TheScope(BlockScope) 321 { 322 Kind = SK_Block; 323 } 324 325 virtual ~BlockScopeInfo(); 326 classof(const FunctionScopeInfo * FSI)327 static bool classof(const FunctionScopeInfo *FSI) { 328 return FSI->Kind == SK_Block; 329 } classof(const BlockScopeInfo * BSI)330 static bool classof(const BlockScopeInfo *BSI) { return true; } 331 }; 332 333 class LambdaScopeInfo : public CapturingScopeInfo { 334 public: 335 /// \brief The class that describes the lambda. 336 CXXRecordDecl *Lambda; 337 338 /// \brief The class that describes the lambda. 339 CXXMethodDecl *CallOperator; 340 341 /// \brief Source range covering the lambda introducer [...]. 342 SourceRange IntroducerRange; 343 344 /// \brief The number of captures in the \c Captures list that are 345 /// explicit captures. 346 unsigned NumExplicitCaptures; 347 348 /// \brief Whether this is a mutable lambda. 349 bool Mutable; 350 351 /// \brief Whether the (empty) parameter list is explicit. 352 bool ExplicitParams; 353 354 /// \brief Whether any of the capture expressions requires cleanups. 355 bool ExprNeedsCleanups; 356 357 /// \brief Whether the lambda contains an unexpanded parameter pack. 358 bool ContainsUnexpandedParameterPack; 359 360 /// \brief Variables used to index into by-copy array captures. 361 llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; 362 363 /// \brief Offsets into the ArrayIndexVars array at which each capture starts 364 /// its list of array index variables. 365 llvm::SmallVector<unsigned, 4> ArrayIndexStarts; 366 LambdaScopeInfo(DiagnosticsEngine & Diag,CXXRecordDecl * Lambda,CXXMethodDecl * CallOperator)367 LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda, 368 CXXMethodDecl *CallOperator) 369 : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda), 370 CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false), 371 ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false) 372 { 373 Kind = SK_Lambda; 374 } 375 376 virtual ~LambdaScopeInfo(); 377 378 /// \brief Note when finishedExplicitCaptures()379 void finishedExplicitCaptures() { 380 NumExplicitCaptures = Captures.size(); 381 } 382 classof(const FunctionScopeInfo * FSI)383 static bool classof(const FunctionScopeInfo *FSI) { 384 return FSI->Kind == SK_Lambda; 385 } classof(const LambdaScopeInfo * BSI)386 static bool classof(const LambdaScopeInfo *BSI) { return true; } 387 388 }; 389 390 } 391 } 392 393 #endif 394