From: Anna Zaks Date: Thu, 24 Jan 2013 23:15:34 +0000 (+0000) Subject: [analyzer] Add "-analyzer-config mode=[deep|shallow] ". X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=36d988f02356a0cbbee86b67830cd3bba2b0241c;p=platform%2Fupstream%2Fllvm.git [analyzer] Add "-analyzer-config mode=[deep|shallow] ". The idea is to introduce a higher level "user mode" option for different use scenarios. For example, if one wants to run the analyzer for a small project each time the code is built, they would use the "shallow" mode. The user mode option will influence the default settings for the lower-level analyzer options. For now, this just influences the ipa modes, but we plan to find more optimal settings for them. llvm-svn: 173386 --- diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index aba4388..c52e39c 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -105,8 +105,7 @@ enum IPAKind { /// Inline C functions and blocks when their definitions are available. IPAK_BasicInlining = 2, - /// Inline callees when their definitions are available. - // TODO: How is this different from BasicInlining? + /// Inline callees(C, C++, ObjC) when their definitions are available. IPAK_Inlining = 3, /// Enable inlining of dynamically dispatched methods. @@ -176,6 +175,20 @@ public: AnalysisInliningMode InliningMode; private: + /// \brief Describes the kinds for high-level analyzer mode. + enum UserModeKind { + UMK_NotSet = 0, + /// Perform shallow but fast analyzes. + UMK_Shallow = 1, + /// Perform deep analyzes. + UMK_Deep = 2 + }; + + /// Controls the high-level analyzer mode, which influences the default + /// settings for some of the lower-level config options (such as IPAMode). + /// \sa getUserMode + UserModeKind UserMode; + /// Controls the mode of inter-procedural analysis. IPAKind IPAMode; @@ -224,6 +237,11 @@ private: int getOptionAsInteger(StringRef Name, int DefaultVal); public: + /// \brief Retrieves and sets the UserMode. This is a high-level option, + /// which is used to set other low-level options. It is not accessible + /// outside of AnalyzerOptions. + UserModeKind getUserMode(); + /// \brief Returns the inter-procedural analysis mode. IPAKind getIPAMode(); diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 107b739..c5a69aea 100644 --- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -20,12 +20,34 @@ using namespace clang; using namespace llvm; +AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() { + if (UserMode == UMK_NotSet) { + StringRef ModeStr(Config.GetOrCreateValue("mode", "deep").getValue()); + UserMode = llvm::StringSwitch(ModeStr) + .Case("shallow", UMK_Shallow) + .Case("deep", UMK_Deep) + .Default(UMK_NotSet); + assert(UserMode != UMK_NotSet && "User mode is not set or invalid."); + } + return UserMode; +} + IPAKind AnalyzerOptions::getIPAMode() { if (IPAMode == IPAK_NotSet) { + // Use the User Mode to set the default IPA value. + // Note, we have to add the string to the Config map for the ConfigDumper + // checker to function properly. + const char *DefaultIPA = 0; + UserModeKind HighLevelMode = getUserMode(); + if (HighLevelMode == UMK_Shallow) + DefaultIPA = "basic-inlining"; + else if (HighLevelMode == UMK_Deep) + DefaultIPA = "dynamic-bifurcate"; + assert(DefaultIPA); + // Lookup the ipa configuration option, use the default from User Mode. - StringRef ModeStr(Config.GetOrCreateValue("ipa", - "dynamic-bifurcate").getValue()); + StringRef ModeStr(Config.GetOrCreateValue("ipa", DefaultIPA).getValue()); IPAKind IPAConfig = llvm::StringSwitch(ModeStr) .Case("none", IPAK_None) .Case("basic-inlining", IPAK_BasicInlining) diff --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c index bf9289b..a314f9c 100644 --- a/clang/test/Analysis/analyzer-config.c +++ b/clang/test/Analysis/analyzer-config.c @@ -11,5 +11,6 @@ void foo() { bar(); } // CHECK-NEXT: ipa = dynamic-bifurcate // CHECK-NEXT: ipa-always-inline-size = 3 // CHECK-NEXT: max-times-inline-large = 32 +// CHECK-NEXT: mode = deep // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 6 +// CHECK-NEXT: num-entries = 7 diff --git a/clang/test/Analysis/analyzer-config.cpp b/clang/test/Analysis/analyzer-config.cpp index 46b583d..10a9ff1 100644 --- a/clang/test/Analysis/analyzer-config.cpp +++ b/clang/test/Analysis/analyzer-config.cpp @@ -20,5 +20,6 @@ public: // CHECK-NEXT: ipa = dynamic-bifurcate // CHECK-NEXT: ipa-always-inline-size = 3 // CHECK-NEXT: max-times-inline-large = 32 +// CHECK-NEXT: mode = deep // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 9 +// CHECK-NEXT: num-entries = 10 diff --git a/clang/test/Analysis/shallow-mode.m b/clang/test/Analysis/shallow-mode.m new file mode 100644 index 0000000..23df699 --- /dev/null +++ b/clang/test/Analysis/shallow-mode.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config mode=shallow -verify %s +// expected-no-diagnostics + +void clang_analyzer_checkInlined(unsigned); + +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 {} ++(id)alloc; +-(id)init; +@end + +@interface MyClass : NSObject ++ (void)callee; ++ (void)caller; +@end + +@implementation MyClass ++ (void)caller { + [MyClass callee]; +} ++ (void)callee { + clang_analyzer_checkInlined(0); // The call is not inlined. +} +@end \ No newline at end of file