Szelethus updated this revision to Diff 172856.
Szelethus set the repository for this revision to rC Clang.
Szelethus added a comment.

- Moved initializer functions to `CompilerInvocation.cpp`, like every other 
Options-like class.
- The fields for options are no longer `Optional`
- Fixed the test files


Repository:
  rC Clang

https://reviews.llvm.org/D53692

Files:
  include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
  include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
  lib/Frontend/CompilerInvocation.cpp
  lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
  lib/StaticAnalyzer/Checkers/MallocChecker.cpp
  lib/StaticAnalyzer/Core/AnalysisManager.cpp
  lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
  lib/StaticAnalyzer/Core/BugReporter.cpp
  lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
  lib/StaticAnalyzer/Core/CallEvent.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
  lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
  lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  lib/StaticAnalyzer/Core/SValBuilder.cpp
  lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
  lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
  lib/StaticAnalyzer/Frontend/ModelInjector.cpp
  test/Analysis/analyzer-config.c
  test/Analysis/analyzer-config.cpp

Index: test/Analysis/analyzer-config.cpp
===================================================================
--- test/Analysis/analyzer-config.cpp
+++ test/Analysis/analyzer-config.cpp
@@ -1,24 +1,10 @@
 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
 // RUN: FileCheck --input-file=%t %s --match-full-lines
 
-void bar() {}
-void foo() {
-  // Call bar 33 times so max-times-inline-large is met and
-  // min-blocks-for-inline-large is checked
-  for (int i = 0; i < 34; ++i) {
-    bar();
-  }
-}
-
-class Foo {
-public:
-  ~Foo() {}
-  void baz() { Foo(); }
-	void bar() { const Foo &f = Foo(); }
-	void foo() { bar(); }
-};
-
 // CHECK: [config]
+// CHECK-NEXT: aggressive-binary-operation-simplification = false
+// CHECK-NEXT: avoid-suppressing-null-argument-paths = false
+// CHECK-NEXT: c++-allocator-inlining = true
 // CHECK-NEXT: c++-container-inlining = false
 // CHECK-NEXT: c++-inlining = destructors
 // CHECK-NEXT: c++-shared_ptr-inlining = false
@@ -32,8 +18,12 @@
 // CHECK-NEXT: cfg-rich-constructors = true
 // CHECK-NEXT: cfg-scopes = false
 // CHECK-NEXT: cfg-temporary-dtors = true
+// CHECK-NEXT: crosscheck-with-z3 = false
+// CHECK-NEXT: ctu-dir = ""
+// CHECK-NEXT: ctu-index-name = externalFnMap.txt
 // CHECK-NEXT: eagerly-assume = true
 // CHECK-NEXT: elide-constructors = true
+// CHECK-NEXT:expand-macros = false
 // CHECK-NEXT: experimental-enable-naive-ctu-analysis = false
 // CHECK-NEXT: exploration_strategy = unexplored_first_queue
 // CHECK-NEXT: faux-bodies = true
@@ -43,12 +33,22 @@
 // CHECK-NEXT: ipa-always-inline-size = 3
 // CHECK-NEXT: max-inlinable-size = 100
 // CHECK-NEXT: max-nodes = 225000
+// CHECK-NEXT: max-symbol-complexity = 35
 // CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
 // CHECK-NEXT: mode = deep
+// CHECK-NEXT: model-path = ""
+// CHECK-NEXT: notes-as-events = false
+// CHECK-NEXT: objc-inlining = true
+// CHECK-NEXT: prune-paths = true
 // CHECK-NEXT: region-store-small-struct-limit = 2
+// CHECK-NEXT: report-in-main-source-file = false
 // CHECK-NEXT: serialize-stats = false
+// CHECK-NEXT: stable-report-filename = false
+// CHECK-NEXT: suppress-c++-stdlib = true
+// CHECK-NEXT: suppress-inlined-defensive-checks = true
+// CHECK-NEXT: suppress-null-return-paths = true
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 31
+// CHECK-NEXT: num-entries = 48
Index: test/Analysis/analyzer-config.c
===================================================================
--- test/Analysis/analyzer-config.c
+++ test/Analysis/analyzer-config.c
@@ -1,39 +1,54 @@
 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
 // RUN: FileCheck --input-file=%t %s --match-full-lines
 
-void bar() {}
-void foo() {
-  // Call bar 33 times so max-times-inline-large is met and
-  // min-blocks-for-inline-large is checked
-  for (int i = 0; i < 34; ++i) {
-    bar();
-  }
-}
-
 // CHECK: [config]
+// CHECK-NEXT: aggressive-binary-operation-simplification = false
+// CHECK-NEXT: avoid-suppressing-null-argument-paths = false
+// CHECK-NEXT: c++-allocator-inlining = true
+// CHECK-NEXT: c++-container-inlining = false
+// CHECK-NEXT: c++-inlining = destructors
+// CHECK-NEXT: c++-shared_ptr-inlining = false
+// CHECK-NEXT: c++-stdlib-inlining = true
+// CHECK-NEXT: c++-temp-dtor-inlining = true
+// CHECK-NEXT: c++-template-inlining = true
 // CHECK-NEXT: cfg-conditional-static-initializers = true
 // CHECK-NEXT: cfg-implicit-dtors = true
 // CHECK-NEXT: cfg-lifetime = false
 // CHECK-NEXT: cfg-loopexit = false
 // CHECK-NEXT: cfg-rich-constructors = true
 // CHECK-NEXT: cfg-scopes = false
 // CHECK-NEXT: cfg-temporary-dtors = true
+// CHECK-NEXT: crosscheck-with-z3 = false
+// CHECK-NEXT: ctu-dir = ""
+// CHECK-NEXT: ctu-index-name = externalFnMap.txt
 // CHECK-NEXT: eagerly-assume = true
 // CHECK-NEXT: elide-constructors = true
+// CHECK-NEXT: expand-macros = false
+// CHECK-NEXT: experimental-enable-naive-ctu-analysis = false
 // CHECK-NEXT: exploration_strategy = unexplored_first_queue
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: graph-trim-interval = 1000
 // CHECK-NEXT: inline-lambdas = true
 // CHECK-NEXT: ipa = dynamic-bifurcate
 // CHECK-NEXT: ipa-always-inline-size = 3
 // CHECK-NEXT: max-inlinable-size = 100
 // CHECK-NEXT: max-nodes = 225000
+// CHECK-NEXT: max-symbol-complexity = 35
 // CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
 // CHECK-NEXT: mode = deep
+// CHECK-NEXT: model-path = ""
+// CHECK-NEXT: notes-as-events = false
+// CHECK-NEXT: objc-inlining = true
+// CHECK-NEXT: prune-paths = true
 // CHECK-NEXT: region-store-small-struct-limit = 2
+// CHECK-NEXT: report-in-main-source-file = false
 // CHECK-NEXT: serialize-stats = false
+// CHECK-NEXT: stable-report-filename = false
+// CHECK-NEXT: suppress-c++-stdlib = true
+// CHECK-NEXT: suppress-inlined-defensive-checks = true
+// CHECK-NEXT: suppress-null-return-paths = true
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 24
+// CHECK-NEXT: num-entries = 48
Index: lib/StaticAnalyzer/Frontend/ModelInjector.cpp
===================================================================
--- lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -48,7 +48,7 @@
   FileID mainFileID = SM.getMainFileID();
 
   AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
-  llvm::StringRef modelPath = analyzerOpts->getModelPath();
+  llvm::StringRef modelPath = analyzerOpts->ModelPath;
 
   llvm::SmallString<128> fileName;
 
