• 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    /// \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  
setHasBranchIntoScope()108    void setHasBranchIntoScope() {
109      HasBranchIntoScope = true;
110    }
111  
setHasBranchProtectedScope()112    void setHasBranchProtectedScope() {
113      HasBranchProtectedScope = true;
114    }
115  
setHasIndirectGoto()116    void setHasIndirectGoto() {
117      HasIndirectGoto = true;
118    }
119  
NeedsScopeChecking()120    bool NeedsScopeChecking() const {
121      return HasIndirectGoto ||
122            (HasBranchProtectedScope && HasBranchIntoScope);
123    }
124  
FunctionScopeInfo(DiagnosticsEngine & Diag)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  
classof(const FunctionScopeInfo * FSI)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:
Capture(VarDecl * Var,bool block,bool byRef,bool isNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,Expr * Cpy)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 };
Capture(IsThisCapture,bool isNested,SourceLocation Loc,QualType CaptureType,Expr * Cpy)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  
isThisCapture()195      bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; }
isVariableCapture()196      bool isVariableCapture() const { return !isThisCapture(); }
isCopyCapture()197      bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; }
isReferenceCapture()198      bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; }
isBlockCapture()199      bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; }
isNested()200      bool isNested() { return CopyExprAndNested.getInt(); }
201  
getVariable()202      VarDecl *getVariable() const {
203        return VarAndKind.getPointer();
204      }
205  
206      /// \brief Retrieve the location at which this variable was captured.
getLocation()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.
getEllipsisLoc()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.
getCaptureType()216      QualType getCaptureType() const { return CaptureType; }
217  
getCopyExpr()218      Expr *getCopyExpr() const {
219        return CopyExprAndNested.getPointer();
220      }
221    };
222  
CapturingScopeInfo(DiagnosticsEngine & Diag,ImplicitCaptureStyle Style)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  
addCapture(VarDecl * Var,bool isBlock,bool isByref,bool isNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,Expr * Cpy)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  
addThisCapture(bool isNested,SourceLocation Loc,QualType CaptureType,Expr * Cpy)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.
isCXXThisCaptured()262    bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
263  
264    /// \brief Retrieve the capture of C++ 'this', if it has been captured.
getCXXThisCapture()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.
isCaptured(VarDecl * Var)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.
getCapture(VarDecl * Var)277    Capture &getCapture(VarDecl *Var) {
278      assert(isCaptured(Var) && "Variable has not been captured");
279      return Captures[CaptureMap[Var] - 1];
280    }
281  
getCapture(VarDecl * Var)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  
classof(const FunctionScopeInfo * FSI)289    static bool classof(const FunctionScopeInfo *FSI) {
290      return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda;
291    }
classof(const CapturingScopeInfo * BSI)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  
BlockScopeInfo(DiagnosticsEngine & Diag,Scope * BlockScope,BlockDecl * Block)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  
classof(const FunctionScopeInfo * FSI)317    static bool classof(const FunctionScopeInfo *FSI) {
318      return FSI->Kind == SK_Block;
319    }
classof(const BlockScopeInfo * BSI)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  
LambdaScopeInfo(DiagnosticsEngine & Diag,CXXRecordDecl * Lambda,CXXMethodDecl * CallOperator)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
finishedExplicitCaptures()366    void finishedExplicitCaptures() {
367      NumExplicitCaptures = Captures.size();
368    }
369  
classof(const FunctionScopeInfo * FSI)370    static bool classof(const FunctionScopeInfo *FSI) {
371      return FSI->Kind == SK_Lambda;
372    }
classof(const LambdaScopeInfo * BSI)373    static bool classof(const LambdaScopeInfo *BSI) { return true; }
374  
375  };
376  
377  }
378  }
379  
380  #endif
381