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