diff options
Diffstat (limited to 'include/clang/Sema/ScopeInfo.h')
-rw-r--r-- | include/clang/Sema/ScopeInfo.h | 226 |
1 files changed, 203 insertions, 23 deletions
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index b4752f5..feda9c9 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file defines FunctionScopeInfo and BlockScopeInfo. +// This file defines FunctionScopeInfo and its subclasses, which contain +// information about a single function, block, lambda, or method body. // //===----------------------------------------------------------------------===// @@ -21,14 +22,20 @@ namespace clang { +class Decl; class BlockDecl; class CXXMethodDecl; +class ObjCPropertyDecl; class IdentifierInfo; class LabelDecl; class ReturnStmt; class Scope; class SwitchStmt; class VarDecl; +class DeclRefExpr; +class ObjCIvarRefExpr; +class ObjCPropertyRefExpr; +class ObjCMessageExpr; namespace sema { @@ -84,13 +91,10 @@ public: /// \brief Whether this function contains any indirect gotos. bool HasIndirectGoto; - /// A flag that is set when parsing a -dealloc method and no [super dealloc] - /// call was found yet. - bool ObjCShouldCallSuperDealloc; - - /// A flag that is set when parsing a -finalize method and no [super finalize] - /// call was found yet. - bool ObjCShouldCallSuperFinalize; + /// A flag that is set when parsing a method that must call super's + /// implementation, such as \c -dealloc, \c -finalize, or any method marked + /// with \c __attribute__((objc_requires_super)). + bool ObjCShouldCallSuper; /// \brief Used to determine if errors occurred in this function or block. DiagnosticErrorTrap ErrorTrap; @@ -113,6 +117,164 @@ public: /// prior to being emitted. SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; +public: + /// Represents a simple identification of a weak object. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + /// + /// This is used to determine if two weak accesses refer to the same object. + /// Here are some examples of how various accesses are "profiled": + /// + /// Access Expression | "Base" Decl | "Property" Decl + /// :---------------: | :-----------------: | :------------------------------: + /// self.property | self (VarDecl) | property (ObjCPropertyDecl) + /// self.implicitProp | self (VarDecl) | -implicitProp (ObjCMethodDecl) + /// self->ivar.prop | ivar (ObjCIvarDecl) | prop (ObjCPropertyDecl) + /// cxxObj.obj.prop | obj (FieldDecl) | prop (ObjCPropertyDecl) + /// [self foo].prop | 0 (unknown) | prop (ObjCPropertyDecl) + /// self.prop1.prop2 | prop1 (ObjCPropertyDecl) | prop2 (ObjCPropertyDecl) + /// MyClass.prop | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl) + /// weakVar | 0 (known) | weakVar (VarDecl) + /// self->weakIvar | self (VarDecl) | weakIvar (ObjCIvarDecl) + /// + /// Objects are identified with only two Decls to make it reasonably fast to + /// compare them. + class WeakObjectProfileTy { + /// The base object decl, as described in the class documentation. + /// + /// The extra flag is "true" if the Base and Property are enough to uniquely + /// identify the object in memory. + /// + /// \sa isExactProfile() + typedef llvm::PointerIntPair<const NamedDecl *, 1, bool> BaseInfoTy; + BaseInfoTy Base; + + /// The "property" decl, as described in the class documentation. + /// + /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the + /// case of "implicit" properties (regular methods accessed via dot syntax). + const NamedDecl *Property; + + /// Used to find the proper base profile for a given base expression. + static BaseInfoTy getBaseInfo(const Expr *BaseE); + + // For use in DenseMap. + friend class DenseMapInfo; + inline WeakObjectProfileTy(); + static inline WeakObjectProfileTy getSentinel(); + + public: + WeakObjectProfileTy(const ObjCPropertyRefExpr *RE); + WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property); + WeakObjectProfileTy(const DeclRefExpr *RE); + WeakObjectProfileTy(const ObjCIvarRefExpr *RE); + + const NamedDecl *getBase() const { return Base.getPointer(); } + const NamedDecl *getProperty() const { return Property; } + + /// Returns true if the object base specifies a known object in memory, + /// rather than, say, an instance variable or property of another object. + /// + /// Note that this ignores the effects of aliasing; that is, \c foo.bar is + /// considered an exact profile if \c foo is a local variable, even if + /// another variable \c foo2 refers to the same object as \c foo. + /// + /// For increased precision, accesses with base variables that are + /// properties or ivars of 'self' (e.g. self.prop1.prop2) are considered to + /// be exact, though this is not true for arbitrary variables + /// (foo.prop1.prop2). + bool isExactProfile() const { + return Base.getInt(); + } + + bool operator==(const WeakObjectProfileTy &Other) const { + return Base == Other.Base && Property == Other.Property; + } + + // For use in DenseMap. + // We can't specialize the usual llvm::DenseMapInfo at the end of the file + // because by that point the DenseMap in FunctionScopeInfo has already been + // instantiated. + class DenseMapInfo { + public: + static inline WeakObjectProfileTy getEmptyKey() { + return WeakObjectProfileTy(); + } + static inline WeakObjectProfileTy getTombstoneKey() { + return WeakObjectProfileTy::getSentinel(); + } + + static unsigned getHashValue(const WeakObjectProfileTy &Val) { + typedef std::pair<BaseInfoTy, const NamedDecl *> Pair; + return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base, + Val.Property)); + } + + static bool isEqual(const WeakObjectProfileTy &LHS, + const WeakObjectProfileTy &RHS) { + return LHS == RHS; + } + }; + }; + + /// Represents a single use of a weak object. + /// + /// Stores both the expression and whether the access is potentially unsafe + /// (i.e. it could potentially be warned about). + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + class WeakUseTy { + llvm::PointerIntPair<const Expr *, 1, bool> Rep; + public: + WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {} + + const Expr *getUseExpr() const { return Rep.getPointer(); } + bool isUnsafe() const { return Rep.getInt(); } + void markSafe() { Rep.setInt(false); } + + bool operator==(const WeakUseTy &Other) const { + return Rep == Other.Rep; + } + }; + + /// Used to collect uses of a particular weak object in a function body. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + typedef SmallVector<WeakUseTy, 4> WeakUseVector; + + /// Used to collect all uses of weak objects in a function body. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + typedef llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8, + WeakObjectProfileTy::DenseMapInfo> + WeakObjectUseMap; + +private: + /// Used to collect all uses of weak objects in this function body. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + WeakObjectUseMap WeakObjectUses; + +public: + /// Record that a weak object was accessed. + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + template <typename ExprT> + inline void recordUseOfWeak(const ExprT *E, bool IsRead = true); + + void recordUseOfWeak(const ObjCMessageExpr *Msg, + const ObjCPropertyDecl *Prop); + + /// Record that a given expression is a "safe" access of a weak object (e.g. + /// assigning it to a strong variable.) + /// + /// Part of the implementation of -Wrepeated-use-of-weak. + void markSafeWeakUse(const Expr *E); + + const WeakObjectUseMap &getWeakObjectUses() const { + return WeakObjectUses; + } + void setHasBranchIntoScope() { HasBranchIntoScope = true; } @@ -135,8 +297,7 @@ public: HasBranchProtectedScope(false), HasBranchIntoScope(false), HasIndirectGoto(false), - ObjCShouldCallSuperDealloc(false), - ObjCShouldCallSuperFinalize(false), + ObjCShouldCallSuper(false), ErrorTrap(Diag) { } virtual ~FunctionScopeInfo(); @@ -144,8 +305,6 @@ public: /// \brief Clear out the information in this function scope, making it /// suitable for reuse. void Clear(); - - static bool classof(const FunctionScopeInfo *FSI) { return true; } }; class CapturingScopeInfo : public FunctionScopeInfo { @@ -262,11 +421,7 @@ public: } void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType, - Expr *Cpy) { - Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, - Cpy)); - CXXThisCaptureIndex = Captures.size(); - } + Expr *Cpy); /// \brief Determine whether the C++ 'this' is captured. bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } @@ -299,7 +454,6 @@ public: static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda; } - static bool classof(const CapturingScopeInfo *BSI) { return true; } }; /// \brief Retains information about a block that is currently being parsed. @@ -327,7 +481,6 @@ public: static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_Block; } - static bool classof(const BlockScopeInfo *BSI) { return true; } }; class LambdaScopeInfo : public CapturingScopeInfo { @@ -379,15 +532,42 @@ public: void finishedExplicitCaptures() { NumExplicitCaptures = Captures.size(); } - - static bool classof(const FunctionScopeInfo *FSI) { + + static bool classof(const FunctionScopeInfo *FSI) { return FSI->Kind == SK_Lambda; } - static bool classof(const LambdaScopeInfo *BSI) { return true; } - }; + +FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy() + : Base(0, false), Property(0) {} + +FunctionScopeInfo::WeakObjectProfileTy +FunctionScopeInfo::WeakObjectProfileTy::getSentinel() { + FunctionScopeInfo::WeakObjectProfileTy Result; + Result.Base.setInt(true); + return Result; +} + +template <typename ExprT> +void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { + assert(E); + WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)]; + Uses.push_back(WeakUseTy(E, IsRead)); } + +inline void +CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc, + QualType CaptureType, Expr *Cpy) { + Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, + Cpy)); + CXXThisCaptureIndex = Captures.size(); + + if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(this)) + LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size()); } +} // end namespace sema +} // end namespace clang + #endif |