summaryrefslogtreecommitdiffstats
path: root/include/clang/Sema/ScopeInfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Sema/ScopeInfo.h')
-rw-r--r--include/clang/Sema/ScopeInfo.h226
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
OpenPOWER on IntegriCloud