[cfe-commits] r160991 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h lib/StaticAnalyzer/Core/CallEvent.cpp lib/StaticAnalyzer/Core/ProgramState.cpp lib/StaticAnalyzer/Core/Store.cpp test/Analysis/inlining/InlineObjCInstanceMethod.h test/Analysis/inlining/InlineObjCInstanceMethod.m
Anna Zaks
ganna at apple.com
Mon Jul 30 13:31:29 PDT 2012
Author: zaks
Date: Mon Jul 30 15:31:29 2012
New Revision: 160991
URL: http://llvm.org/viewvc/llvm-project?rev=160991&view=rev
Log:
[analyzer] Very simple ObjC instance method inlining
- Retrieves the type of the object/receiver from the state.
- Binds self during stack setup.
- Only explores the path on which the method is inlined (no
bifurcation to explore the path on which the method is not inlined).
Added:
cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.h
cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.m
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h?rev=160991&r1=160990&r2=160991&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h Mon Jul 30 15:31:29 2012
@@ -695,8 +695,6 @@
virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
virtual QualType getDeclaredResultType() const;
- ObjCMethodDecl *LookupClassMethodDefinition(Selector Sel,
- ObjCInterfaceDecl *ClassDecl) const;
public:
virtual const ObjCMessageExpr *getOriginExpr() const {
@@ -752,22 +750,7 @@
// TODO: We might want to only compute this once (or change the API for
// getting the parameters). Currently, this gets called 3 times during
// inlining.
- virtual const Decl *getRuntimeDefinition() const {
- const ObjCMessageExpr *E = getOriginExpr();
- assert(E);
-
- if (E->isInstanceMessage()) {
- return 0;
- } else {
- // This is a class method.
- // If we have type info for the receiver class, we are calling via
- // class name.
- if (ObjCInterfaceDecl *IDecl = E->getReceiverInterface())
- return LookupClassMethodDefinition(E->getSelector(), IDecl);
- }
-
- return 0;
- }
+ virtual const Decl *getRuntimeDefinition() const;
virtual param_iterator param_begin(bool UseDefinitionParams = false) const;
virtual param_iterator param_end(bool UseDefinitionParams = false) const;
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h?rev=160991&r1=160990&r2=160991&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h Mon Jul 30 15:31:29 2012
@@ -56,6 +56,18 @@
}
};
+/// \class Stores the dynamic type information.
+/// Information about type of an object at runtime. This is used by dynamic
+/// dispatch implementation.
+class DynamicTypeInfo {
+ QualType T;
+
+public:
+ DynamicTypeInfo() : T(QualType()) {}
+ DynamicTypeInfo(QualType WithType) : T(WithType) {}
+ QualType getType() {return T;}
+};
+
/// \class ProgramState
/// ProgramState - This class encapsulates:
///
@@ -313,6 +325,9 @@
bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const;
bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const;
+ /// Get dynamic type information for a region.
+ DynamicTypeInfo getDynamicTypeInfo(const MemRegion *Reg) const;
+
//==---------------------------------------------------------------------==//
// Accessing the Generic Data Map (GDM).
//==---------------------------------------------------------------------==//
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=160991&r1=160990&r2=160991&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Mon Jul 30 15:31:29 2012
@@ -590,34 +590,34 @@
return static_cast<ObjCMessageKind>(Info.getInt());
}
-// TODO: This implementation is copied from SemaExprObjC.cpp, needs to be
-// factored into the ObjCInterfaceDecl.
-ObjCMethodDecl *ObjCMethodCall::LookupClassMethodDefinition(Selector Sel,
- ObjCInterfaceDecl *ClassDecl) const {
- ObjCMethodDecl *Method = 0;
- // Lookup in class and all superclasses.
- while (ClassDecl && !Method) {
- if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
- Method = ImpDecl->getClassMethod(Sel);
-
- // Look through local category implementations associated with the class.
- if (!Method)
- Method = ClassDecl->getCategoryClassMethod(Sel);
-
- // Before we give up, check if the selector is an instance method.
- // But only in the root. This matches gcc's behavior and what the
- // runtime expects.
- if (!Method && !ClassDecl->getSuperClass()) {
- Method = ClassDecl->lookupInstanceMethod(Sel);
- // Look through local category implementations associated
- // with the root class.
- //if (!Method)
- // Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+const Decl *ObjCMethodCall::getRuntimeDefinition() const {
+ const ObjCMessageExpr *E = getOriginExpr();
+ Selector Sel = E->getSelector();
+ assert(E);
+
+ if (E->isInstanceMessage()) {
+ const MemRegion *Receiver = getReceiverSVal().getAsRegion();
+ DynamicTypeInfo TI = getState()->getDynamicTypeInfo(Receiver);
+ const ObjCObjectPointerType *T =
+ dyn_cast<ObjCObjectPointerType>(TI.getType().getTypePtr());
+ if (!T)
+ return 0;
+ if (ObjCInterfaceDecl *IDecl = T->getInterfaceDecl()) {
+ // Find the method implementation.
+ return IDecl->lookupPrivateMethod(Sel);
}
- ClassDecl = ClassDecl->getSuperClass();
+ } else {
+ // This is a class method.
+ // If we have type info for the receiver class, we are calling via
+ // class name.
+ if (ObjCInterfaceDecl *IDecl = E->getReceiverInterface()) {
+ // Find/Return the method implementation.
+ return IDecl->lookupPrivateClassMethod(Sel);
+ }
}
- return Method;
+
+ return 0;
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=160991&r1=160990&r2=160991&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Mon Jul 30 15:31:29 2012
@@ -731,3 +731,12 @@
return Tainted;
}
+
+DynamicTypeInfo ProgramState::getDynamicTypeInfo(const MemRegion *Reg) const {
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(Reg))
+ return DynamicTypeInfo(TR->getLocationType());
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg))
+ return DynamicTypeInfo(SR->getSymbol()
+ ->getType(getStateManager().getContext()));
+ return DynamicTypeInfo();
+}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp?rev=160991&r1=160990&r2=160991&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp Mon Jul 30 15:31:29 2012
@@ -53,6 +53,13 @@
Store = Bind(Store.getStore(), ThisRegion, ThisVal);
}
+ if (const ObjCMethodCall *MCall = dyn_cast<ObjCMethodCall>(&Call)) {
+ SVal SelfVal = MCall->getReceiverSVal();
+ const VarDecl *SelfDecl = LCtx->getAnalysisDeclContext()->getSelfDecl();
+ Store = Bind(Store.getStore(),
+ svalBuilder.makeLoc(MRMgr.getVarRegion(SelfDecl, LCtx)),
+ SelfVal);
+ }
return Store;
}
Added: cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.h?rev=160991&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.h (added)
+++ cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.h Mon Jul 30 15:31:29 2012
@@ -0,0 +1,19 @@
+
+// Define a public header for the ObjC methods that are "visible" externally
+// and, thus, could be sub-classed. We should explore the path on which these
+// are sub-classed with unknown class by not inlining them.
+
+typedef signed char BOOL;
+typedef struct objc_class *Class;
+typedef struct objc_object {
+ Class isa;
+} *id;
+ at protocol NSObject - (BOOL)isEqual:(id)object; @end
+ at interface NSObject <NSObject> {}
++(id)alloc;
+-(id)init;
+-(id)autorelease;
+-(id)copy;
+- (Class)class;
+-(id)retain;
+ at end
Added: cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.m?rev=160991&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.m (added)
+++ cfe/trunk/test/Analysis/inlining/InlineObjCInstanceMethod.m Mon Jul 30 15:31:29 2012
@@ -0,0 +1,80 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=dynamic -verify %s
+
+#include "InlineObjCInstanceMethod.h"
+
+// Method is defined in the parent; called through self.
+ at interface MyParent : NSObject
+- (int)getInt;
+ at end
+ at implementation MyParent
+- (int)getInt {
+ return 0;
+}
+ at end
+
+ at interface MyClass : MyParent
+ at end
+ at implementation MyClass
+- (int)testDynDispatchSelf {
+ int y = [self getInt];
+ return 5/y; // expected-warning {{Division by zero}}
+}
+
+// Method is called on inited object.
++ (int)testAllocInit {
+ MyClass *a = [[self alloc] init];
+ return 5/[a getInt]; // todo
+}
+
+// Method is called on inited object.
++ (int)testAllocInit2 {
+ MyClass *a = [[MyClass alloc] init];
+ return 5/[a getInt]; // todo
+}
+
+// Method is called on a parameter.
++ (int)testParam: (MyClass*) a {
+ return 5/[a getInt]; // expected-warning {{Division by zero}}
+}
+
+// Method is called on a parameter of unnown type.
++ (int)testParamUnknownType: (id) a {
+ return 5/[a getInt]; // no warning
+}
+
+ at end
+
+// TODO: When method is inlined, the attribute reset should be visible.
+ at interface TestSettingAnAttributeInCallee : NSObject {
+ int _attribute;
+}
+ - (void) method2;
+ at end
+
+ at implementation TestSettingAnAttributeInCallee
+- (int) method1 {
+ [self method2];
+ return 5/_attribute; // expected-warning {{Division by zero}}
+}
+
+- (void) method2 {
+ _attribute = 0;
+}
+ at end
+
+ at interface TestSettingAnAttributeInCaller : NSObject {
+ int _attribute;
+}
+ - (int) method2;
+ at end
+
+ at implementation TestSettingAnAttributeInCaller
+- (void) method1 {
+ _attribute = 0;
+ [self method2];
+}
+
+- (int) method2 {
+ return 5/_attribute; // expected-warning {{Division by zero}}
+}
+ at end
\ No newline at end of file
More information about the cfe-commits
mailing list