Index: lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
===================================================================
--- lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -204,7 +204,7 @@
         PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
         Plugins(plugins), Injector(injector), CTU(CI) {
     DigestAnalyzerOptions();
-    if (Opts->PrintStats || Opts->shouldSerializeStats()) {
+    if (Opts->PrintStats || Opts->ShouldSerializeStats) {
       AnalyzerTimers = llvm::make_unique<llvm::TimerGroup>(
           "analyzer", "Analyzer timers");
       TUTotalTimer = llvm::make_unique<llvm::Timer>(
@@ -739,7 +739,7 @@
 
   // Execute the worklist algorithm.
   Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
-                      Mgr->options.getMaxNodesPerTopLevelFunction());
+                      Mgr->options.MaxNodesPerTopLevelFunction);
 
   if (!Mgr->options.DumpExplodedGraphTo.empty())
     Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
Index: lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
===================================================================
--- lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -459,7 +459,7 @@
   // FIXME: After putting complexity threshold to the symbols we can always
   //        rearrange additive operations but rearrange comparisons only if
   //        option is set.
-  if(!Opts.shouldAggressivelySimplifyBinaryOperation())
+  if(!Opts.ShouldAggressivelySimplifyBinaryOperation)
     return None;
 
   SymbolRef LSym = Lhs.getAsSymbol();
Index: lib/StaticAnalyzer/Core/SValBuilder.cpp
===================================================================
--- lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -385,7 +385,7 @@
   // instead of generating an Unknown value and propagate the taint info to it.
   const unsigned MaxComp = StateMgr.getOwningEngine()
                                ->getAnalysisManager()
-                               .options.getMaxSymbolComplexity();
+                               .options.MaxSymbolComplexity;
 
   if (symLHS && symRHS &&
       (symLHS->computeComplexity() + symRHS->computeComplexity()) <  MaxComp)
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===================================================================
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -350,7 +350,7 @@
     if (SubEngine *Eng = StateMgr.getOwningEngine()) {
       AnalyzerOptions &Options = Eng->getAnalysisManager().options;
       SmallStructLimit =
-        Options.getRegionStoreSmallStructLimit();
+        Options.RegionStoreSmallStructLimit;
     }
   }
 
Index: lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
===================================================================
--- lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -476,7 +476,7 @@
 
   o << "   </array>\n";
 
-  if (!AnOpts.shouldDisplayMacroExpansions())
+  if (!AnOpts.ShouldDisplayMacroExpansions)
     return;
 
   o << "   <key>macro_expansions</key>\n"
@@ -709,7 +709,7 @@
     EmitString(o << "  ", SM.getFileEntryForID(FID)->getName()) << '\n';
   o << " </array>\n";
 
-  if (llvm::AreStatisticsEnabled() && AnOpts.shouldSerializeStats()) {
+  if (llvm::AreStatisticsEnabled() && AnOpts.ShouldSerializeStats) {
     o << " <key>statistics</key>\n";
     std::string stats;
     llvm::raw_string_ostream os(stats);
Index: lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
===================================================================
--- lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -218,7 +218,7 @@
   int FD;
   SmallString<128> Model, ResultPath;
 
-  if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
+  if (!AnalyzerOpts.ShouldWriteStableReportFilename) {
       llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
       if (std::error_code EC =
           llvm::sys::fs::make_absolute(Model)) {
Index: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -349,7 +349,7 @@
                                                         /*WasInlined=*/true);
     } else if (CE &&
                !(isa<CXXNewExpr>(CE) && // Called when visiting CXXNewExpr.
-                 AMgr.getAnalyzerOptions().mayInlineCXXAllocator())) {
+                 AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) {
       getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE,
                                                  *this, /*WasInlined=*/true);
     } else {
@@ -386,7 +386,7 @@
       // Do not count the small functions when determining the stack depth.
       AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
       const CFG *CalleeCFG = CalleeADC->getCFG();
-      if (CalleeCFG->getNumBlockIDs() > AMgr.options.getAlwaysInlineSize())
+      if (CalleeCFG->getNumBlockIDs() > AMgr.options.AlwaysInlineSize)
         ++StackDepth;
     }
     LCtx = LCtx->getParent();
@@ -683,7 +683,7 @@
                                         : nullptr;
 
     if (CC && isa<NewAllocatedObjectConstructionContext>(CC) &&
-        !Opts.mayInlineCXXAllocator())
+        !Opts.MayInlineCXXAllocator)
       return CIP_DisallowedOnce;
 
     // FIXME: We don't handle constructors or destructors for arrays properly.
@@ -712,7 +712,7 @@
       // If we don't handle temporary destructors, we shouldn't inline
       // their constructors.
       if (CallOpts.IsTemporaryCtorOrDtor &&
-          !Opts.includeTemporaryDtorsInCFG())
+          !Opts.ShouldIncludeTemporaryDtorsInCFG)
         return CIP_DisallowedOnce;
 
       // If we did not find the correct this-region, it would be pointless
@@ -743,7 +743,8 @@
       return CIP_DisallowedOnce;
 
     // Allow disabling temporary destructor inlining with a separate option.
-    if (CallOpts.IsTemporaryCtorOrDtor && !Opts.mayInlineCXXTemporaryDtors())
+    if (CallOpts.IsTemporaryCtorOrDtor &&
+        !Opts.MayInlineCXXTemporaryDtors)
       return CIP_DisallowedOnce;
 
     // If we did not find the correct this-region, it would be pointless
@@ -754,13 +755,13 @@
     break;
   }
   case CE_CXXAllocator:
-    if (Opts.mayInlineCXXAllocator())
+    if (Opts.MayInlineCXXAllocator)
       break;
     // Do not inline allocators until we model deallocators.
     // This is unfortunate, but basically necessary for smart pointers and such.
     return CIP_DisallowedAlways;
   case CE_ObjCMessage:
-    if (!Opts.mayInlineObjCMethod())
+    if (!Opts.MayInlineObjCMethod)
       return CIP_DisallowedAlways;
     if (!(Opts.getIPAMode() == IPAK_DynamicDispatch ||
           Opts.getIPAMode() == IPAK_DynamicDispatchBifurcate))
@@ -844,28 +845,28 @@
   if (Ctx.getLangOpts().CPlusPlus) {
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeADC->getDecl())) {
       // Conditionally control the inlining of template functions.
-      if (!Opts.mayInlineTemplateFunctions())
+      if (!Opts.MayInlineTemplateFunctions)
         if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
           return false;
 
       // Conditionally control the inlining of C++ standard library functions.
-      if (!Opts.mayInlineCXXStandardLibrary())
+      if (!Opts.MayInlineCXXStandardLibrary)
         if (Ctx.getSourceManager().isInSystemHeader(FD->getLocation()))
           if (AnalysisDeclContext::isInStdNamespace(FD))
             return false;
 
       // Conditionally control the inlining of methods on objects that look
       // like C++ containers.
-      if (!Opts.mayInlineCXXContainerMethods())
+      if (!Opts.MayInlineCXXContainerMethods)
         if (!AMgr.isInCodeFile(FD->getLocation()))
           if (isContainerMethod(Ctx, FD))
             return false;
 
       // Conditionally control the inlining of the destructor of C++ shared_ptr.
       // We don't currently do a good job modeling shared_ptr because we can't
       // see the reference count, so treating as opaque is probably the best
       // idea.
-      if (!Opts.mayInlineCXXSharedPtrDtor())
+      if (!Opts.MayInlineCXXSharedPtrDtor)
         if (isCXXSharedPtrDtor(FD))
           return false;
     }
@@ -878,7 +879,7 @@
     return false;
 
   // Do not inline large functions.
-  if (CalleeCFG->getNumBlockIDs() > Opts.getMaxInlinableSize())
+  if (CalleeCFG->getNumBlockIDs() > Opts.MaxInlinableSize)
     return false;
 
   // It is possible that the live variables analysis cannot be
@@ -946,21 +947,21 @@
   unsigned StackDepth = 0;
   examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
   if ((StackDepth >= Opts.InlineMaxStackDepth) &&
-      ((CalleeCFG->getNumBlockIDs() > Opts.getAlwaysInlineSize())
+      ((CalleeCFG->getNumBlockIDs() > Opts.AlwaysInlineSize)
        || IsRecursive))
     return false;
 
   // Do not inline large functions too many times.
   if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
-       Opts.getMaxTimesInlineLarge()) &&
+       Opts.MaxTimesInlineLarge) &&
        CalleeCFG->getNumBlockIDs() >=
