• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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