ScopeInfo.h revision 76e3da57b0e8cf72d221f44d54566ef206341668
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 IdentifierInfo; 26class LabelDecl; 27class ReturnStmt; 28class Scope; 29class SwitchStmt; 30 31namespace sema { 32 33class PossiblyUnreachableDiag { 34public: 35 PartialDiagnostic PD; 36 SourceLocation Loc; 37 const Stmt *stmt; 38 39 PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, 40 const Stmt *stmt) 41 : PD(PD), Loc(Loc), stmt(stmt) {} 42}; 43 44/// \brief Retains information about a function, method, or block that is 45/// currently being parsed. 46class FunctionScopeInfo { 47protected: 48 enum ScopeKind { 49 SK_Function, 50 SK_Block, 51 SK_Lambda 52 }; 53 54public: 55 /// \brief What kind of scope we are describing. 56 /// 57 ScopeKind Kind; 58 59 /// \brief Whether this function contains a VLA, @try, try, C++ 60 /// initializer, or anything else that can't be jumped past. 61 bool HasBranchProtectedScope; 62 63 /// \brief Whether this function contains any switches or direct gotos. 64 bool HasBranchIntoScope; 65 66 /// \brief Whether this function contains any indirect gotos. 67 bool HasIndirectGoto; 68 69 /// \brief Used to determine if errors occurred in this function or block. 70 DiagnosticErrorTrap ErrorTrap; 71 72 /// SwitchStack - This is the current set of active switch statements in the 73 /// block. 74 SmallVector<SwitchStmt*, 8> SwitchStack; 75 76 /// \brief The list of return statements that occur within the function or 77 /// block, if there is any chance of applying the named return value 78 /// optimization. 79 SmallVector<ReturnStmt*, 4> Returns; 80 81 /// \brief A list of PartialDiagnostics created but delayed within the 82 /// current function scope. These diagnostics are vetted for reachability 83 /// prior to being emitted. 84 SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; 85 86 void setHasBranchIntoScope() { 87 HasBranchIntoScope = true; 88 } 89 90 void setHasBranchProtectedScope() { 91 HasBranchProtectedScope = true; 92 } 93 94 void setHasIndirectGoto() { 95 HasIndirectGoto = true; 96 } 97 98 bool NeedsScopeChecking() const { 99 return HasIndirectGoto || 100 (HasBranchProtectedScope && HasBranchIntoScope); 101 } 102 103 FunctionScopeInfo(DiagnosticsEngine &Diag) 104 : Kind(SK_Function), 105 HasBranchProtectedScope(false), 106 HasBranchIntoScope(false), 107 HasIndirectGoto(false), 108 ErrorTrap(Diag) { } 109 110 virtual ~FunctionScopeInfo(); 111 112 /// \brief Clear out the information in this function scope, making it 113 /// suitable for reuse. 114 void Clear(); 115 116 static bool classof(const FunctionScopeInfo *FSI) { return true; } 117}; 118 119class CapturingScopeInfo : public FunctionScopeInfo { 120public: 121 enum ImplicitCaptureStyle { 122 ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block 123 }; 124 125 ImplicitCaptureStyle ImpCaptureStyle; 126 127 class Capture { 128 // There are two categories of capture: capturing 'this', and capturing 129 // local variables. There are three ways to capture a local variable: 130 // capture by copy in the C++11 sense, capture by reference 131 // in the C++11 sense, and __block capture. Lambdas explicitly specify 132 // capture by copy or capture by reference. For blocks, __block capture 133 // applies to variables with that annotation, variables of reference type 134 // are captured by reference, and other variables are captured by copy. 135 enum CaptureKind { 136 Cap_This, Cap_ByCopy, Cap_ByRef, Cap_Block 137 }; 138 139 // The variable being captured (if we are not capturing 'this'), 140 // and misc bits descibing the capture. 141 llvm::PointerIntPair<VarDecl*, 2, CaptureKind> VarAndKind; 142 143 // Expression to initialize a field of the given type, and whether this 144 // is a nested capture; the expression is only required if we are 145 // capturing ByVal and the variable's type has a non-trivial 146 // copy constructor. 147 llvm::PointerIntPair<Expr*, 1, bool> CopyExprAndNested; 148 149 /// \brief The source location at which the first capture occurred.. 150 SourceLocation Loc; 151 152 public: 153 Capture(VarDecl *Var, bool block, bool byRef, bool isNested, 154 SourceLocation Loc, Expr *Cpy) 155 : VarAndKind(Var, block ? Cap_Block : byRef ? Cap_ByRef : Cap_ByCopy), 156 CopyExprAndNested(Cpy, isNested) {} 157 158 enum IsThisCapture { ThisCapture }; 159 Capture(IsThisCapture, bool isNested, SourceLocation Loc) 160 : VarAndKind(0, Cap_This), CopyExprAndNested(0, isNested), Loc(Loc) { 161 } 162 163 bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; } 164 bool isVariableCapture() const { return !isThisCapture(); } 165 bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; } 166 bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; } 167 bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; } 168 bool isNested() { return CopyExprAndNested.getInt(); } 169 170 VarDecl *getVariable() const { 171 return VarAndKind.getPointer(); 172 } 173 174 /// \brief Retrieve the location at which this variable was captured. 175 SourceLocation getLocation() const { return Loc; } 176 177 Expr *getCopyExpr() const { 178 return CopyExprAndNested.getPointer(); 179 } 180 }; 181 182 CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) 183 : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0), 184 HasImplicitReturnType(false) 185 {} 186 187 /// CaptureMap - A map of captured variables to (index+1) into Captures. 188 llvm::DenseMap<VarDecl*, unsigned> CaptureMap; 189 190 /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; 191 /// zero if 'this' is not captured. 192 unsigned CXXThisCaptureIndex; 193 194 /// Captures - The captures. 195 SmallVector<Capture, 4> Captures; 196 197 /// \brief - Whether the target type of return statements in this context 198 /// is deduced (e.g. a lambda or block with omitted return type). 199 bool HasImplicitReturnType; 200 201 /// ReturnType - The target type of return statements in this context, 202 /// or null if unknown. 203 QualType ReturnType; 204 205 void AddCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested, 206 SourceLocation Loc, Expr *Cpy) { 207 Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, Cpy)); 208 CaptureMap[Var] = Captures.size(); 209 } 210 211 void AddThisCapture(bool isNested, SourceLocation Loc) { 212 Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc)); 213 CXXThisCaptureIndex = Captures.size(); 214 } 215 216 /// \brief Determine whether the C++ 'this' is captured. 217 bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } 218 219 /// \brief Retrieve the capture of C++ 'this', if it has been captured. 220 Capture &getCXXThisCapture() { 221 assert(isCXXThisCaptured() && "this has not been captured"); 222 return Captures[CXXThisCaptureIndex - 1]; 223 } 224 225 /// \brief Determine whether the given variable has been captured. 226 bool isCaptured(VarDecl *Var) const { 227 return CaptureMap.count(Var); 228 } 229 230 /// \brief Retrieve the capture of the given variable, if it has been 231 /// captured already. 232 Capture &getCapture(VarDecl *Var) { 233 assert(isCaptured(Var) && "Variable has not been captured"); 234 return Captures[CaptureMap[Var] - 1]; 235 } 236 237 const Capture &getCapture(VarDecl *Var) const { 238 llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known 239 = CaptureMap.find(Var); 240 assert(Known != CaptureMap.end() && "Variable has not been captured"); 241 return Captures[Known->second - 1]; 242 } 243 244 static bool classof(const FunctionScopeInfo *FSI) { 245 return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; 246 } 247 static bool classof(const CapturingScopeInfo *BSI) { return true; } 248}; 249 250/// \brief Retains information about a block that is currently being parsed. 251class BlockScopeInfo : public CapturingScopeInfo { 252public: 253 BlockDecl *TheDecl; 254 255 /// TheScope - This is the scope for the block itself, which contains 256 /// arguments etc. 257 Scope *TheScope; 258 259 /// BlockType - The function type of the block, if one was given. 260 /// Its return type may be BuiltinType::Dependent. 261 QualType FunctionType; 262 263 BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) 264 : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), 265 TheScope(BlockScope) 266 { 267 Kind = SK_Block; 268 } 269 270 virtual ~BlockScopeInfo(); 271 272 static bool classof(const FunctionScopeInfo *FSI) { 273 return FSI->Kind == SK_Block; 274 } 275 static bool classof(const BlockScopeInfo *BSI) { return true; } 276}; 277 278class LambdaScopeInfo : public CapturingScopeInfo { 279public: 280 /// \brief The class that describes the lambda. 281 CXXRecordDecl *Lambda; 282 283 /// \brief The class that describes the lambda. 284 CXXMethodDecl *CallOperator; 285 286 /// \brief Source range covering the lambda introducer [...]. 287 SourceRange IntroducerRange; 288 289 /// \brief The number of captures in the \c Captures list that are 290 /// explicit captures. 291 unsigned NumExplicitCaptures; 292 293 bool Mutable; 294 295 /// \brief Whether the (empty) parameter list is explicit. 296 bool ExplicitParams; 297 298 LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda, 299 CXXMethodDecl *CallOperator) 300 : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda), 301 CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false) 302 { 303 Kind = SK_Lambda; 304 } 305 306 virtual ~LambdaScopeInfo(); 307 308 /// \brief Note when 309 void finishedExplicitCaptures() { 310 NumExplicitCaptures = Captures.size(); 311 } 312 313 static bool classof(const FunctionScopeInfo *FSI) { 314 return FSI->Kind == SK_Lambda; 315 } 316 static bool classof(const LambdaScopeInfo *BSI) { return true; } 317 318}; 319 320} 321} 322 323#endif 324