ScopeInfo.h revision 999713eea940f4e087cc3ac878689c5c5c7a7225
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    /// \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.
296class BlockScopeInfo : public CapturingScopeInfo {
297public:
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
323class LambdaScopeInfo : public CapturingScopeInfo {
324public:
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
381