/// \sa mayInlineTemplateFunctions
llvm::Optional<bool> InlineTemplateFunctions;
+ /// \sa mayInlineObjCMethod
+ llvm::Optional<bool> ObjCInliningMode;
+
// Cache of the "ipa-always-inline-size" setting.
// \sa getAlwaysInlineSize
llvm::Optional<unsigned> AlwaysInlineSize;
/// \sa CXXMemberInliningMode
bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const;
+ /// Returns true if ObjectiveC inlining is enabled, false otherwise.
+ bool mayInlineObjCMethod() const;
+
/// Returns whether or not the destructors for C++ temporary objects should
/// be included in the CFG.
///
return *InlineTemplateFunctions;
}
+bool AnalyzerOptions::mayInlineObjCMethod() const {
+ if (!ObjCInliningMode.hasValue())
+ const_cast<llvm::Optional<bool> &>(ObjCInliningMode) =
+ getBooleanOption("objc-inlining", /*Default=*/true);
+
+ return *ObjCInliningMode;
+}
+
int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) const {
std::string OptStr = Config.lookup(Name);
if (OptStr.empty())
unsigned AnalyzerOptions::getAlwaysInlineSize() const {
if (!AlwaysInlineSize.hasValue()) {
unsigned DefaultSize = 3;
- Optional<unsigned> &MutableOption =
- const_cast<Optional<unsigned> &>(AlwaysInlineSize);
- MutableOption = getOptionAsInteger("ipa-always-inline-size", DefaultSize);
+ const_cast<Optional<unsigned> &>(AlwaysInlineSize) =
+ getOptionAsInteger("ipa-always-inline-size", DefaultSize);
}
return AlwaysInlineSize.getValue();
break;
}
case CE_ObjCMessage:
+ if (!Opts.mayInlineObjCMethod())
+ return false;
if (!(getAnalysisManager().options.IPAMode == DynamicDispatch ||
getAnalysisManager().options.IPAMode == DynamicDispatchBifurcate))
return false;
--- /dev/null
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=dynamic-bifurcate -analyzer-config objc-inlining=false -verify %s
+
+typedef signed char BOOL;
+typedef struct objc_class *Class;
+typedef struct objc_object {
+ Class isa;
+} *id;
+@protocol NSObject - (BOOL)isEqual:(id)object; @end
+@interface NSObject <NSObject> {}
++(id)alloc;
+-(id)init;
+-(id)autorelease;
+-(id)copy;
+- (Class)class;
+-(id)retain;
+@end
+
+// Vanila: ObjC class method is called by name.
+@interface MyParent : NSObject
++ (int)getInt;
+@end
+@interface MyClass : MyParent
++ (int)getInt;
+@end
+@implementation MyClass
++ (int)testClassMethodByName {
+ int y = [MyClass getInt];
+ return 5/y; // no-warning
+}
++ (int)getInt {
+ return 0;
+}
+@end
\ No newline at end of file