Clang Project

clang_source_code/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
1//===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains special accessors for analyzer configuration options
10// with string representations.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
15#include "clang/StaticAnalyzer/Core/Checker.h"
16#include "llvm/ADT/SmallString.h"
17#include "llvm/ADT/StringSwitch.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/ADT/Twine.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/FileSystem.h"
22#include "llvm/Support/raw_ostream.h"
23#include <cassert>
24#include <cstddef>
25#include <utility>
26#include <vector>
27
28using namespace clang;
29using namespace ento;
30using namespace llvm;
31
32std::vector<StringRef>
33AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
34  static const StringRef StaticAnalyzerChecks[] = {
35#define GET_CHECKERS
36#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI)                            \
37  FULLNAME,
38#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
39#undef CHECKER
40#undef GET_CHECKERS
41  };
42  std::vector<StringRef> Result;
43  for (StringRef CheckName : StaticAnalyzerChecks) {
44    if (!CheckName.startswith("debug.") &&
45        (IncludeExperimental || !CheckName.startswith("alpha.")))
46      Result.push_back(CheckName);
47  }
48  return Result;
49}
50
51ExplorationStrategyKind
52AnalyzerOptions::getExplorationStrategy() const {
53  auto K =
54    llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
55                                                            ExplorationStrategy)
56          .Case("dfs", ExplorationStrategyKind::DFS)
57          .Case("bfs", ExplorationStrategyKind::BFS)
58          .Case("unexplored_first",
59                ExplorationStrategyKind::UnexploredFirst)
60          .Case("unexplored_first_queue",
61                ExplorationStrategyKind::UnexploredFirstQueue)
62          .Case("unexplored_first_location_queue",
63                ExplorationStrategyKind::UnexploredFirstLocationQueue)
64          .Case("bfs_block_dfs_contents",
65                ExplorationStrategyKind::BFSBlockDFSContents)
66          .Default(None);
67   (0) . __assert_fail ("K.hasValue() && \"User mode is invalid.\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 67, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(K.hasValue() && "User mode is invalid.");
68  return K.getValue();
69}
70
71IPAKind AnalyzerOptions::getIPAMode() const {
72  auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode)
73          .Case("none", IPAK_None)
74          .Case("basic-inlining", IPAK_BasicInlining)
75          .Case("inlining", IPAK_Inlining)
76          .Case("dynamic", IPAK_DynamicDispatch)
77          .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
78          .Default(None);
79   (0) . __assert_fail ("K.hasValue() && \"IPA Mode is invalid.\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 79, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(K.hasValue() && "IPA Mode is invalid.");
80
81  return K.getValue();
82}
83
84bool
85AnalyzerOptions::mayInlineCXXMemberFunction(
86                                          CXXInlineableMemberKind Paramconst {
87  if (getIPAMode() < IPAK_Inlining)
88    return false;
89
90  auto K =
91    llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
92                                                          CXXMemberInliningMode)
93    .Case("constructors", CIMK_Constructors)
94    .Case("destructors", CIMK_Destructors)
95    .Case("methods", CIMK_MemberFunctions)
96    .Case("none", CIMK_None)
97    .Default(None);
98
99   (0) . __assert_fail ("K.hasValue() && \"Invalid c++ member function inlining mode.\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 99, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(K.hasValue() && "Invalid c++ member function inlining mode.");
100
101  return *K >= Param;
102}
103
104StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName,
105                                                  StringRef OptionName,
106                                                  StringRef DefaultVal,
107                                                  bool SearchInParents ) const {
108   (0) . __assert_fail ("!CheckerName.empty() && \"Empty checker name! Make sure the checker object (including it's \" \"bases!) if fully initialized before calling this function!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 110, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!CheckerName.empty() &&
109 (0) . __assert_fail ("!CheckerName.empty() && \"Empty checker name! Make sure the checker object (including it's \" \"bases!) if fully initialized before calling this function!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 110, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">         "Empty checker name! Make sure the checker object (including it's "
110 (0) . __assert_fail ("!CheckerName.empty() && \"Empty checker name! Make sure the checker object (including it's \" \"bases!) if fully initialized before calling this function!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 110, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">         "bases!) if fully initialized before calling this function!");
111
112  ConfigTable::const_iterator E = Config.end();
113  do {
114    ConfigTable::const_iterator I =
115        Config.find((Twine(CheckerName) + ":" + OptionName).str());
116    if (I != E)
117      return StringRef(I->getValue());
118    size_t Pos = CheckerName.rfind('.');
119    if (Pos == StringRef::npos)
120      return DefaultVal;
121    CheckerName = CheckerName.substr(0, Pos);
122  } while (!CheckerName.empty() && SearchInParents);
123  return DefaultVal;
124}
125
126StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C,
127                                                  StringRef OptionName,
128                                                  StringRef DefaultVal,
129                                                  bool SearchInParents ) const {
130  return getCheckerStringOption(
131             C->getTagDescription(), OptionName, DefaultVal, SearchInParents);
132}
133
134bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName,
135                                              StringRef OptionName,
136                                              bool DefaultVal,
137                                              bool SearchInParents ) const {
138  // FIXME: We should emit a warning here if the value is something other than
139  // "true", "false", or the empty string (meaning the default value),
140  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
141  return llvm::StringSwitch<bool>(
142      getCheckerStringOption(CheckerName, OptionName,
143                             DefaultVal ? "true" : "false",
144                             SearchInParents))
145      .Case("true"true)
146      .Case("false"false)
147      .Default(DefaultVal);
148}
149
150bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C,
151                                              StringRef OptionName,
152                                              bool DefaultVal,
153                                              bool SearchInParents ) const {
154  return getCheckerBooleanOption(
155             C->getTagDescription(), OptionName, DefaultVal, SearchInParents);
156}
157
158int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName,
159                                             StringRef OptionName,
160                                             int DefaultVal,
161                                             bool SearchInParents ) const {
162  int Ret = DefaultVal;
163  bool HasFailed = getCheckerStringOption(CheckerName, OptionName,
164                                          std::to_string(DefaultVal),
165                                          SearchInParents)
166                     .getAsInteger(10, Ret);
167   (0) . __assert_fail ("!HasFailed && \"analyzer-config option should be numeric\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 167, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!HasFailed && "analyzer-config option should be numeric");
168  (void)HasFailed;
169  return Ret;
170}
171
172int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C,
173                                             StringRef OptionName,
174                                             int DefaultVal,
175                                             bool SearchInParents ) const {
176  return getCheckerIntegerOption(
177             C->getTagDescription(), OptionName, DefaultVal, SearchInParents);
178}
179
clang::AnalyzerOptions::getRegisteredCheckers
clang::AnalyzerOptions::getExplorationStrategy
clang::AnalyzerOptions::getIPAMode
clang::AnalyzerOptions::mayInlineCXXMemberFunction
clang::AnalyzerOptions::getCheckerStringOption
clang::AnalyzerOptions::getCheckerStringOption
clang::AnalyzerOptions::getCheckerBooleanOption
clang::AnalyzerOptions::getCheckerBooleanOption
clang::AnalyzerOptions::getCheckerIntegerOption
clang::AnalyzerOptions::getCheckerIntegerOption