ScopeInfo.h revision 625bb569df0c34feec0d52c0ec5215f21ef2e054
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 22namespace clang { 23 24class BlockDecl; 25class CXXMethodDecl; 26class IdentifierInfo; 27class LabelDecl; 28class ReturnStmt; 29class Scope; 30class SwitchStmt; 31class VarDecl; 32 33namespace sema { 34 35/// \brief Contains information about the compound statement currently being 36/// parsed. 37class CompoundScopeInfo { 38public: 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 46 void setHasEmptyLoopBodies() { 47 HasEmptyLoopBodies = true; 48 } 49}; 50 51class PossiblyUnreachableDiag { 52public: 53 PartialDiagnostic PD; 54 SourceLocation Loc; 55 const Stmt *stmt; 56 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. 64class FunctionScopeInfo { 65protected: 66 enum ScopeKind { 67 SK_Function, 68 SK_Block, 69 SK_Lambda 70 }; 71 72public: 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 108 void setHasBranchIntoScope() { 109 HasBranchIntoScope = true; 110 } 111 112 void setHasBranchProtectedScope() { 113 HasBranchProtectedScope = true; 114 } 115 116 void setHasIndirectGoto() { 117 HasIndirectGoto = true; 118 } 119 120 bool NeedsScopeChecking() const { 121 return HasIndirectGoto || 122 (HasBranchProtectedScope && HasBranchIntoScope); 123 } 124 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 138 static bool classof(const FunctionScopeInfo *FSI) { return true; } 139}; 140 141class CapturingScopeInfo : public FunctionScopeInfo { 142public: 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 public: 178 Capture(VarDecl *Var, bool block, bool byRef, bool isNested, 179 SourceLocation Loc, SourceLocation EllipsisLoc, Expr *Cpy) 180 : VarAndKind(Var, block ? Cap_Block : byRef ? Cap_ByRef : Cap_ByCopy), 181 CopyExprAndNested(Cpy, isNested), Loc(Loc), EllipsisLoc(EllipsisLoc) {} 182 183 enum IsThisCapture { ThisCapture }; 184 Capture(IsThisCapture, bool isNested, SourceLocation Loc, Expr *Cpy) 185 : VarAndKind(0, Cap_This), CopyExprAndNested(Cpy, isNested), Loc(Loc), 186 EllipsisLoc() { } 187 188 bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; } 189 bool isVariableCapture() const { return !isThisCapture(); } 190 bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; } 191 bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; } 192 bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; } 193 bool isNested() { return CopyExprAndNested.getInt(); } 194 195 VarDecl *getVariable() const { 196 return VarAndKind.getPointer(); 197 } 198 199 /// \brief Retrieve the location at which this variable was captured. 200 SourceLocation getLocation() const { return Loc; } 201 202 /// \brief Retrieve the source location of the ellipsis, whose presence 203 /// indicates that the capture is a pack expansion. 204 SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 205 206 Expr *getCopyExpr() const { 207 return CopyExprAndNested.getPointer(); 208 } 209 }; 210 211 CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) 212 : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0), 213 HasImplicitReturnType(false) 214 {} 215 216 /// CaptureMap - A map of captured variables to (index+1) into Captures. 217 llvm::DenseMap<VarDecl*, unsigned> CaptureMap; 218 219 /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; 220 /// zero if 'this' is not captured. 221 unsigned CXXThisCaptureIndex; 222 223 /// Captures - The captures. 224 SmallVector<Capture, 4> Captures; 225 226 /// \brief - Whether the target type of return statements in this context 227 /// is deduced (e.g. a lambda or block with omitted return type). 228 bool HasImplicitReturnType; 229 230 /// ReturnType - The target type of return statements in this context, 231 /// or null if unknown. 232 QualType ReturnType; 233 234 void AddCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested, 235 SourceLocation Loc, SourceLocation EllipsisLoc, Expr *Cpy) { 236 Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, 237 EllipsisLoc, Cpy)); 238 CaptureMap[Var] = Captures.size(); 239 } 240 241 void AddThisCapture(bool isNested, SourceLocation Loc, Expr *Cpy) { 242 Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, Cpy)); 243 CXXThisCaptureIndex = Captures.size(); 244 } 245 246 /// \brief Determine whether the C++ 'this' is captured. 247 bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } 248 249 /// \brief Retrieve the capture of C++ 'this', if it has been captured. 250 Capture &getCXXThisCapture() { 251 assert(isCXXThisCaptured() && "this has not been captured"); 252 return Captures[CXXThisCaptureIndex - 1]; 253 } 254 255 /// \brief Determine whether the given variable has been captured. 256 bool isCaptured(VarDecl *Var) const { 257 return CaptureMap.count(Var); 258 } 259 260 /// \brief Retrieve the capture of the given variable, if it has been 261 /// captured already. 262 Capture &getCapture(VarDecl *Var) { 263 assert(isCaptured(Var) && "Variable has not been captured"); 264 return Captures[CaptureMap[Var] - 1]; 265 } 266 267 const Capture &getCapture(VarDecl *Var) const { 268 llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known 269 = CaptureMap.find(Var); 270 assert(Known != CaptureMap.end() && "Variable has not been captured"); 271 return Captures[Known->second - 1]; 272 } 273 274 static bool classof(const FunctionScopeInfo *FSI) { 275 return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; 276 } 277 static bool classof(const CapturingScopeInfo *BSI) { return true; } 278}; 279 280/// \brief Retains information about a block that is currently being parsed. 281class BlockScopeInfo : public CapturingScopeInfo { 282public: 283 BlockDecl *TheDecl; 284 285 /// TheScope - This is the scope for the block itself, which contains 286 /// arguments etc. 287 Scope *TheScope; 288 289 /// BlockType - The function type of the block, if one was given. 290 /// Its return type may be BuiltinType::Dependent. 291 QualType FunctionType; 292 293 BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) 294 : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), 295 TheScope(BlockScope) 296 { 297 Kind = SK_Block; 298 } 299 300 virtual ~BlockScopeInfo(); 301 302 static bool classof(const FunctionScopeInfo *FSI) { 303 return FSI->Kind == SK_Block; 304 } 305 static bool classof(const BlockScopeInfo *BSI) { return true; } 306}; 307 308class LambdaScopeInfo : public CapturingScopeInfo { 309public: 310 /// \brief The class that describes the lambda. 311 CXXRecordDecl *Lambda; 312 313 /// \brief The class that describes the lambda. 314 CXXMethodDecl *CallOperator; 315 316 /// \brief Source range covering the lambda introducer [...]. 317 SourceRange IntroducerRange; 318 319 /// \brief The number of captures in the \c Captures list that are 320 /// explicit captures. 321 unsigned NumExplicitCaptures; 322 323 /// \brief Whether this is a mutable lambda. 324 bool Mutable; 325 326 /// \brief Whether the (empty) parameter list is explicit. 327 bool ExplicitParams; 328 329 /// \brief Whether any of the capture expressions requires cleanups. 330 bool ExprNeedsCleanups; 331 332 /// \brief Variables used to index into by-copy array captures. 333 llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; 334 335 /// \brief Offsets into the ArrayIndexVars array at which each capture starts 336 /// its list of array index variables. 337 llvm::SmallVector<unsigned, 4> ArrayIndexStarts; 338 339 LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda, 340 CXXMethodDecl *CallOperator) 341 : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda), 342 CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false), 343 ExprNeedsCleanups(false) 344 { 345 Kind = SK_Lambda; 346 } 347 348 virtual ~LambdaScopeInfo(); 349 350 /// \brief Note when 351 void finishedExplicitCaptures() { 352 NumExplicitCaptures = Captures.size(); 353 } 354 355 static bool classof(const FunctionScopeInfo *FSI) { 356 return FSI->Kind == SK_Lambda; 357 } 358 static bool classof(const LambdaScopeInfo *BSI) { return true; } 359 360}; 361 362} 363} 364 365#endif 366