-       Opts.getMinCFGSizeTreatFunctionsAsLarge()) {
+       Opts.MinCFGSizeTreatFunctionsAsLarge) {
     NumReachedInlineCountMax++;
     return false;
   }
 
   if (HowToInline == Inline_Minimal &&
-      (CalleeCFG->getNumBlockIDs() > Opts.getAlwaysInlineSize()
+      (CalleeCFG->getNumBlockIDs() > Opts.AlwaysInlineSize
       || IsRecursive))
     return false;
 
Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -159,7 +159,7 @@
       return std::make_pair(State, FieldVal);
     }
     case ConstructionContext::NewAllocatedObjectKind: {
-      if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+      if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
         const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
         const auto *NE = NECC->getCXXNewExpr();
         SVal V = *getObjectUnderConstruction(State, NE, LCtx);
@@ -210,7 +210,7 @@
       llvm_unreachable("Unhandled return value construction context!");
     }
     case ConstructionContext::ElidedTemporaryObjectKind: {
-      assert(AMgr.getAnalyzerOptions().shouldElideConstructors());
+      assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);
       const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
       const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
       const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
@@ -706,7 +706,7 @@
   ProgramStateRef State = Pred->getState();
 
   // Retrieve the stored operator new() return value.
-  if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+  if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
     symVal = *getObjectUnderConstruction(State, CNE, LCtx);
     State = finishObjectConstruction(State, CNE, LCtx);
   }
@@ -726,7 +726,7 @@
   CallEventRef<CXXAllocatorCall> Call =
     CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
 
