]> CyberLeo.Net >> Repos - FreeBSD/releng/9.1.git/blob - contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
Copy stable/9 to releng/9.1 as part of the 9.1-RELEASE release process.
[FreeBSD/releng/9.1.git] / contrib / llvm / tools / clang / include / clang / Sema / ScopeInfo.h
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:
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
51 class PossiblyUnreachableDiag {
52 public:
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.
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
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
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:
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 };
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
195     bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; }
196     bool isVariableCapture() const { return !isThisCapture(); }
197     bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; }
198     bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; }
199     bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; }
200     bool isNested() { return CopyExprAndNested.getInt(); }
201
202     VarDecl *getVariable() const {
203       return VarAndKind.getPointer();
204     }
205     
206     /// \brief Retrieve the location at which this variable was captured.
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.
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.
216     QualType getCaptureType() const { return CaptureType; }
217     
218     Expr *getCopyExpr() const {
219       return CopyExprAndNested.getPointer();
220     }
221   };
222
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
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
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.
262   bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
263   
264   /// \brief Retrieve the capture of C++ 'this', if it has been captured.
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.
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.
277   Capture &getCapture(VarDecl *Var) {
278     assert(isCaptured(Var) && "Variable has not been captured");
279     return Captures[CaptureMap[Var] - 1];
280   }
281
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
289   static bool classof(const FunctionScopeInfo *FSI) { 
290     return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; 
291   }
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
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
317   static bool classof(const FunctionScopeInfo *FSI) { 
318     return FSI->Kind == SK_Block; 
319   }
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   
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 
366   void finishedExplicitCaptures() {
367     NumExplicitCaptures = Captures.size();
368   }
369   
370   static bool classof(const FunctionScopeInfo *FSI) { 
371     return FSI->Kind == SK_Lambda; 
372   }
373   static bool classof(const LambdaScopeInfo *BSI) { return true; }
374
375 };
376
377 }
378 }
379
380 #endif