clang API Documentation
00001 //===--- CheckerRegistry.cpp - Maintains all available checkers -*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "clang/StaticAnalyzer/Core/CheckerRegistry.h" 00011 #include "clang/StaticAnalyzer/Core/CheckerOptInfo.h" 00012 #include "llvm/ADT/SetVector.h" 00013 #include "llvm/Support/raw_ostream.h" 00014 00015 using namespace clang; 00016 using namespace ento; 00017 00018 static const char PackageSeparator = '.'; 00019 typedef llvm::SetVector<const CheckerRegistry::CheckerInfo *> CheckerInfoSet; 00020 00021 00022 static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a, 00023 const CheckerRegistry::CheckerInfo &b) { 00024 return a.FullName < b.FullName; 00025 } 00026 00027 static bool isInPackage(const CheckerRegistry::CheckerInfo &checker, 00028 StringRef packageName) { 00029 // Does the checker's full name have the package as a prefix? 00030 if (!checker.FullName.startswith(packageName)) 00031 return false; 00032 00033 // Is the package actually just the name of a specific checker? 00034 if (checker.FullName.size() == packageName.size()) 00035 return true; 00036 00037 // Is the checker in the package (or a subpackage)? 00038 if (checker.FullName[packageName.size()] == PackageSeparator) 00039 return true; 00040 00041 return false; 00042 } 00043 00044 static void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers, 00045 const llvm::StringMap<size_t> &packageSizes, 00046 CheckerOptInfo &opt, CheckerInfoSet &collected) { 00047 // Use a binary search to find the possible start of the package. 00048 CheckerRegistry::CheckerInfo packageInfo(nullptr, opt.getName(), ""); 00049 CheckerRegistry::CheckerInfoList::const_iterator e = checkers.end(); 00050 CheckerRegistry::CheckerInfoList::const_iterator i = 00051 std::lower_bound(checkers.begin(), e, packageInfo, checkerNameLT); 00052 00053 // If we didn't even find a possible package, give up. 00054 if (i == e) 00055 return; 00056 00057 // If what we found doesn't actually start the package, give up. 00058 if (!isInPackage(*i, opt.getName())) 00059 return; 00060 00061 // There is at least one checker in the package; claim the option. 00062 opt.claim(); 00063 00064 // See how large the package is. 00065 // If the package doesn't exist, assume the option refers to a single checker. 00066 size_t size = 1; 00067 llvm::StringMap<size_t>::const_iterator packageSize = 00068 packageSizes.find(opt.getName()); 00069 if (packageSize != packageSizes.end()) 00070 size = packageSize->getValue(); 00071 00072 // Step through all the checkers in the package. 00073 for (e = i+size; i != e; ++i) { 00074 if (opt.isEnabled()) 00075 collected.insert(&*i); 00076 else 00077 collected.remove(&*i); 00078 } 00079 } 00080 00081 void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name, 00082 StringRef desc) { 00083 Checkers.push_back(CheckerInfo(fn, name, desc)); 00084 00085 // Record the presence of the checker in its packages. 00086 StringRef packageName, leafName; 00087 std::tie(packageName, leafName) = name.rsplit(PackageSeparator); 00088 while (!leafName.empty()) { 00089 Packages[packageName] += 1; 00090 std::tie(packageName, leafName) = packageName.rsplit(PackageSeparator); 00091 } 00092 } 00093 00094 void CheckerRegistry::initializeManager(CheckerManager &checkerMgr, 00095 SmallVectorImpl<CheckerOptInfo> &opts) const { 00096 // Sort checkers for efficient collection. 00097 std::sort(Checkers.begin(), Checkers.end(), checkerNameLT); 00098 00099 // Collect checkers enabled by the options. 00100 CheckerInfoSet enabledCheckers; 00101 for (SmallVectorImpl<CheckerOptInfo>::iterator 00102 i = opts.begin(), e = opts.end(); i != e; ++i) { 00103 collectCheckers(Checkers, Packages, *i, enabledCheckers); 00104 } 00105 00106 // Initialize the CheckerManager with all enabled checkers. 00107 for (CheckerInfoSet::iterator 00108 i = enabledCheckers.begin(), e = enabledCheckers.end(); i != e; ++i) { 00109 checkerMgr.setCurrentCheckName(CheckName((*i)->FullName)); 00110 (*i)->Initialize(checkerMgr); 00111 } 00112 } 00113 00114 void CheckerRegistry::printHelp(raw_ostream &out, 00115 size_t maxNameChars) const { 00116 // FIXME: Alphabetical sort puts 'experimental' in the middle. 00117 // Would it be better to name it '~experimental' or something else 00118 // that's ASCIIbetically last? 00119 std::sort(Checkers.begin(), Checkers.end(), checkerNameLT); 00120 00121 // FIXME: Print available packages. 00122 00123 out << "CHECKERS:\n"; 00124 00125 // Find the maximum option length. 00126 size_t optionFieldWidth = 0; 00127 for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end(); 00128 i != e; ++i) { 00129 // Limit the amount of padding we are willing to give up for alignment. 00130 // Package.Name Description [Hidden] 00131 size_t nameLength = i->FullName.size(); 00132 if (nameLength <= maxNameChars) 00133 optionFieldWidth = std::max(optionFieldWidth, nameLength); 00134 } 00135 00136 const size_t initialPad = 2; 00137 for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end(); 00138 i != e; ++i) { 00139 out.indent(initialPad) << i->FullName; 00140 00141 int pad = optionFieldWidth - i->FullName.size(); 00142 00143 // Break on long option names. 00144 if (pad < 0) { 00145 out << '\n'; 00146 pad = optionFieldWidth + initialPad; 00147 } 00148 out.indent(pad + 2) << i->Desc; 00149 00150 out << '\n'; 00151 } 00152 }