-  if (!AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+  if (!AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
     // Invalidate placement args.
     // FIXME: Once we figure out how we want allocators to work,
     // we should be using the usual pre-/(default-)eval-/post-call checks here.
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -193,7 +193,7 @@
       svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
       BR(mgr, *this),
       VisitedCallees(VisitedCalleesIn), HowToInline(HowToInlineIn) {
-  unsigned TrimInterval = mgr.options.getGraphTrimInterval();
+  unsigned TrimInterval = mgr.options.GraphTrimInterval;
   if (TrimInterval != 0) {
     // Enable eager node reclaimation when constructing the ExplodedGraph.
     G.enableNodeReclamation(TrimInterval);
@@ -755,7 +755,7 @@
   NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
   ProgramStateRef NewState = Pred->getState();
 
-  if(AMgr.options.shouldUnrollLoops())
+  if(AMgr.options.ShouldUnrollLoops)
     NewState = processLoopEnd(S, NewState);
 
   LoopExit PP(S, Pred->getLocationContext());
@@ -887,7 +887,7 @@
   // TODO: We're not evaluating allocators for all cases just yet as
   // we're not handling the return value correctly, which causes false
   // positives when the alpha.cplusplus.NewDeleteLeaks check is on.
-  if (Opts.mayInlineCXXAllocator())
+  if (Opts.MayInlineCXXAllocator)
     VisitCXXNewAllocatorCall(NE, Pred, Dst);
   else {
     NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
@@ -1102,7 +1102,7 @@
   // This is a fallback solution in case we didn't have a construction
   // context when we were constructing the temporary. Otherwise the map should
   // have been populated there.
-  if (!getAnalysisManager().options.includeTemporaryDtorsInCFG()) {
+  if (!getAnalysisManager().options.ShouldIncludeTemporaryDtorsInCFG) {
     // In case we don't have temporary destructors in the CFG, do not mark
     // the initialization - we would otherwise never clean it up.
     Dst = PreVisit;
@@ -1465,7 +1465,7 @@
       break;
 
     case Stmt::LambdaExprClass:
-      if (AMgr.options.shouldInlineLambdas()) {
+      if (AMgr.options.ShouldInlineLambdas) {
         Bldr.takeNodes(Pred);
         VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
         Bldr.addNodes(Dst);
@@ -1494,7 +1494,7 @@
 
       Bldr.takeNodes(Pred);
 
-      if (AMgr.options.shouldEagerlyAssume() &&
+      if (AMgr.options.ShouldEagerlyAssume &&
           (B->isRelationalOp() || B->isEqualityOp())) {
         ExplodedNodeSet Tmp;
         VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
@@ -1758,7 +1758,7 @@
     case Stmt::UnaryOperatorClass: {
       Bldr.takeNodes(Pred);
       const auto *U = cast<UnaryOperator>(S);
-      if (AMgr.options.shouldEagerlyAssume() && (U->getOpcode() == UO_LNot)) {
+      if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
         ExplodedNodeSet Tmp;
         VisitUnaryOperator(U, Pred, Tmp);
         evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
@@ -1859,7 +1859,7 @@
   PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
   // If we reach a loop which has a known bound (and meets
   // other constraints) then consider completely unrolling it.
-  if(AMgr.options.shouldUnrollLoops()) {
+  if(AMgr.options.ShouldUnrollLoops) {
     unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
     const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
     if (Term) {
@@ -1881,7 +1881,7 @@
   // maximum number of times, widen the loop.
   unsigned int BlockCount = nodeBuilder.getContext().blockCount();
   if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
-      AMgr.options.shouldWidenLoops()) {
+      AMgr.options.ShouldWidenLoops) {
     const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
     if (!(Term &&
           (isa<ForStmt>(Term) || isa<WhileStmt>(Term) || isa<DoStmt>(Term))))
@@ -2382,7 +2382,7 @@
     const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
     Optional<std::pair<SVal, QualType>> VInfo;
 
-    if (AMgr.options.shouldInlineLambdas() && DeclRefEx &&
+    if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
         DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
         MD->getParent()->isLambda()) {
       // Lookup the field of the lambda.
Index: lib/StaticAnalyzer/Core/CallEvent.cpp
===================================================================
--- lib/StaticAnalyzer/Core/CallEvent.cpp
+++ lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -554,13 +554,14 @@
   AnalyzerOptions &Opts = Engine->getAnalysisManager().options;
 
   // Try to get CTU definition only if CTUDir is provided.
-  if (!Opts.naiveCTUEnabled())
+  if (!Opts.IsNaiveCTUEnabled)
     return {};
 
   cross_tu::CrossTranslationUnitContext &CTUCtx =
       *Engine->getCrossTranslationUnitContext();
   llvm::Expected<const FunctionDecl *> CTUDeclOrError =
-      CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName());
+      CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir,
+                                  Opts.CTUIndexName);
 
   if (!CTUDeclOrError) {
     handleAllErrors(CTUDeclOrError.takeError(),
Index: lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
===================================================================
--- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -676,8 +676,8 @@
         bool EnableNullFPSuppression, BugReport &BR,
         const SVal V) {
     AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
-    if (EnableNullFPSuppression && Options.shouldSuppressNullReturnPaths()
-          && V.getAs<Loc>())
+    if (EnableNullFPSuppression &&
+        Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>())
       BR.addVisitor(llvm::make_unique<MacroNullReturnSuppressionVisitor>(
               R->getAs<SubRegion>(), V));
   }
@@ -808,7 +808,8 @@
     AnalyzerOptions &Options = State->getAnalysisManager().options;
 
     bool EnableNullFPSuppression = false;
-    if (InEnableNullFPSuppression && Options.shouldSuppressNullReturnPaths())
+    if (InEnableNullFPSuppression &&
+        Options.ShouldSuppressNullReturnPaths)
       if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
         EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
 
@@ -877,7 +878,7 @@
         // future nodes. We want to emit a path note as well, in case
         // the report is resurrected as valid later on.
         if (EnableNullFPSuppression &&
-            Options.shouldAvoidSuppressingNullArgumentPaths())
+            Options.ShouldAvoidSuppressingNullArgumentPaths)
           Mode = MaybeUnsuppress;
 
         if (RetE->getType()->isObjCObjectPointerType()) {
@@ -925,7 +926,7 @@
   visitNodeMaybeUnsuppress(const ExplodedNode *N,
                            BugReporterContext &BRC, BugReport &BR) {
 #ifndef NDEBUG
-    assert(Options.shouldAvoidSuppressingNullArgumentPaths());
+    assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
 #endif
 
     // Are we at the entry node for this call?
@@ -1378,7 +1379,7 @@
     : V(Value) {
   // Check if the visitor is disabled.
   AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
-  if (!Options.shouldSuppressInlinedDefensiveChecks())
+  if (!Options.ShouldSuppressInlinedDefensiveChecks)
     IsSatisfied = true;
 
   assert(N->getState()->isNull(V).isConstrainedTrue() &&
@@ -2219,7 +2220,7 @@
     // the user's fault, we currently don't report them very well, and
     // Note that this will not help for any other data structure libraries, like
     // TR1, Boost, or llvm/ADT.
-    if (Options.shouldSuppressFromCXXStandardLibrary()) {
+    if (Options.ShouldSuppressFromCXXStandardLibrary) {
       BR.markInvalid(getTag(), nullptr);
       return;
     } else {
Index: lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- lib/StaticAnalyzer/Core/BugReporter.cpp
+++ lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1976,7 +1976,7 @@
 
   // Finally, prune the diagnostic path of uninteresting stuff.
   if (!PD->path.empty()) {
-    if (R->shouldPrunePath() && Opts.shouldPrunePaths()) {
+    if (R->shouldPrunePath() && Opts.ShouldPrunePaths) {
       bool stillHasNotes =
           removeUnneededCalls(PD->getMutablePieces(), R, LCM);
       assert(stillHasNotes);
@@ -2007,7 +2007,7 @@
     removeEdgesToDefaultInitializers(PD->getMutablePieces());
   }
 
-  if (GenerateDiagnostics && Opts.shouldDisplayMacroExpansions())
+  if (GenerateDiagnostics && Opts.ShouldDisplayMacroExpansions)
     CompactMacroExpandedPieces(PD->getMutablePieces(), SM);
 
   return PD;
@@ -2621,7 +2621,7 @@
         generateVisitorsDiagnostics(R, ErrorNode, BRC);
 
     if (R->isValid()) {
-      if (Opts.shouldCrosscheckWithZ3()) {
+      if (Opts.ShouldCrosscheckWithZ3) {
         // If crosscheck is enabled, remove all visitors, add the refutation
         // visitor and check again
         R->clearVisitors();
@@ -2963,7 +2963,7 @@
     }
 
     PathPieces &Pieces = PD->getMutablePieces();
-    if (getAnalyzerOptions().shouldDisplayNotesAsEvents()) {
+    if (getAnalyzerOptions().ShouldDisplayNotesAsEvents) {
       // For path diagnostic consumers that don't support extra notes,
       // we may optionally convert those to path notes.
       for (auto I = report->getNotes().rbegin(),
@@ -3100,7 +3100,7 @@
   // report location to the last piece in the main source file.
   AnalyzerOptions &Opts = getAnalyzerOptions();
   for (auto const &P : *Out)
-    if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll)
+    if (Opts.ShouldReportIssuesInMainSourceFile && !Opts.AnalyzeAll)
       P.second->resetDiagnosticLocationToMainFile();
 
   return Out;
Index: lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
===================================================================
--- lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -49,28 +49,11 @@
   return Result;
 }
 
-UserModeKind AnalyzerOptions::getUserMode() {
-  if (!UserMode.hasValue()) {
-    UserMode = getStringOption("mode", "deep");
-  }
-
-  auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(*UserMode)
-    .Case("shallow", UMK_Shallow)
-    .Case("deep", UMK_Deep)
-    .Default(None);
-  assert(UserMode.hasValue() && "User mode is invalid.");
-  return K.getValue();
-}
-
 ExplorationStrategyKind
-AnalyzerOptions::getExplorationStrategy() {
-  if (!ExplorationStrategy.hasValue()) {
-    ExplorationStrategy = getStringOption("exploration_strategy",
-                                            "unexplored_first_queue");
-  }
+AnalyzerOptions::getExplorationStrategy() const {
   auto K =
     llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
-                                                           *ExplorationStrategy)
+                                                            ExplorationStrategy)
           .Case("dfs", ExplorationStrategyKind::DFS)
           .Case("bfs", ExplorationStrategyKind::BFS)
           .Case("unexplored_first",
@@ -86,18 +69,8 @@
   return K.getValue();
 }
 
-IPAKind AnalyzerOptions::getIPAMode() {
-  if (!IPAMode.hasValue()) {
-    switch (getUserMode()) {
-    case UMK_Shallow:
-      IPAMode = getStringOption("ipa", "inlining");
-      break;
-    case UMK_Deep:
-      IPAMode = getStringOption("ipa", "dynamic-bifurcate");
-      break;
-    }
-  }
-  auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(*IPAMode)
+IPAKind AnalyzerOptions::getIPAMode() const {
+  auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode)
           .Case("none", IPAK_None)
           .Case("basic-inlining", IPAK_BasicInlining)
           .Case("inlining", IPAK_Inlining)
@@ -110,17 +83,14 @@
 }
 
 bool
-AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind Param) {
-  if (!CXXMemberInliningMode.hasValue()) {
-    CXXMemberInliningMode = getStringOption("c++-inlining", "destructors");
-  }
-
+AnalyzerOptions::mayInlineCXXMemberFunction(
+                                          CXXInlineableMemberKind Param) const {
   if (getIPAMode() < IPAK_Inlining)
     return false;
 
   auto K =
     llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
-                                                         *CXXMemberInliningMode)
+                                                          CXXMemberInliningMode)
     .Case("constructors", CIMK_Constructors)
     .Case("destructors", CIMK_Destructors)
     .Case("methods", CIMK_MemberFunctions)
@@ -132,50 +102,6 @@
   return *K >= Param;
 }
 
-StringRef AnalyzerOptions::getStringOption(StringRef OptionName,
-                                           StringRef DefaultVal) {
-  return Config.insert({OptionName, DefaultVal}).first->second;
-}
-
-static StringRef toString(bool B) { return (B ? "true" : "false"); }
-
-template <typename T>
-static StringRef toString(T) = delete;
-
-void AnalyzerOptions::initOption(Optional<StringRef> &V, StringRef Name,
-                                                         StringRef DefaultVal) {
-  if (V.hasValue())
-    return;
-
-  V = getStringOption(Name, DefaultVal);
-}
-
-void AnalyzerOptions::initOption(Optional<bool> &V, StringRef Name,
-                                                    bool DefaultVal) {
-  if (V.hasValue())
-    return;
-
-  // FIXME: We should emit a warning here if the value is something other than
-  // "true", "false", or the empty string (meaning the default value),
-  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
-  V = llvm::StringSwitch<bool>(getStringOption(Name, toString(DefaultVal)))
-      .Case("true", true)
-      .Case("false", false)
-      .Default(DefaultVal);
-}
-
-void AnalyzerOptions::initOption(Optional<unsigned> &V, StringRef Name,
-                                                        unsigned DefaultVal) {
-  if (V.hasValue())
-    return;
-
-  V = DefaultVal;
-  bool HasFailed = getStringOption(Name, std::to_string(DefaultVal))
-                     .getAsInteger(10, *V);
-  assert(!HasFailed && "analyzer-config option should be numeric");
-  (void)HasFailed;
-}
-
 StringRef AnalyzerOptions::getCheckerStringOption(StringRef OptionName,
                                                   StringRef DefaultVal,
                                                   const CheckerBase *C,
@@ -210,7 +136,8 @@
   // but the AnalyzerOptions doesn't have access to a diagnostic engine.
   assert(C);
   return llvm::StringSwitch<bool>(
-      getCheckerStringOption(Name, toString(DefaultVal), C, SearchInParents))
+      getCheckerStringOption(Name, DefaultVal ? "true" : "false", C,
+                             SearchInParents))
       .Case("true", true)
       .Case("false", false)
       .Default(DefaultVal);
@@ -227,12 +154,3 @@
   (void)HasFailed;
   return Ret;
 }
-
-StringRef AnalyzerOptions::getCTUDir() {
-  if (!CTUDir.hasValue()) {
-    CTUDir = getStringOption("ctu-dir", "");
-    if (!llvm::sys::fs::is_directory(*CTUDir))
-      CTUDir = "";
-  }
-  return CTUDir.getValue();
-}
Index: lib/StaticAnalyzer/Core/AnalysisManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -22,16 +22,21 @@
                                  AnalyzerOptions &Options,
                                  CodeInjector *injector)
     : AnaCtxMgr(
-          ASTCtx, Options.UnoptimizedCFG, Options.includeImplicitDtorsInCFG(),
-          /*AddInitializers=*/true, Options.includeTemporaryDtorsInCFG(),
-          Options.includeLifetimeInCFG(),
+          ASTCtx, Options.UnoptimizedCFG,
+          Options.ShouldIncludeImplicitDtorsInCFG,
+          /*AddInitializers=*/true,
+          Options.ShouldIncludeTemporaryDtorsInCFG,
+          Options.ShouldIncludeLifetimeInCFG,
           // Adding LoopExit elements to the CFG is a requirement for loop
           // unrolling.
-          Options.includeLoopExitInCFG() || Options.shouldUnrollLoops(),
-          Options.includeScopesInCFG(), Options.shouldSynthesizeBodies(),
-          Options.shouldConditionalizeStaticInitializers(),
-          /*addCXXNewAllocator=*/true, Options.includeRichConstructorsInCFG(),
-          Options.shouldElideConstructors(), injector),
+          Options.ShouldIncludeLoopExitInCFG ||
+            Options.ShouldUnrollLoops,
+          Options.ShouldIncludeScopesInCFG,
+          Options.ShouldSynthesizeBodies,
+          Options.ShouldConditionalizeStaticInitializers,
+          /*addCXXNewAllocator=*/true,
+          Options.ShouldIncludeRichConstructorsInCFG,
+          Options.ShouldElideConstructors, injector),
       Ctx(ASTCtx), Diags(diags), LangOpts(ASTCtx.getLangOpts()),
       PathConsumers(PDC), CreateStoreMgr(storemgr),
       CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr),
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1094,7 +1094,7 @@
 
 void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
                                   CheckerContext &C) const {
-  if (!C.getAnalysisManager().getAnalyzerOptions().mayInlineCXXAllocator())
+  if (!C.getAnalysisManager().getAnalyzerOptions().MayInlineCXXAllocator)
     processNewAllocation(NE, C, C.getSVal(NE));
 }
 
Index: lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
+++ lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
@@ -182,7 +182,9 @@
 
     llvm::errs() << "[config]\n";
     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
-      llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
+      llvm::errs() << Keys[I]->getKey() << " = "
+                   << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
+                   << '\n';
 
     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
   }
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -181,6 +181,9 @@
   }
 }
 
+static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
+                                 DiagnosticsEngine &Diags);
+
 static void getAllNoBuiltinFuncValues(ArgList &Args,
                                       std::vector<std::string> &Funcs) {
   SmallVector<const char *, 8> Values;
@@ -343,6 +346,8 @@
     }
   }
 
+  parseAnalyzerConfigs(Opts, Diags);
+
   llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
   for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
     if (i != 0)
@@ -354,6 +359,64 @@
   return Success;
 }
 
+static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,
+                                 StringRef OptionName, StringRef DefaultVal) {
+  return Config.insert({OptionName, DefaultVal}).first->second;
+}
+
+static void initOption(AnalyzerOptions::ConfigTable &Config,
+                       StringRef &OptionField, StringRef Name,
+                       StringRef DefaultVal) {
+  OptionField = getStringOption(Config, Name, DefaultVal);
+}
+
+static void initOption(AnalyzerOptions::ConfigTable &Config,
+                       bool &OptionField, StringRef Name, bool DefaultVal) {
+  // FIXME: We should emit a warning here if the value is something other than
+  // "true", "false", or the empty string (meaning the default value),
+  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
+  OptionField = llvm::StringSwitch<bool>(getStringOption(Config, Name,
+                                               (DefaultVal ? "true" : "false")))
+      .Case("true", true)
+      .Case("false", false)
+      .Default(DefaultVal);
+}
+
+static void initOption(AnalyzerOptions::ConfigTable &Config,
+                       unsigned &OptionField, StringRef Name,
+                       unsigned DefaultVal) {
+  OptionField = DefaultVal;
+  bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))
+                     .getAsInteger(10, OptionField);
+  assert(!HasFailed && "analyzer-config option should be numeric");
+  (void)HasFailed;
+}
+
+static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
+                                 DiagnosticsEngine &Diags) {
+  // TODO: Emit warnings for incorrect options.
+  // TODO: There's no need to store the entire configtable, it'd be plenty
+  // enough tostore checker options.
+
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
+  initOption(AnOpts.Config, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);                \
+
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
+                                           SHALLOW_VAL, DEEP_VAL)              \
+  switch (AnOpts.getUserMode()) {                                              \
+  case UMK_Shallow:                                                            \
+    initOption(AnOpts.Config, AnOpts.NAME, CMDFLAG, SHALLOW_VAL);              \
+    break;                                                                     \
+  case UMK_Deep:                                                               \
+    initOption(AnOpts.Config, AnOpts.NAME, CMDFLAG, DEEP_VAL);                 \
+    break;                                                                     \
+  }                                                                            \
+
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
+#undef ANALYZER_OPTION
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+}
+
 static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) {
   Opts.NoNSAllocReallocError = Args.hasArg(OPT_migrator_no_nsalloc_error);
   Opts.NoFinalizeRemoval = Args.hasArg(OPT_migrator_no_finalize_removal);
Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
===================================================================
--- include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -20,6 +20,7 @@
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
 #include <string>
 #include <utility>
 #include <vector>
@@ -170,6 +171,7 @@
   std::vector<std::pair<std::string, bool>> CheckersControlList;
 
   /// A key-value table of use-specified configuration values.
+  // TODO: This shouldn't be public.
   ConfigTable Config;
   AnalysisStores AnalysisStoreOpt = RegionStoreModel;
   AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;
@@ -220,33 +222,17 @@
   /// The mode of function selection used during inlining.
   AnalysisInliningMode InliningMode = NoRedundancy;
 
-private:
-
-#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
-  Optional<TYPE> NAME;
 #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
                                              SHALLOW_VAL, DEEP_VAL)            \
-  Optional<TYPE> NAME;
+  ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL)
+
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
+  TYPE NAME;
+
 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
 #undef ANALYZER_OPTION
 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
 
-  /// Query an option's string value.
-  ///
-  /// If an option value is not provided, returns the given \p DefaultVal.
-  /// @param [in] Name Name for option to retrieve.
-  /// @param [in] DefaultVal Default value returned if no such option was
-  /// specified.
-  StringRef getStringOption(StringRef OptionName, StringRef DefaultVal);
-
-  void initOption(Optional<StringRef> &V, StringRef Name,
-                                          StringRef DefaultVal);
-
-  void initOption(Optional<bool> &V, StringRef Name, bool DefaultVal);
-
-  void initOption(Optional<unsigned> &V, StringRef Name,
-                                         unsigned DefaultVal);
-public:
   AnalyzerOptions()
       : DisableAllChecks(false), ShowCheckerHelp(false),
         ShowEnabledCheckerList(false), AnalyzeAll(false),
@@ -309,56 +295,44 @@
                               const ento::CheckerBase *C,
                               bool SearchInParents = false) const;
 
-#define ANALYZER_OPTION_GEN_FN(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL,  \
-                               CREATE_FN)                               \
-  TYPE CREATE_FN() {                                                    \
-    initOption(NAME, CMDFLAG, DEFAULT_VAL);                             \
-    return NAME.getValue();                                             \
-  }
-
-#define ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE(                    \
-    TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, DEEP_VAL, CREATE_FN)        \
-  TYPE CREATE_FN() {                                                    \
-    switch (getUserMode()) {                                            \
-    case UMK_Shallow:                                                   \
-      initOption(NAME, CMDFLAG, SHALLOW_VAL);                           \
-      break;                                                            \
-    case UMK_Deep:                                                      \
-      initOption(NAME, CMDFLAG, DEEP_VAL);                              \
-      break;                                                            \
-    }                                                                   \
-                                                                        \
-    return NAME.getValue();                                             \
-  }
-
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
-
-#undef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-#undef ANALYZER_OPTION_WITH_FN
-
   /// 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();
+  UserModeKind getUserMode() const;
 
-  ExplorationStrategyKind getExplorationStrategy();
+  ExplorationStrategyKind getExplorationStrategy() const;
 
   /// Returns the inter-procedural analysis mode.
-  IPAKind getIPAMode();
+  IPAKind getIPAMode() const;
 
   /// Returns the option controlling which C++ member functions will be
   /// considered for inlining.
   ///
   /// This is controlled by the 'c++-inlining' config option.
   ///
   /// \sa CXXMemberInliningMode
-  bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K);
-
-  StringRef getCTUDir();
+  bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const;
 };
 
 using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
 
+//===----------------------------------------------------------------------===//
+// We'll use AnalyzerOptions in the frontend, but we can't link the frontend
+// with clangStaticAnalyzerCore, because clangStaticAnalyzerCore depends on
+// clangFrontend.
+//
+// For this reason, implement some methods in this header file.
+//===----------------------------------------------------------------------===//
+
+inline UserModeKind AnalyzerOptions::getUserMode() const {
+  auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(UserMode)
+    .Case("shallow", UMK_Shallow)
+    .Case("deep", UMK_Deep)
+    .Default(None);
+  assert(K.hasValue() && "User mode is invalid.");
+  return K.getValue();
+}
+
 } // namespace clang
 
 #endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
