ClangSACheckersEmitter.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. //=- ClangSACheckersEmitter.cpp - Generate Clang SA checkers tables -*- C++ -*-
  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 tablegen backend emits Clang Static Analyzer checkers tables.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "TableGenBackends.h"
  13. #include "llvm/ADT/StringMap.h"
  14. #include "llvm/TableGen/Error.h"
  15. #include "llvm/TableGen/Record.h"
  16. #include "llvm/TableGen/TableGenBackend.h"
  17. #include <map>
  18. #include <string>
  19. using namespace llvm;
  20. //===----------------------------------------------------------------------===//
  21. // Static Analyzer Checkers Tables generation
  22. //===----------------------------------------------------------------------===//
  23. static std::string getPackageFullName(const Record *R, StringRef Sep = ".");
  24. static std::string getParentPackageFullName(const Record *R,
  25. StringRef Sep = ".") {
  26. std::string name;
  27. if (DefInit *DI = dyn_cast<DefInit>(R->getValueInit("ParentPackage")))
  28. name = getPackageFullName(DI->getDef(), Sep);
  29. return name;
  30. }
  31. static std::string getPackageFullName(const Record *R, StringRef Sep) {
  32. std::string name = getParentPackageFullName(R, Sep);
  33. if (!name.empty())
  34. name += Sep;
  35. assert(!R->getValueAsString("PackageName").empty());
  36. name += R->getValueAsString("PackageName");
  37. return name;
  38. }
  39. static std::string getCheckerFullName(const Record *R, StringRef Sep = ".") {
  40. std::string name = getParentPackageFullName(R, Sep);
  41. if (!name.empty())
  42. name += Sep;
  43. assert(!R->getValueAsString("CheckerName").empty());
  44. name += R->getValueAsString("CheckerName");
  45. return name;
  46. }
  47. static std::string getStringValue(const Record &R, StringRef field) {
  48. if (StringInit *SI = dyn_cast<StringInit>(R.getValueInit(field)))
  49. return std::string(SI->getValue());
  50. return std::string();
  51. }
  52. // Calculates the integer value representing the BitsInit object
  53. static inline uint64_t getValueFromBitsInit(const BitsInit *B, const Record &R) {
  54. assert(B->getNumBits() <= sizeof(uint64_t) * 8 && "BitInits' too long!");
  55. uint64_t Value = 0;
  56. for (unsigned i = 0, e = B->getNumBits(); i != e; ++i) {
  57. const auto *Bit = dyn_cast<BitInit>(B->getBit(i));
  58. if (Bit)
  59. Value |= uint64_t(Bit->getValue()) << i;
  60. else
  61. PrintFatalError(R.getLoc(),
  62. "missing Documentation for " + getCheckerFullName(&R));
  63. }
  64. return Value;
  65. }
  66. static std::string getCheckerDocs(const Record &R) {
  67. const BitsInit *BI = R.getValueAsBitsInit("Documentation");
  68. if (!BI)
  69. PrintFatalError(R.getLoc(), "missing Documentation<...> member for " +
  70. getCheckerFullName(&R));
  71. // Ignore 'Documentation<NotDocumented>' checkers.
  72. if (getValueFromBitsInit(BI, R) == 0)
  73. return "";
  74. std::string CheckerFullName = StringRef(getCheckerFullName(&R, "-")).lower();
  75. return (llvm::Twine("https://clang.llvm.org/docs/analyzer/checkers.html#") +
  76. CheckerFullName)
  77. .str();
  78. }
  79. /// Retrieves the type from a CmdOptionTypeEnum typed Record object. Note that
  80. /// the class itself has to be modified for adding a new option type in
  81. /// CheckerBase.td.
  82. static std::string getCheckerOptionType(const Record &R) {
  83. if (BitsInit *BI = R.getValueAsBitsInit("Type")) {
  84. switch(getValueFromBitsInit(BI, R)) {
  85. case 0:
  86. return "int";
  87. case 1:
  88. return "string";
  89. case 2:
  90. return "bool";
  91. }
  92. }
  93. PrintFatalError(R.getLoc(),
  94. "unable to parse command line option type for "
  95. + getCheckerFullName(&R));
  96. return "";
  97. }
  98. static std::string getDevelopmentStage(const Record &R) {
  99. if (BitsInit *BI = R.getValueAsBitsInit("DevelopmentStage")) {
  100. switch(getValueFromBitsInit(BI, R)) {
  101. case 0:
  102. return "alpha";
  103. case 1:
  104. return "released";
  105. }
  106. }
  107. PrintFatalError(R.getLoc(),
  108. "unable to parse command line option type for "
  109. + getCheckerFullName(&R));
  110. return "";
  111. }
  112. static bool isHidden(const Record *R) {
  113. if (R->getValueAsBit("Hidden"))
  114. return true;
  115. // Not declared as hidden, check the parent package if it is hidden.
  116. if (DefInit *DI = dyn_cast<DefInit>(R->getValueInit("ParentPackage")))
  117. return isHidden(DI->getDef());
  118. return false;
  119. }
  120. static void printChecker(llvm::raw_ostream &OS, const Record &R) {
  121. OS << "CHECKER(" << "\"";
  122. OS.write_escaped(getCheckerFullName(&R)) << "\", ";
  123. OS << R.getName() << ", ";
  124. OS << "\"";
  125. OS.write_escaped(getStringValue(R, "HelpText")) << "\", ";
  126. OS << "\"";
  127. OS.write_escaped(getCheckerDocs(R));
  128. OS << "\", ";
  129. if (!isHidden(&R))
  130. OS << "false";
  131. else
  132. OS << "true";
  133. OS << ")\n";
  134. }
  135. static void printOption(llvm::raw_ostream &OS, StringRef FullName,
  136. const Record &R) {
  137. OS << "\"";
  138. OS.write_escaped(getCheckerOptionType(R)) << "\", \"";
  139. OS.write_escaped(FullName) << "\", ";
  140. OS << '\"' << getStringValue(R, "CmdFlag") << "\", ";
  141. OS << '\"';
  142. OS.write_escaped(getStringValue(R, "Desc")) << "\", ";
  143. OS << '\"';
  144. OS.write_escaped(getStringValue(R, "DefaultVal")) << "\", ";
  145. OS << '\"';
  146. OS << getDevelopmentStage(R) << "\", ";
  147. if (!R.getValueAsBit("Hidden"))
  148. OS << "false";
  149. else
  150. OS << "true";
  151. }
  152. void clang::EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
  153. std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker");
  154. std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package");
  155. using SortedRecords = llvm::StringMap<const Record *>;
  156. OS << "// This file is automatically generated. Do not edit this file by "
  157. "hand.\n";
  158. // Emit packages.
  159. //
  160. // PACKAGE(PACKAGENAME)
  161. // - PACKAGENAME: The name of the package.
  162. OS << "\n"
  163. "#ifdef GET_PACKAGES\n";
  164. {
  165. SortedRecords sortedPackages;
  166. for (unsigned i = 0, e = packages.size(); i != e; ++i)
  167. sortedPackages[getPackageFullName(packages[i])] = packages[i];
  168. for (SortedRecords::iterator
  169. I = sortedPackages.begin(), E = sortedPackages.end(); I != E; ++I) {
  170. const Record &R = *I->second;
  171. OS << "PACKAGE(" << "\"";
  172. OS.write_escaped(getPackageFullName(&R)) << '\"';
  173. OS << ")\n";
  174. }
  175. }
  176. OS << "#endif // GET_PACKAGES\n"
  177. "\n";
  178. // Emit a package option.
  179. //
  180. // PACKAGE_OPTION(OPTIONTYPE, PACKAGENAME, OPTIONNAME, DESCRIPTION, DEFAULT)
  181. // - OPTIONTYPE: Type of the option, whether it's integer or boolean etc.
  182. // This is important for validating user input. Note that
  183. // it's a string, rather than an actual type: since we can
  184. // load checkers runtime, we can't use template hackery for
  185. // sorting this out compile-time.
  186. // - PACKAGENAME: Name of the package.
  187. // - OPTIONNAME: Name of the option.
  188. // - DESCRIPTION
  189. // - DEFAULT: The default value for this option.
  190. //
  191. // The full option can be specified in the command like this:
  192. // -analyzer-config PACKAGENAME:OPTIONNAME=VALUE
  193. OS << "\n"
  194. "#ifdef GET_PACKAGE_OPTIONS\n";
  195. for (const Record *Package : packages) {
  196. if (Package->isValueUnset("PackageOptions"))
  197. continue;
  198. std::vector<Record *> PackageOptions = Package
  199. ->getValueAsListOfDefs("PackageOptions");
  200. for (Record *PackageOpt : PackageOptions) {
  201. OS << "PACKAGE_OPTION(";
  202. printOption(OS, getPackageFullName(Package), *PackageOpt);
  203. OS << ")\n";
  204. }
  205. }
  206. OS << "#endif // GET_PACKAGE_OPTIONS\n"
  207. "\n";
  208. // Emit checkers.
  209. //
  210. // CHECKER(FULLNAME, CLASS, HELPTEXT)
  211. // - FULLNAME: The full name of the checker, including packages, e.g.:
  212. // alpha.cplusplus.UninitializedObject
  213. // - CLASS: The name of the checker, with "Checker" appended, e.g.:
  214. // UninitializedObjectChecker
  215. // - HELPTEXT: The description of the checker.
  216. OS << "\n"
  217. "#ifdef GET_CHECKERS\n"
  218. "\n";
  219. for (const Record *checker : checkers) {
  220. printChecker(OS, *checker);
  221. }
  222. OS << "\n"
  223. "#endif // GET_CHECKERS\n"
  224. "\n";
  225. // Emit dependencies.
  226. //
  227. // CHECKER_DEPENDENCY(FULLNAME, DEPENDENCY)
  228. // - FULLNAME: The full name of the checker that depends on another checker.
  229. // - DEPENDENCY: The full name of the checker FULLNAME depends on.
  230. OS << "\n"
  231. "#ifdef GET_CHECKER_DEPENDENCIES\n";
  232. for (const Record *Checker : checkers) {
  233. if (Checker->isValueUnset("Dependencies"))
  234. continue;
  235. for (const Record *Dependency :
  236. Checker->getValueAsListOfDefs("Dependencies")) {
  237. OS << "CHECKER_DEPENDENCY(";
  238. OS << '\"';
  239. OS.write_escaped(getCheckerFullName(Checker)) << "\", ";
  240. OS << '\"';
  241. OS.write_escaped(getCheckerFullName(Dependency)) << '\"';
  242. OS << ")\n";
  243. }
  244. }
  245. OS << "\n"
  246. "#endif // GET_CHECKER_DEPENDENCIES\n";
  247. // Emit weak dependencies.
  248. //
  249. // CHECKER_DEPENDENCY(FULLNAME, DEPENDENCY)
  250. // - FULLNAME: The full name of the checker that is supposed to be
  251. // registered first.
  252. // - DEPENDENCY: The full name of the checker FULLNAME weak depends on.
  253. OS << "\n"
  254. "#ifdef GET_CHECKER_WEAK_DEPENDENCIES\n";
  255. for (const Record *Checker : checkers) {
  256. if (Checker->isValueUnset("WeakDependencies"))
  257. continue;
  258. for (const Record *Dependency :
  259. Checker->getValueAsListOfDefs("WeakDependencies")) {
  260. OS << "CHECKER_WEAK_DEPENDENCY(";
  261. OS << '\"';
  262. OS.write_escaped(getCheckerFullName(Checker)) << "\", ";
  263. OS << '\"';
  264. OS.write_escaped(getCheckerFullName(Dependency)) << '\"';
  265. OS << ")\n";
  266. }
  267. }
  268. OS << "\n"
  269. "#endif // GET_CHECKER_WEAK_DEPENDENCIES\n";
  270. // Emit a package option.
  271. //
  272. // CHECKER_OPTION(OPTIONTYPE, CHECKERNAME, OPTIONNAME, DESCRIPTION, DEFAULT)
  273. // - OPTIONTYPE: Type of the option, whether it's integer or boolean etc.
  274. // This is important for validating user input. Note that
  275. // it's a string, rather than an actual type: since we can
  276. // load checkers runtime, we can't use template hackery for
  277. // sorting this out compile-time.
  278. // - CHECKERNAME: Name of the package.
  279. // - OPTIONNAME: Name of the option.
  280. // - DESCRIPTION
  281. // - DEFAULT: The default value for this option.
  282. //
  283. // The full option can be specified in the command like this:
  284. // -analyzer-config CHECKERNAME:OPTIONNAME=VALUE
  285. OS << "\n"
  286. "#ifdef GET_CHECKER_OPTIONS\n";
  287. for (const Record *Checker : checkers) {
  288. if (Checker->isValueUnset("CheckerOptions"))
  289. continue;
  290. std::vector<Record *> CheckerOptions = Checker
  291. ->getValueAsListOfDefs("CheckerOptions");
  292. for (Record *CheckerOpt : CheckerOptions) {
  293. OS << "CHECKER_OPTION(";
  294. printOption(OS, getCheckerFullName(Checker), *CheckerOpt);
  295. OS << ")\n";
  296. }
  297. }
  298. OS << "#endif // GET_CHECKER_OPTIONS\n"
  299. "\n";
  300. }