ScopeInfo.h revision b69b42c55d56815bab62991bf839cdb41634d3af
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#include "llvm/ADT/SetVector.h" 22 23namespace clang { 24 25class BlockDecl; 26class IdentifierInfo; 27class LabelDecl; 28class ReturnStmt; 29class Scope; 30class SwitchStmt; 31 32namespace sema { 33 34class PossiblyUnreachableDiag { 35public: 36 PartialDiagnostic PD; 37 SourceLocation Loc; 38 const Stmt *stmt; 39 40 PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, 41 const Stmt *stmt) 42 : PD(PD), Loc(Loc), stmt(stmt) {} 43}; 44 45/// \brief Retains information about a function, method, or block that is 46/// currently being parsed. 47class FunctionScopeInfo { 48protected: 49 enum ScopeKind { 50 SK_Function, 51 SK_Block, 52 SK_Lambda 53 }; 54 55public: 56 /// \brief What kind of scope we are describing. 57 /// 58 ScopeKind Kind; 59 60 /// \brief Whether this function contains a VLA, @try, try, C++ 61 /// initializer, or anything else that can't be jumped past. 62 bool HasBranchProtectedScope; 63 64 /// \brief Whether this function contains any switches or direct gotos. 65 bool HasBranchIntoScope; 66 67 /// \brief Whether this function contains any indirect gotos. 68 bool HasIndirectGoto; 69 70 /// \brief Used to determine if errors occurred in this function or block. 71 DiagnosticErrorTrap ErrorTrap; 72 73 /// SwitchStack - This is the current set of active switch statements in the 74 /// block. 75 SmallVector<SwitchStmt*, 8> SwitchStack; 76 77 /// \brief The list of return statements that occur within the function or 78 /// block, if there is any chance of applying the named return value 79 /// optimization. 80 SmallVector<ReturnStmt*, 4> Returns; 81 82 /// \brief A list of PartialDiagnostics created but delayed within the 83 /// current function scope. These diagnostics are vetted for reachability 84 /// prior to being emitted. 85 SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; 86 87 void setHasBranchIntoScope() { 88 HasBranchIntoScope = true; 89 } 90 91 void setHasBranchProtectedScope() { 92 HasBranchProtectedScope = true; 93 } 94 95 void setHasIndirectGoto() { 96 HasIndirectGoto = true; 97 } 98 99 bool NeedsScopeChecking() const { 100 return HasIndirectGoto || 101 (HasBranchProtectedScope && HasBranchIntoScope); 102 } 103 104 FunctionScopeInfo(DiagnosticsEngine &Diag) 105 : Kind(SK_Function), 106 HasBranchProtectedScope(false), 107 HasBranchIntoScope(false), 108 HasIndirectGoto(false), 109 ErrorTrap(Diag) { } 110 111 virtual ~FunctionScopeInfo(); 112 113 /// \brief Clear out the information in this function scope, making it 114 /// suitable for reuse. 115 void Clear(); 116 117 static bool classof(const FunctionScopeInfo *FSI) { return true; } 118}; 119 120class CapturingScopeInfo : public FunctionScopeInfo { 121public: 122 enum ImplicitCaptureStyle { 123 ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block 124 }; 125 126 ImplicitCaptureStyle ImpCaptureStyle; 127 128 class Capture { 129 enum CaptureKind { 130 Cap_This, Cap_ByVal, Cap_ByRef 131 }; 132 133 // The variable being captured (if we are not capturing 'this'), 134 // and misc bits descibing the capture. 135 llvm::PointerIntPair<VarDecl*, 2, CaptureKind> VarAndKind; 136 137 // Expression to initialize a field of the given type, and whether this 138 // is a nested capture; the expression is only required if we are 139 // capturing ByVal and the variable's type has a non-trivial 140 // copy constructor. 141 llvm::PointerIntPair<Expr*, 1, bool> CopyExprAndNested; 142 143 public: 144 Capture(VarDecl *Var, bool isByref, bool isNested, Expr *Cpy) 145 : VarAndKind(Var, isByref ? Cap_ByRef : Cap_ByVal), 146 CopyExprAndNested(Cpy, isNested) {} 147 148 enum IsThisCapture { ThisCapture }; 149 Capture(IsThisCapture, bool isNested) 150 : VarAndKind(0, Cap_This), 151 CopyExprAndNested(0, isNested) { 152 } 153 154 bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; } 155 bool isVariableCapture() const { return !isThisCapture(); } 156 bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByVal; } 157 bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; } 158 bool isNested() { return CopyExprAndNested.getInt(); } 159 160 VarDecl *getVariable() const { 161 return VarAndKind.getPointer(); 162 } 163 Expr *getCopyExpr() const { 164 return CopyExprAndNested.getPointer(); 165 } 166 }; 167 168 CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) 169 : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0) 170 {} 171 172 /// CaptureMap - A map of captured variables to (index+1) into Captures. 173 llvm::DenseMap<VarDecl*, unsigned> CaptureMap; 174 175 /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; 176 /// zero if 'this' is not captured. 177 unsigned CXXThisCaptureIndex; 178 179 /// Captures - The captures. 180 SmallVector<Capture, 4> Captures; 181 182 void AddCapture(VarDecl *Var, bool isByref, bool isNested, Expr *Cpy) { 183 Captures.push_back(Capture(Var, isByref, isNested, Cpy)); 184 CaptureMap[Var] = Captures.size(); 185 } 186 187 void AddThisCapture(bool isNested) { 188 Captures.push_back(Capture(Capture::ThisCapture, isNested)); 189 CXXThisCaptureIndex = Captures.size(); 190 } 191 192 static bool classof(const FunctionScopeInfo *FSI) { 193 return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; 194 } 195 static bool classof(const CapturingScopeInfo *BSI) { return true; } 196}; 197 198/// \brief Retains information about a block that is currently being parsed. 199class BlockScopeInfo : public CapturingScopeInfo { 200public: 201 BlockDecl *TheDecl; 202 203 /// TheScope - This is the scope for the block itself, which contains 204 /// arguments etc. 205 Scope *TheScope; 206 207 /// ReturnType - The return type of the block, or null if the block 208 /// signature didn't provide an explicit return type. 209 QualType ReturnType; 210 211 /// BlockType - The function type of the block, if one was given. 212 /// Its return type may be BuiltinType::Dependent. 213 QualType FunctionType; 214 215 BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) 216 : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), 217 TheScope(BlockScope) 218 { 219 Kind = SK_Block; 220 } 221 222 virtual ~BlockScopeInfo(); 223 224 static bool classof(const FunctionScopeInfo *FSI) { 225 return FSI->Kind == SK_Block; 226 } 227 static bool classof(const BlockScopeInfo *BSI) { return true; } 228}; 229 230class LambdaScopeInfo : public CapturingScopeInfo { 231public: 232 /// \brief The class that describes the lambda. 233 CXXRecordDecl *Lambda; 234 235 /// \brief The number of captures in the \c Captures list that are 236 /// explicit captures. 237 unsigned NumExplicitCaptures; 238 239 /// \brief - Whether the return type of the lambda is implicit 240 bool HasImplicitReturnType; 241 242 /// ReturnType - The return type of the lambda, or null if unknown. 243 QualType ReturnType; 244 245 LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda) 246 : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda), 247 NumExplicitCaptures(0), HasImplicitReturnType(false) 248 { 249 Kind = SK_Lambda; 250 } 251 252 virtual ~LambdaScopeInfo(); 253 254 static bool classof(const FunctionScopeInfo *FSI) { 255 return FSI->Kind == SK_Lambda; 256 } 257 static bool classof(const LambdaScopeInfo *BSI) { return true; } 258 259}; 260 261} 262} 263 264#endif 265