===================================================================
--- include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -9,29 +9,6 @@
 //
 //  This file defines the analyzer options avaible with -analyzer-config.
 //
-//  This file is in part intended for method generation. If it's not included
-//  for that purpose, the following function-like macros should be predefined,
-//  through which all registered options are accessible:
-//
-//    * ANALYZER_OPTION: Register a new option.
-//    * ANALYZER_OPTION_DEPENDS_ON_USER_MODE: Register a new option, default
-//      value depends on the "user-mode" option.
-//
-//  Options where a simple getter method is sufficient are registered with the
-//  following macros:
-//
-//    * ANALYZER_OPTION_GEN_FN: Register a new option, and generate a getter
-//      method for it in AnalyzerOptions.
-//
-//    * ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE: Same as above, but
-//      generates a getter function that depends on the "user-mode" option.
-//
-//  You can only include this file when both or none of the above two macros
-//  are defined!
-//  When they are defined, entries that do not generate functions  won't appear,
-//  and when they aren't, all entries are converted to ANALYZER_OPTION or to
-//  ANALYZER_OPTION_DEPENDS_ON_USER_MODE.
-//
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_ADT_STRINGREF_H
@@ -53,22 +30,6 @@
 #endif
 #endif
 
-#ifdef ANALYZER_OPTION_GEN_FN
-#ifndef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-#error If you include this file with the intent of generating functions, \
-define both 'ANALYZER_OPTION_GEN_FN' and \
-'ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE' macros!
-#endif
-#endif
-
-#ifdef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-#ifndef ANALYZER_OPTION_GEN_FN
-#error If you include this file with the intent of generating functions, \
-define both 'ANALYZER_OPTION_GEN_FN' and \
-'ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE' macros!
-#endif
-#endif
-
 #ifndef ANALYZER_OPTION
 /// Create a new analyzer option, but dont generate a method for it in
 /// AnalyzerOptions.
