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 /// \brief Used to determine if errors occurred in this function or block. 88 DiagnosticErrorTrap ErrorTrap; 89 90 /// SwitchStack - This is the current set of active switch statements in the 91 /// block. 92 SmallVector<SwitchStmt*, 8> SwitchStack; 93 94 /// \brief The list of return statements that occur within the function or 95 /// block, if there is any chance of applying the named return value 96 /// optimization. 97 SmallVector<ReturnStmt*, 4> Returns; 98 99 /// \brief The stack of currently active compound stamement scopes in the 100 /// function. 101 SmallVector<CompoundScopeInfo, 4> CompoundScopes; 102 103 /// \brief A list of PartialDiagnostics created but delayed within the 104 /// current function scope. These diagnostics are vetted for reachability 105 /// prior to being emitted. 106 SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; 107 setHasBranchIntoScope()108 void setHasBranchIntoScope() { 109 HasBranchIntoScope = true; 110 } 111 setHasBranchProtectedScope()112 void setHasBranchProtectedScope() { 113 HasBranchProtectedScope = true; 114 } 115 setHasIndirectGoto()116 void setHasIndirectGoto() { 117 HasIndirectGoto = true; 118 } 119 NeedsScopeChecking()120 bool NeedsScopeChecking() const { 121 return HasIndirectGoto || 122 (HasBranchProtectedScope && HasBranchIntoScope); 123 } 124 FunctionScopeInfo(DiagnosticsEngine & Diag)125 FunctionScopeInfo(DiagnosticsEngine &Diag) 126 : Kind(SK_Function), 127 HasBranchProtectedScope(false), 128 HasBranchIntoScope(false), 129 HasIndirectGoto(false), 130 ErrorTrap(Diag) { } 131 132 virtual ~FunctionScopeInfo(); 133 134 /// \brief Clear out the information in this function scope, making it 135 /// suitable for reuse. 136 void Clear(); 137 classof(const FunctionScopeInfo * FSI)138 static bool classof(const FunctionScopeInfo *FSI) { return true; } 139 }; 140 141 class CapturingScopeInfo : public FunctionScopeInfo { 142 public: 143 enum ImplicitCaptureStyle { 144 ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block 145 }; 146 147 ImplicitCaptureStyle ImpCaptureStyle; 148 149 class Capture { 150 // There are two categories of capture: capturing 'this', and capturing 151 // local variables. There are three ways to capture a local variable: 152 // capture by copy in the C++11 sense, capture by reference 153 // in the C++11 sense, and __block capture. Lambdas explicitly specify 154 // capture by copy or capture by reference. For blocks, __block capture 155 // applies to variables with that annotation, variables of reference type 156 // are captured by reference, and other variables are captured by copy. 157 enum CaptureKind { 158 Cap_This, Cap_ByCopy, Cap_ByRef, Cap_Block 159 }; 160 161 // The variable being captured (if we are not capturing 'this'), 162 // and misc bits descibing the capture. 163 llvm::PointerIntPair<VarDecl*, 2, CaptureKind> VarAndKind; 164 165 // Expression to initialize a field of the given type, and whether this 166 // is a nested capture; the expression is only required if we are 167 // capturing ByVal and the variable's type has a non-trivial 168 // copy constructor. 169 llvm::PointerIntPair<Expr*, 1, bool> CopyExprAndNested; 170 171 /// \brief The source location at which the first capture occurred.. 172 SourceLocation Loc; 173 174 /// \brief The location of the ellipsis that expands a parameter pack. 175 SourceLocation EllipsisLoc; 176 177 /// \brief The type as it was captured, which is in effect the type of the 178 /// non-static data member that would hold the capture. 179 QualType CaptureType; 180 181 public: Capture(VarDecl * Var,bool block,bool byRef,bool isNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,Expr * Cpy)182 Capture(VarDecl *Var, bool block, bool byRef, bool isNested, 183 SourceLocation Loc, SourceLocation EllipsisLoc, 184 QualType CaptureType, Expr *Cpy) 185 : VarAndKind(Var, block ? Cap_Block : byRef ? Cap_ByRef : Cap_ByCopy), 186 CopyExprAndNested(Cpy, isNested), Loc(Loc), EllipsisLoc(EllipsisLoc), 187 CaptureType(CaptureType){} 188 189 enum IsThisCapture { ThisCapture }; Capture(IsThisCapture,bool isNested,SourceLocation Loc,QualType CaptureType,Expr * Cpy)190 Capture(IsThisCapture, bool isNested, SourceLocation Loc, 191 QualType CaptureType, Expr *Cpy) 192 : VarAndKind(0, Cap_This), CopyExprAndNested(Cpy, isNested), Loc(Loc), 193 EllipsisLoc(), CaptureType(CaptureType) { } 194 isThisCapture()195 bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; } isVariableCapture()196 bool isVariableCapture() const { return !isThisCapture(); } isCopyCapture()197 bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; } isReferenceCapture()198 bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; } isBlockCapture()199 bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; } isNested()200 bool isNested() { return CopyExprAndNested.getInt(); } 201 getVariable()202 VarDecl *getVariable() const { 203 return VarAndKind.getPointer(); 204 } 205 206 /// \brief Retrieve the location at which this variable was captured. getLocation()207 SourceLocation getLocation() const { return Loc; } 208 209 /// \brief Retrieve the source location of the ellipsis, whose presence 210 /// indicates that the capture is a pack expansion. getEllipsisLoc()211 SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 212 213 /// \brief Retrieve the capture type for this capture, which is effectively 214 /// the type of the non-static data member in the lambda/block structure 215 /// that would store this capture. getCaptureType()216 QualType getCaptureType() const { return CaptureType; } 217 getCopyExpr()218 Expr *getCopyExpr() const { 219 return CopyExprAndNested.getPointer(); 220 } 221 }; 222 CapturingScopeInfo(DiagnosticsEngine & Diag,ImplicitCaptureStyle Style)223 CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) 224 : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0), 225 HasImplicitReturnType(false) 226 {} 227 228 /// CaptureMap - A map of captured variables to (index+1) into Captures. 229 llvm::DenseMap<VarDecl*, unsigned> CaptureMap; 230 231 /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; 232 /// zero if 'this' is not captured. 233 unsigned CXXThisCaptureIndex; 234 235 /// Captures - The captures. 236 SmallVector<Capture, 4> Captures; 237 238 /// \brief - Whether the target type of return statements in this context 239 /// is deduced (e.g. a lambda or block with omitted return type). 240 bool HasImplicitReturnType; 241 242 /// ReturnType - The target type of return statements in this context, 243 /// or null if unknown. 244 QualType ReturnType; 245 addCapture(VarDecl * Var,bool isBlock,bool isByref,bool isNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,Expr * Cpy)246 void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested, 247 SourceLocation Loc, SourceLocation EllipsisLoc, 248 QualType CaptureType, Expr *Cpy) { 249 Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, 250 EllipsisLoc, CaptureType, Cpy)); 251 CaptureMap[Var] = Captures.size(); 252 } 253 addThisCapture(bool isNested,SourceLocation Loc,QualType CaptureType,Expr * Cpy)254 void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType, 255 Expr *Cpy) { 256 Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, 257 Cpy)); 258 CXXThisCaptureIndex = Captures.size(); 259 } 260 261 /// \brief Determine whether the C++ 'this' is captured. isCXXThisCaptured()262 bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } 263 264 /// \brief Retrieve the capture of C++ 'this', if it has been captured. getCXXThisCapture()265 Capture &getCXXThisCapture() { 266 assert(isCXXThisCaptured() && "this has not been captured"); 267 return Captures[CXXThisCaptureIndex - 1]; 268 } 269 270 /// \brief Determine whether the given variable has been captured. isCaptured(VarDecl * Var)271 bool isCaptured(VarDecl *Var) const { 272 return CaptureMap.count(Var); 273 } 274 275 /// \brief Retrieve the capture of the given variable, if it has been 276 /// captured already. getCapture(VarDecl * Var)277 Capture &getCapture(VarDecl *Var) { 278 assert(isCaptured(Var) && "Variable has not been captured"); 279 return Captures[CaptureMap[Var] - 1]; 280 } 281 getCapture(VarDecl * Var)282 const Capture &getCapture(VarDecl *Var) const { 283 llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known 284 = CaptureMap.find(Var); 285 assert(Known != CaptureMap.end() && "Variable has not been captured"); 286 return Captures[Known->second - 1]; 287 } 288 classof(const FunctionScopeInfo * FSI)289 static bool classof(const FunctionScopeInfo *FSI) { 290 return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; 291 } classof(const CapturingScopeInfo * BSI)292 static bool classof(const CapturingScopeInfo *BSI) { return true; } 293 }; 294 295 /// \brief Retains information about a block that is currently being parsed. 296 class BlockScopeInfo : public CapturingScopeInfo { 297 public: 298 BlockDecl *TheDecl; 299 300 /// TheScope - This is the scope for the block itself, which contains 301 /// arguments etc. 302 Scope *TheScope; 303 304 /// BlockType - The function type of the block, if one was given. 305 /// Its return type may be BuiltinType::Dependent. 306 QualType FunctionType; 307 BlockScopeInfo(DiagnosticsEngine & Diag,Scope * BlockScope,BlockDecl * Block)308 BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) 309 : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), 310 TheScope(BlockScope) 311 { 312 Kind = SK_Block; 313 } 314 315 virtual ~BlockScopeInfo(); 316 classof(const FunctionScopeInfo * FSI)317 static bool classof(const FunctionScopeInfo *FSI) { 318 return FSI->Kind == SK_Block; 319 } classof(const BlockScopeInfo * BSI)320 static bool classof(const BlockScopeInfo *BSI) { return true; } 321 }; 322 323 class LambdaScopeInfo : public CapturingScopeInfo { 324 public: 325 /// \brief The class that describes the lambda. 326 CXXRecordDecl *Lambda; 327 328 /// \brief The class that describes the lambda. 329 CXXMethodDecl *CallOperator; 330 331 /// \brief Source range covering the lambda introducer [...]. 332 SourceRange IntroducerRange; 333 334 /// \brief The number of captures in the \c Captures list that are 335 /// explicit captures. 336 unsigned NumExplicitCaptures; 337 338 /// \brief Whether this is a mutable lambda. 339 bool Mutable; 340 341 /// \brief Whether the (empty) parameter list is explicit. 342 bool ExplicitParams; 343 344 /// \brief Whether any of the capture expressions requires cleanups. 345 bool ExprNeedsCleanups; 346 347 /// \brief Variables used to index into by-copy array captures. 348 llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; 349 350 /// \brief Offsets into the ArrayIndexVars array at which each capture starts 351 /// its list of array index variables. 352 llvm::SmallVector<unsigned, 4> ArrayIndexStarts; 353 LambdaScopeInfo(DiagnosticsEngine & Diag,CXXRecordDecl * Lambda,CXXMethodDecl * CallOperator)354 LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda, 355 CXXMethodDecl *CallOperator) 356 : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda), 357 CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false), 358 ExprNeedsCleanups(false) 359 { 360 Kind = SK_Lambda; 361 } 362 363 virtual ~LambdaScopeInfo(); 364 365 /// \brief Note when finishedExplicitCaptures()366 void finishedExplicitCaptures() { 367 NumExplicitCaptures = Captures.size(); 368 } 369 classof(const FunctionScopeInfo * FSI)370 static bool classof(const FunctionScopeInfo *FSI) { 371 return FSI->Kind == SK_Lambda; 372 } classof(const LambdaScopeInfo * BSI)373 static bool classof(const LambdaScopeInfo *BSI) { return true; } 374 375 }; 376 377 } 378 } 379 380 #endif 381