clang API Documentation

ScopeInfo.h
Go to the documentation of this file.
00001 //===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines FunctionScopeInfo and BlockScopeInfo.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H
00015 #define LLVM_CLANG_SEMA_SCOPE_INFO_H
00016 
00017 #include "clang/AST/Type.h"
00018 #include "clang/Basic/PartialDiagnostic.h"
00019 #include "llvm/ADT/DenseMap.h"
00020 #include "llvm/ADT/SmallVector.h"
00021 
00022 namespace clang {
00023 
00024 class BlockDecl;
00025 class CXXMethodDecl;
00026 class IdentifierInfo;
00027 class LabelDecl;
00028 class ReturnStmt;
00029 class Scope;
00030 class SwitchStmt;
00031 class VarDecl;
00032 
00033 namespace sema {
00034 
00035 /// \brief Contains information about the compound statement currently being
00036 /// parsed.
00037 class CompoundScopeInfo {
00038 public:
00039   CompoundScopeInfo()
00040     : HasEmptyLoopBodies(false) { }
00041 
00042   /// \brief Whether this compound stamement contains `for' or `while' loops
00043   /// with empty bodies.
00044   bool HasEmptyLoopBodies;
00045 
00046   void setHasEmptyLoopBodies() {
00047     HasEmptyLoopBodies = true;
00048   }
00049 };
00050 
00051 class PossiblyUnreachableDiag {
00052 public:
00053   PartialDiagnostic PD;
00054   SourceLocation Loc;
00055   const Stmt *stmt;
00056   
00057   PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
00058                           const Stmt *stmt)
00059     : PD(PD), Loc(Loc), stmt(stmt) {}
00060 };
00061     
00062 /// \brief Retains information about a function, method, or block that is
00063 /// currently being parsed.
00064 class FunctionScopeInfo {
00065 protected:
00066   enum ScopeKind {
00067     SK_Function,
00068     SK_Block,
00069     SK_Lambda
00070   };
00071   
00072 public:
00073   /// \brief What kind of scope we are describing.
00074   ///
00075   ScopeKind Kind;
00076 
00077   /// \brief Whether this function contains a VLA, @try, try, C++
00078   /// initializer, or anything else that can't be jumped past.
00079   bool HasBranchProtectedScope;
00080 
00081   /// \brief Whether this function contains any switches or direct gotos.
00082   bool HasBranchIntoScope;
00083 
00084   /// \brief Whether this function contains any indirect gotos.
00085   bool HasIndirectGoto;
00086 
00087   /// \brief Used to determine if errors occurred in this function or block.
00088   DiagnosticErrorTrap ErrorTrap;
00089 
00090   /// SwitchStack - This is the current set of active switch statements in the
00091   /// block.
00092   SmallVector<SwitchStmt*, 8> SwitchStack;
00093 
00094   /// \brief The list of return statements that occur within the function or
00095   /// block, if there is any chance of applying the named return value
00096   /// optimization.
00097   SmallVector<ReturnStmt*, 4> Returns;
00098 
00099   /// \brief The stack of currently active compound stamement scopes in the
00100   /// function.
00101   SmallVector<CompoundScopeInfo, 4> CompoundScopes;
00102 
00103   /// \brief A list of PartialDiagnostics created but delayed within the
00104   /// current function scope.  These diagnostics are vetted for reachability
00105   /// prior to being emitted.
00106   SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags;
00107 
00108   void setHasBranchIntoScope() {
00109     HasBranchIntoScope = true;
00110   }
00111 
00112   void setHasBranchProtectedScope() {
00113     HasBranchProtectedScope = true;
00114   }
00115 
00116   void setHasIndirectGoto() {
00117     HasIndirectGoto = true;
00118   }
00119 
00120   bool NeedsScopeChecking() const {
00121     return HasIndirectGoto ||
00122           (HasBranchProtectedScope && HasBranchIntoScope);
00123   }
00124   
00125   FunctionScopeInfo(DiagnosticsEngine &Diag)
00126     : Kind(SK_Function),
00127       HasBranchProtectedScope(false),
00128       HasBranchIntoScope(false),
00129       HasIndirectGoto(false),
00130       ErrorTrap(Diag) { }
00131 
00132   virtual ~FunctionScopeInfo();
00133 
00134   /// \brief Clear out the information in this function scope, making it
00135   /// suitable for reuse.
00136   void Clear();
00137 
00138   static bool classof(const FunctionScopeInfo *FSI) { return true; }
00139 };
00140 
00141 class CapturingScopeInfo : public FunctionScopeInfo {
00142 public:
00143   enum ImplicitCaptureStyle {
00144     ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block
00145   };
00146 
00147   ImplicitCaptureStyle ImpCaptureStyle;
00148 
00149   class Capture {
00150     // There are two categories of capture: capturing 'this', and capturing
00151     // local variables.  There are three ways to capture a local variable:
00152     // capture by copy in the C++11 sense, capture by reference
00153     // in the C++11 sense, and __block capture.  Lambdas explicitly specify
00154     // capture by copy or capture by reference.  For blocks, __block capture
00155     // applies to variables with that annotation, variables of reference type
00156     // are captured by reference, and other variables are captured by copy.
00157     enum CaptureKind {
00158       Cap_This, Cap_ByCopy, Cap_ByRef, Cap_Block
00159     };
00160 
00161     // The variable being captured (if we are not capturing 'this'),
00162     // and misc bits descibing the capture.
00163     llvm::PointerIntPair<VarDecl*, 2, CaptureKind> VarAndKind;
00164 
00165     // Expression to initialize a field of the given type, and whether this
00166     // is a nested capture; the expression is only required if we are
00167     // capturing ByVal and the variable's type has a non-trivial
00168     // copy constructor.
00169     llvm::PointerIntPair<Expr*, 1, bool> CopyExprAndNested;
00170 
00171     /// \brief The source location at which the first capture occurred..
00172     SourceLocation Loc;
00173     
00174     /// \brief The location of the ellipsis that expands a parameter pack.
00175     SourceLocation EllipsisLoc;
00176     
00177     /// \brief The type as it was captured, which is in effect the type of the
00178     /// non-static data member that would hold the capture.
00179     QualType CaptureType;
00180     
00181   public:
00182     Capture(VarDecl *Var, bool block, bool byRef, bool isNested, 
00183             SourceLocation Loc, SourceLocation EllipsisLoc, 
00184             QualType CaptureType, Expr *Cpy)
00185       : VarAndKind(Var, block ? Cap_Block : byRef ? Cap_ByRef : Cap_ByCopy),
00186         CopyExprAndNested(Cpy, isNested), Loc(Loc), EllipsisLoc(EllipsisLoc),
00187         CaptureType(CaptureType){}
00188 
00189     enum IsThisCapture { ThisCapture };
00190     Capture(IsThisCapture, bool isNested, SourceLocation Loc, 
00191             QualType CaptureType, Expr *Cpy)
00192       : VarAndKind(0, Cap_This), CopyExprAndNested(Cpy, isNested), Loc(Loc),
00193         EllipsisLoc(), CaptureType(CaptureType) { }
00194 
00195     bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; }
00196     bool isVariableCapture() const { return !isThisCapture(); }
00197     bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; }
00198     bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; }
00199     bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; }
00200     bool isNested() { return CopyExprAndNested.getInt(); }
00201 
00202     VarDecl *getVariable() const {
00203       return VarAndKind.getPointer();
00204     }
00205     
00206     /// \brief Retrieve the location at which this variable was captured.
00207     SourceLocation getLocation() const { return Loc; }
00208     
00209     /// \brief Retrieve the source location of the ellipsis, whose presence
00210     /// indicates that the capture is a pack expansion.
00211     SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
00212     
00213     /// \brief Retrieve the capture type for this capture, which is effectively
00214     /// the type of the non-static data member in the lambda/block structure
00215     /// that would store this capture.
00216     QualType getCaptureType() const { return CaptureType; }
00217     
00218     Expr *getCopyExpr() const {
00219       return CopyExprAndNested.getPointer();
00220     }
00221   };
00222 
00223   CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style)
00224     : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0),
00225       HasImplicitReturnType(false)
00226      {}
00227 
00228   /// CaptureMap - A map of captured variables to (index+1) into Captures.
00229   llvm::DenseMap<VarDecl*, unsigned> CaptureMap;
00230 
00231   /// CXXThisCaptureIndex - The (index+1) of the capture of 'this';
00232   /// zero if 'this' is not captured.
00233   unsigned CXXThisCaptureIndex;
00234 
00235   /// Captures - The captures.
00236   SmallVector<Capture, 4> Captures;
00237 
00238   /// \brief - Whether the target type of return statements in this context
00239   /// is deduced (e.g. a lambda or block with omitted return type).
00240   bool HasImplicitReturnType;
00241 
00242   /// ReturnType - The target type of return statements in this context,
00243   /// or null if unknown.
00244   QualType ReturnType;
00245 
00246   void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested,
00247                   SourceLocation Loc, SourceLocation EllipsisLoc, 
00248                   QualType CaptureType, Expr *Cpy) {
00249     Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, 
00250                                EllipsisLoc, CaptureType, Cpy));
00251     CaptureMap[Var] = Captures.size();
00252   }
00253 
00254   void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
00255                       Expr *Cpy) {
00256     Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType,
00257                                Cpy));
00258     CXXThisCaptureIndex = Captures.size();
00259   }
00260 
00261   /// \brief Determine whether the C++ 'this' is captured.
00262   bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
00263   
00264   /// \brief Retrieve the capture of C++ 'this', if it has been captured.
00265   Capture &getCXXThisCapture() {
00266     assert(isCXXThisCaptured() && "this has not been captured");
00267     return Captures[CXXThisCaptureIndex - 1];
00268   }
00269   
00270   /// \brief Determine whether the given variable has been captured.
00271   bool isCaptured(VarDecl *Var) const {
00272     return CaptureMap.count(Var);
00273   }
00274   
00275   /// \brief Retrieve the capture of the given variable, if it has been
00276   /// captured already.
00277   Capture &getCapture(VarDecl *Var) {
00278     assert(isCaptured(Var) && "Variable has not been captured");
00279     return Captures[CaptureMap[Var] - 1];
00280   }
00281 
00282   const Capture &getCapture(VarDecl *Var) const {
00283     llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known
00284       = CaptureMap.find(Var);
00285     assert(Known != CaptureMap.end() && "Variable has not been captured");
00286     return Captures[Known->second - 1];
00287   }
00288 
00289   static bool classof(const FunctionScopeInfo *FSI) { 
00290     return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; 
00291   }
00292   static bool classof(const CapturingScopeInfo *BSI) { return true; }
00293 };
00294 
00295 /// \brief Retains information about a block that is currently being parsed.
00296 class BlockScopeInfo : public CapturingScopeInfo {
00297 public:
00298   BlockDecl *TheDecl;
00299   
00300   /// TheScope - This is the scope for the block itself, which contains
00301   /// arguments etc.
00302   Scope *TheScope;
00303 
00304   /// BlockType - The function type of the block, if one was given.
00305   /// Its return type may be BuiltinType::Dependent.
00306   QualType FunctionType;
00307 
00308   BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block)
00309     : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block),
00310       TheScope(BlockScope)
00311   {
00312     Kind = SK_Block;
00313   }
00314 
00315   virtual ~BlockScopeInfo();
00316 
00317   static bool classof(const FunctionScopeInfo *FSI) { 
00318     return FSI->Kind == SK_Block; 
00319   }
00320   static bool classof(const BlockScopeInfo *BSI) { return true; }
00321 };
00322 
00323 class LambdaScopeInfo : public CapturingScopeInfo {
00324 public:
00325   /// \brief The class that describes the lambda.
00326   CXXRecordDecl *Lambda;
00327 
00328   /// \brief The class that describes the lambda.
00329   CXXMethodDecl *CallOperator;
00330 
00331   /// \brief Source range covering the lambda introducer [...].
00332   SourceRange IntroducerRange;
00333 
00334   /// \brief The number of captures in the \c Captures list that are 
00335   /// explicit captures.
00336   unsigned NumExplicitCaptures;
00337 
00338   /// \brief Whether this is a mutable lambda.
00339   bool Mutable;
00340   
00341   /// \brief Whether the (empty) parameter list is explicit.
00342   bool ExplicitParams;
00343 
00344   /// \brief Whether any of the capture expressions requires cleanups.
00345   bool ExprNeedsCleanups;
00346 
00347   /// \brief Variables used to index into by-copy array captures.
00348   llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
00349 
00350   /// \brief Offsets into the ArrayIndexVars array at which each capture starts
00351   /// its list of array index variables.
00352   llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
00353   
00354   LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
00355                   CXXMethodDecl *CallOperator)
00356     : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
00357       CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false),
00358       ExprNeedsCleanups(false)
00359   {
00360     Kind = SK_Lambda;
00361   }
00362 
00363   virtual ~LambdaScopeInfo();
00364 
00365   /// \brief Note when 
00366   void finishedExplicitCaptures() {
00367     NumExplicitCaptures = Captures.size();
00368   }
00369   
00370   static bool classof(const FunctionScopeInfo *FSI) { 
00371     return FSI->Kind == SK_Lambda; 
00372   }
00373   static bool classof(const LambdaScopeInfo *BSI) { return true; }
00374 
00375 };
00376 
00377 }
00378 }
00379 
00380 #endif