@@ -105,231 +66,187 @@
                                              SHALLOW_VAL, DEEP_VAL)
 #endif
 
-#ifndef ANALYZER_OPTION_GEN_FN
-/// Create a new analyzer option, and generate a getter method for it in
-/// AnalyzerOptions.
-///
-///   TYPE - The type of the option object that will be stored in
-///          AnalyzerOptions. This file is expected to be icluded in translation
-///          units where AnalyzerOptions.h is included, so types from that
-///          header should be used.
-///   NAME - The name of the option object.
-///   CMDFLAG - The command line flag for the option.
-///             (-analyzer-config CMDFLAG=VALUE)
-///   DESC - Description of the flag.
-///   DEFAULT_VAL - The default value for CMDFLAG.
-///   CREATE_FN - Name of the getter function.
-//
-// If this def file wasn't included with the intent of generating functions,
-// regard all entries as ANALYZER_OPTION.
-#define ANALYZER_OPTION_GEN_FN(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL,         \
-                               CREATE_FN)                                      \
-  ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)
-#endif
+//===----------------------------------------------------------------------===//
+// The "mode" option. Since some options depend on this, we list it on top of
+// this file in order to make sure that the generated field for it is
+// initialized before the rest.
+//===----------------------------------------------------------------------===//
 
-#ifndef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-/// Create a new analyzer option, and generate a getter method for it in
-/// AnalyzerOptions, and make it's default value depend on the "user-mode"
-/// option.
-///
-///   TYPE - The type of the option object that will be stored in
-///          AnalyzerOptions. This file is expected to be icluded in translation
-///          units where AnalyzerOptions.h is included, so types from that
-///          header should be used.
-///   NAME - The name of the option object.
-///   CMDFLAG - The command line flag for the option.
-///               (-analyzer-config CMDFLAG=VALUE)
-///   DESC - Description of the flago.
-///   SHALLOW_VAL - The default value for CMDFLAG, when "user-mode" was set to
-///                 "shallow".
-///   DEEP_VAL - The default value for CMDFLAG, when "user-mode" was set to
-///              "deep".
-///   CREATE_FN - Name of the getter function.
-//
-// If this def file wasn't included with the intent of generating functions,
-// regard all entries as ANALYZER_OPTION_DEPENDS_ON_USER_MODE.
-#define ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE(                           \
-    TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, DEEP_VAL, CREATE_FN)               \
-  ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, \
-                                       DEEP_VAL)
-#endif
+ANALYZER_OPTION(
+    StringRef, UserMode, "mode",
+    "(string) Controls the high-level analyzer mode, which influences the "
+    "default settings for some of the lower-level config options (such as "
+    "IPAMode). Value: \"deep\", \"shallow\".",
+    "deep")
 
 //===----------------------------------------------------------------------===//
 // Boolean analyzer options.
 //===----------------------------------------------------------------------===//
 
-ANALYZER_OPTION_GEN_FN(bool, IncludeImplicitDtorsInCFG, "cfg-implicit-dtors",
-                       "Whether or not implicit destructors for C++ objects "
-                       "should be included in the CFG.",
-                       true, includeImplicitDtorsInCFG)
+ANALYZER_OPTION(bool, ShouldIncludeImplicitDtorsInCFG, "cfg-implicit-dtors",
+                "Whether or not implicit destructors for C++ objects "
+                "should be included in the CFG.",
+                true)
 
-ANALYZER_OPTION_GEN_FN(bool, IncludeTemporaryDtorsInCFG, "cfg-temporary-dtors",
-                       "Whether or not the destructors for C++ temporary "
-                       "objects should be included in the CFG.",
-                       true, includeTemporaryDtorsInCFG)
+ANALYZER_OPTION(bool, ShouldIncludeTemporaryDtorsInCFG, "cfg-temporary-dtors",
+                "Whether or not the destructors for C++ temporary "
+                "objects should be included in the CFG.",
+                true)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, IncludeLifetimeInCFG, "cfg-lifetime",
+ANALYZER_OPTION(
+    bool, ShouldIncludeLifetimeInCFG, "cfg-lifetime",
     "Whether or not end-of-lifetime information should be included in the CFG.",
-    false, includeLifetimeInCFG)
-
-ANALYZER_OPTION_GEN_FN(bool, IncludeLoopExitInCFG, "cfg-loopexit",
-                       "Whether or not the end of the loop information should "
-                       "be included in the CFG.",
-                       false, includeLoopExitInCFG)
-
-ANALYZER_OPTION_GEN_FN(bool, IncludeRichConstructorsInCFG,
-                       "cfg-rich-constructors",
-                       "Whether or not construction site information should be "
-                       "included in the CFG C++ constructor elements.",
-                       true, includeRichConstructorsInCFG)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, IncludeScopesInCFG, "cfg-scopes",
-    "Whether or not scope information should be included in the CFG.", false,
-    includeScopesInCFG)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineTemplateFunctions, "c++-template-inlining",
-    "Whether or not templated functions may be considered for inlining.", true,
-    mayInlineTemplateFunctions)
-
-ANALYZER_OPTION_GEN_FN(bool, InlineCXXStandardLibrary, "c++-stdlib-inlining",
-                       "Whether or not C++ standard library functions may be "
-                       "considered for inlining.",
-                       true, mayInlineCXXStandardLibrary)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineCXXAllocator, "c++-allocator-inlining",
-    "Whether or not allocator call may be considered for inlining.", true,
-    mayInlineCXXAllocator)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineCXXSharedPtrDtor, "c++-shared_ptr-inlining",
+    false)
+
+ANALYZER_OPTION(bool, ShouldIncludeLoopExitInCFG, "cfg-loopexit",
+                "Whether or not the end of the loop information should "
+                "be included in the CFG.",
+                false)
+
+ANALYZER_OPTION(bool, ShouldIncludeRichConstructorsInCFG,
+                "cfg-rich-constructors",
+                "Whether or not construction site information should be "
+                "included in the CFG C++ constructor elements.",
+                true)
+
+ANALYZER_OPTION(
+    bool, ShouldIncludeScopesInCFG, "cfg-scopes",
+    "Whether or not scope information should be included in the CFG.", false)
+
+ANALYZER_OPTION(
+    bool, MayInlineTemplateFunctions, "c++-template-inlining",
+    "Whether or not templated functions may be considered for inlining.", true)
+
+ANALYZER_OPTION(bool, MayInlineCXXStandardLibrary, "c++-stdlib-inlining",
+                "Whether or not C++ standard library functions may be "
+                "considered for inlining.",
+                true)
+
+ANALYZER_OPTION(bool, MayInlineCXXAllocator, "c++-allocator-inlining",
+                "Whether or not allocator call may be considered for inlining.",
+                true)
+
+ANALYZER_OPTION(
+    bool, MayInlineCXXSharedPtrDtor, "c++-shared_ptr-inlining",
     "Whether or not the destructor of C++ 'shared_ptr' may be considered for "
     "inlining. This covers std::shared_ptr, std::tr1::shared_ptr, and "
     "boost::shared_ptr, and indeed any destructor named '~shared_ptr'.",
-    false, mayInlineCXXSharedPtrDtor)
+    false)
 
-ANALYZER_OPTION_GEN_FN(bool, InlineCXXTemporaryDtors, "c++-temp-dtor-inlining",
-                       "Whether C++ temporary destructors should be inlined "
-                       "during analysis. If temporary destructors are disabled "
-                       "in the CFG via the 'cfg-temporary-dtors' option, "
-                       "temporary destructors would not be inlined anyway.",
-                       true, mayInlineCXXTemporaryDtors)
+ANALYZER_OPTION(bool, MayInlineCXXTemporaryDtors, "c++-temp-dtor-inlining",
+                "Whether C++ temporary destructors should be inlined "
+                "during analysis. If temporary destructors are disabled "
+                "in the CFG via the 'cfg-temporary-dtors' option, "
+                "temporary destructors would not be inlined anyway.",
+                true)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, SuppressNullReturnPaths, "suppress-null-return-paths",
+ANALYZER_OPTION(
+    bool, ShouldSuppressNullReturnPaths, "suppress-null-return-paths",
     "Whether or not paths that go through null returns should be suppressed. "
     "This is a heuristic for avoiding bug reports with paths that go through "
     "inlined functions that are more defensive than their callers.",
-    true, shouldSuppressNullReturnPaths)
+    true)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, AvoidSuppressingNullArgumentPaths,
+ANALYZER_OPTION(
+    bool, ShouldAvoidSuppressingNullArgumentPaths,
     "avoid-suppressing-null-argument-paths",
     "Whether a bug report should not be suppressed if its path includes a call "
     "with a null argument, even if that call has a null return. This option "
-    "has no effect when #shouldSuppressNullReturnPaths() is false. This is a "
+    "has no effect when ShouldSuppressNullReturnPaths is false. This is a "
     "counter-heuristic to avoid false negatives.",
-    false, shouldAvoidSuppressingNullArgumentPaths)
-
-ANALYZER_OPTION_GEN_FN(bool, SuppressInlinedDefensiveChecks,
-                       "suppress-inlined-defensive-checks",
-                       "Whether or not diagnostics containing inlined "
-                       "defensive NULL checks should be suppressed.",
-                       true, shouldSuppressInlinedDefensiveChecks)
-
-ANALYZER_OPTION_GEN_FN(bool, InlineCXXContainerMethods,
-                       "c++-container-inlining",
-                       "Whether or not methods of C++ container objects may be "
-                       "considered for inlining.",
-                       false, mayInlineCXXContainerMethods)
-
-ANALYZER_OPTION_GEN_FN(bool, SuppressFromCXXStandardLibrary,
-                       "suppress-c++-stdlib",
-                       "Whether or not diagnostics reported within the C++ "
-                       "standard library should be suppressed.",
-                       true, shouldSuppressFromCXXStandardLibrary)
-
-ANALYZER_OPTION_GEN_FN(bool, CrosscheckWithZ3, "crosscheck-with-z3",
-                       "Whether bug reports should be crosschecked with the Z3 "
-                       "constraint manager backend.",
-                       false, shouldCrosscheckWithZ3)
-
-ANALYZER_OPTION_GEN_FN(bool, ReportIssuesInMainSourceFile,
-                       "report-in-main-source-file",
-                       "Whether or not the diagnostic report should be always "
-                       "reported in the main source file and not the headers.",
-                       false, shouldReportIssuesInMainSourceFile)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, WriteStableReportFilename, "stable-report-filename",
-    "Whether or not the report filename should be random or not.", false,
-    shouldWriteStableReportFilename)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, SerializeStats, "serialize-stats",
+    false)
+
+ANALYZER_OPTION(bool, ShouldSuppressInlinedDefensiveChecks,
+                "suppress-inlined-defensive-checks",
+                "Whether or not diagnostics containing inlined "
+                "defensive NULL checks should be suppressed.",
+                true)
+
+ANALYZER_OPTION(bool, MayInlineCXXContainerMethods, "c++-container-inlining",
+                "Whether or not methods of C++ container objects may be "
+                "considered for inlining.",
+                false)
+
+ANALYZER_OPTION(bool, ShouldSuppressFromCXXStandardLibrary,
+                "suppress-c++-stdlib",
+                "Whether or not diagnostics reported within the C++ "
+                "standard library should be suppressed.",
+                true)
+
+ANALYZER_OPTION(bool, ShouldCrosscheckWithZ3, "crosscheck-with-z3",
+                "Whether bug reports should be crosschecked with the Z3 "
+                "constraint manager backend.",
+                false)
+
+ANALYZER_OPTION(bool, ShouldReportIssuesInMainSourceFile,
+                "report-in-main-source-file",
+                "Whether or not the diagnostic report should be always "
+                "reported in the main source file and not the headers.",
+                false)
+
+ANALYZER_OPTION(bool, ShouldWriteStableReportFilename, "stable-report-filename",
+                "Whether or not the report filename should be random or not.",
+                false)
+
+ANALYZER_OPTION(
+    bool, ShouldSerializeStats, "serialize-stats",
     "Whether the analyzer should serialize statistics to plist output. "
     "Statistics would be serialized in JSON format inside the main dictionary "
     "under the statistics key. Available only if compiled in assert mode or "
     "with LLVM statistics explicitly enabled.",
-    false, shouldSerializeStats)
+    false)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineObjCMethod, "objc-inlining",
-    "Whether ObjectiveC inlining is enabled, false otherwise.", true,
-    mayInlineObjCMethod)
+ANALYZER_OPTION(bool, MayInlineObjCMethod, "objc-inlining",
+                "Whether ObjectiveC inlining is enabled, false otherwise.",
+                true)
 
-ANALYZER_OPTION_GEN_FN(bool, PrunePaths, "prune-paths",
-                       "Whether irrelevant parts of a bug report path should "
-                       "be pruned out of the final output.",
-                       true, shouldPrunePaths)
+ANALYZER_OPTION(bool, ShouldPrunePaths, "prune-paths",
+                "Whether irrelevant parts of a bug report path should "
+                "be pruned out of the final output.",
+                true)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, ConditionalizeStaticInitializers,
+ANALYZER_OPTION(
+    bool, ShouldConditionalizeStaticInitializers,
     "cfg-conditional-static-initializers",
     "Whether 'static' initializers should be in conditional logic in the CFG.",
-    true, shouldConditionalizeStaticInitializers)
+    true)
 
-ANALYZER_OPTION_GEN_FN(bool, SynthesizeBodies, "faux-bodies",
-                       "Whether the analyzer engine should synthesize fake "
-                       "bodies for well-known functions.",
-                       true, shouldSynthesizeBodies)
+ANALYZER_OPTION(bool, ShouldSynthesizeBodies, "faux-bodies",
+                "Whether the analyzer engine should synthesize fake "
+                "bodies for well-known functions.",
+                true)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, ElideConstructors, "elide-constructors",
+ANALYZER_OPTION(
+    bool, ShouldElideConstructors, "elide-constructors",
     "Whether elidable C++ copy-constructors and move-constructors should be "
     "actually elided during analysis. Both behaviors are allowed by the C++ "
     "standard, and the analyzer, like CodeGen, defaults to eliding. Starting "
     "with C++17 some elisions become mandatory, and in these cases the option "
     "will be ignored.",
-    true, shouldElideConstructors)
+    true)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineLambdas, "inline-lambdas",
+ANALYZER_OPTION(
+    bool, ShouldInlineLambdas, "inline-lambdas",
     "Whether lambdas should be inlined. Otherwise a sink node will be "
     "generated each time a LambdaExpr is visited.",
-    true, shouldInlineLambdas)
+    true)
 
-ANALYZER_OPTION_GEN_FN(bool, WidenLoops, "widen-loops",
-                       "Whether the analysis should try to widen loops.", false,
-                       shouldWidenLoops)
+ANALYZER_OPTION(bool, ShouldWidenLoops, "widen-loops",
+                "Whether the analysis should try to widen loops.", false)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, UnrollLoops, "unroll-loops",
-    "Whether the analysis should try to unroll loops with known bounds.", false,
-    shouldUnrollLoops)
+ANALYZER_OPTION(
+    bool, ShouldUnrollLoops, "unroll-loops",
+    "Whether the analysis should try to unroll loops with known bounds.", false)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, DisplayNotesAsEvents, "notes-as-events",
+ANALYZER_OPTION(
+    bool, ShouldDisplayNotesAsEvents, "notes-as-events",
     "Whether the bug reporter should transparently treat extra note diagnostic "
     "pieces as event diagnostic pieces. Useful when the diagnostic consumer "
     "doesn't support the extra note pieces.",
-    false, shouldDisplayNotesAsEvents)
+    false)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, AggressivelySimplifyBinaryOperation,
+ANALYZER_OPTION(
+    bool, ShouldAggressivelySimplifyBinaryOperation,
     "aggressive-binary-operation-simplification",
     "Whether SValBuilder should rearrange comparisons and additive operations "
     "of symbolic expressions which consist of a sum of a symbol and a concrete "
@@ -342,105 +259,95 @@
     "'<', '<=', '>', '>=', '+' or '-'. The rearrangement also happens with '-' "
     "instead of '+' on either or both side and also if any or both integers "
     "are missing.",
-    false, shouldAggressivelySimplifyBinaryOperation)
+    false)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, EagerlyAssume, "eagerly-assume",
+ANALYZER_OPTION(
+    bool, ShouldEagerlyAssume, "eagerly-assume",
     "Whether we should eagerly assume evaluations of conditionals, thus, "
     "bifurcating the path. This indicates how the engine should handle "
     "expressions such as: 'x = (y != 0)'. When this is true then the "
     "subexpression 'y != 0' will be eagerly assumed to be true or false, thus "
     "evaluating it to the integers 0 or 1 respectively. The upside is that "
     "this can increase analysis precision until we have a better way to lazily "
     "evaluate such logic. The downside is that it eagerly bifurcates paths.",
-    true, shouldEagerlyAssume)
+    true)
 
-ANALYZER_OPTION_GEN_FN(
-    bool, NaiveCTU, "experimental-enable-naive-ctu-analysis",
+ANALYZER_OPTION(
+    bool, IsNaiveCTUEnabled, "experimental-enable-naive-ctu-analysis",
     "Whether naive cross translation unit analysis is enabled. This is an "
     "experimental feature to inline functions from another translation units.",
-    false, naiveCTUEnabled)
+    false)
 
-ANALYZER_OPTION_GEN_FN(bool, DisplayMacroExpansions, "expand-macros",
-                       "Whether macros related to the bugpath should be "
-                       "expanded and included in the plist output.",
-                       false, shouldDisplayMacroExpansions)
+ANALYZER_OPTION(bool, ShouldDisplayMacroExpansions, "expand-macros",
+                "Whether macros related to the bugpath should be "
+                "expanded and included in the plist output.",
+                false)
 
 //===----------------------------------------------------------------------===//
 // Unsinged analyzer options.
 //===----------------------------------------------------------------------===//
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     unsigned, AlwaysInlineSize, "ipa-always-inline-size",
     "The size of the functions (in basic blocks), which should be considered "
     "to be small enough to always inline.",
-    3, getAlwaysInlineSize)
+    3)
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     unsigned, GraphTrimInterval, "graph-trim-interval",
     "How often nodes in the ExplodedGraph should be recycled to save memory. "
     "To disable node reclamation, set the option to 0.",
-    1000, getGraphTrimInterval)
+    1000)
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     unsigned, MinCFGSizeTreatFunctionsAsLarge,
     "min-cfg-size-treat-functions-as-large",
     "The number of basic blocks a function needs to have to be considered "
     "large for the 'max-times-inline-large' config option.",
-    14, getMinCFGSizeTreatFunctionsAsLarge)
+    14)
 
-ANALYZER_OPTION_GEN_FN(unsigned, MaxSymbolComplexity, "max-symbol-complexity",
-                       "The maximum complexity of symbolic constraint.", 35,
-                       getMaxSymbolComplexity)
+ANALYZER_OPTION(unsigned, MaxSymbolComplexity, "max-symbol-complexity",
+                "The maximum complexity of symbolic constraint.", 35)
 
-ANALYZER_OPTION_GEN_FN(unsigned, MaxTimesInlineLarge, "max-times-inline-large",
-                       "The maximum times a large function could be inlined.",
-                       32, getMaxTimesInlineLarge)
+ANALYZER_OPTION(unsigned, MaxTimesInlineLarge, "max-times-inline-large",
+                "The maximum times a large function could be inlined.", 32)
 
-ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE(
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
     unsigned, MaxInlinableSize, "max-inlinable-size",
     "The bound on the number of basic blocks in an inlined function.",
-    /* SHALLOW_VAL */ 4, /* DEEP_VAL */ 100, getMaxInlinableSize)
+    /* SHALLOW_VAL */ 4, /* DEEP_VAL */ 100)
 
-ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE(
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
     unsigned, MaxNodesPerTopLevelFunction, "max-nodes",
     "The maximum number of nodes the analyzer can generate while exploring a "
     "top level function (for each exploded graph). 0 means no limit.",
-    /* SHALLOW_VAL */ 75000, /* DEEP_VAL */ 225000,
-    getMaxNodesPerTopLevelFunction)
+    /* SHALLOW_VAL */ 75000, /* DEEP_VAL */ 225000)
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     unsigned, RegionStoreSmallStructLimit, "region-store-small-struct-limit",
     "The largest number of fields a struct can have and still be considered "
     "small This is currently used to decide whether or not it is worth forcing "
     "a LazyCompoundVal on bind. To disable all small-struct-dependent "
     "behavior, set the option to 0.",
-    2, getRegionStoreSmallStructLimit)
+    2)
 
 //===----------------------------------------------------------------------===//
 // String analyzer options.
 //===----------------------------------------------------------------------===//
 
 ANALYZER_OPTION(StringRef, CTUDir, "ctu-dir",
                 "The directory containing the CTU related files.", "")
 
-ANALYZER_OPTION_GEN_FN(
-    StringRef, CTUIndexName, "ctu-index-name",
-    "the name of the file containing the CTU index of functions.",
-    "externalFnMap.txt", getCTUIndexName)
+ANALYZER_OPTION(StringRef, CTUIndexName, "ctu-index-name",
+                "the name of the file containing the CTU index of functions.",
+                "externalFnMap.txt")
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     StringRef, ModelPath, "model-path",
     "The analyzer can inline an alternative implementation written in C at the "
     "call site if the called function's body is not available. This is a path "
     "where to look for those alternative implementations (called models).",
-    "", getModelPath)
-
-ANALYZER_OPTION(StringRef, UserMode, "mode",
-                "Controls the high-level analyzer mode, which influences the "
-                "default settings for some of the lower-level config options "
-                "(such as IPAMode). Value: \"deep\", \"shallow\".",
-                "deep")
+    "")
 
 ANALYZER_OPTION(
     StringRef, CXXMemberInliningMode, "c++-inlining",
@@ -461,7 +368,5 @@
     "\"bfs_block_dfs_contents\".",
     "unexplored_first_queue")
 
-#undef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-#undef ANALYZER_OPTION_GEN_FN
 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
 #undef ANALYZER_OPTION
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to