2011-10-06 21:03:08 +08:00
|
|
|
//=- ClangSACheckersEmitter.cpp - Generate Clang SA checkers tables -*- C++ -*-
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This tablegen backend emits Clang Static Analyzer checkers tables.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-11-13 01:49:51 +08:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2012-10-26 00:37:08 +08:00
|
|
|
#include "llvm/TableGen/Error.h"
|
2012-06-13 13:12:41 +08:00
|
|
|
#include "llvm/TableGen/Record.h"
|
|
|
|
#include "llvm/TableGen/TableGenBackend.h"
|
2011-10-06 21:03:08 +08:00
|
|
|
#include <map>
|
|
|
|
#include <string>
|
2018-11-13 01:49:51 +08:00
|
|
|
|
2011-10-06 21:03:08 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Static Analyzer Checkers Tables generation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
static std::string getPackageFullName(const Record *R);
|
|
|
|
|
|
|
|
static std::string getParentPackageFullName(const Record *R) {
|
|
|
|
std::string name;
|
2012-10-11 04:25:43 +08:00
|
|
|
if (DefInit *DI = dyn_cast<DefInit>(R->getValueInit("ParentPackage")))
|
2011-10-06 21:03:08 +08:00
|
|
|
name = getPackageFullName(DI->getDef());
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::string getPackageFullName(const Record *R) {
|
|
|
|
std::string name = getParentPackageFullName(R);
|
2018-11-13 01:49:51 +08:00
|
|
|
if (!name.empty())
|
|
|
|
name += ".";
|
|
|
|
assert(!R->getValueAsString("PackageName").empty());
|
2017-06-01 03:01:22 +08:00
|
|
|
name += R->getValueAsString("PackageName");
|
|
|
|
return name;
|
2011-10-06 21:03:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static std::string getCheckerFullName(const Record *R) {
|
|
|
|
std::string name = getParentPackageFullName(R);
|
2018-11-13 01:49:51 +08:00
|
|
|
if (!name.empty())
|
|
|
|
name += ".";
|
|
|
|
assert(!R->getValueAsString("CheckerName").empty());
|
|
|
|
name += R->getValueAsString("CheckerName");
|
2011-10-06 21:03:08 +08:00
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::string getStringValue(const Record &R, StringRef field) {
|
2012-10-11 04:25:43 +08:00
|
|
|
if (StringInit *SI = dyn_cast<StringInit>(R.getValueInit(field)))
|
2011-10-06 21:03:08 +08:00
|
|
|
return SI->getValue();
|
|
|
|
return std::string();
|
|
|
|
}
|
|
|
|
|
2012-06-13 13:12:41 +08:00
|
|
|
namespace clang {
|
|
|
|
void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
|
2011-10-06 21:03:08 +08:00
|
|
|
std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker");
|
|
|
|
std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package");
|
|
|
|
|
2018-11-13 01:49:51 +08:00
|
|
|
using SortedRecords = llvm::StringMap<const Record *>;
|
2011-10-06 21:03:08 +08:00
|
|
|
|
|
|
|
OS << "\n#ifdef GET_PACKAGES\n";
|
|
|
|
{
|
|
|
|
SortedRecords sortedPackages;
|
|
|
|
for (unsigned i = 0, e = packages.size(); i != e; ++i)
|
|
|
|
sortedPackages[getPackageFullName(packages[i])] = packages[i];
|
|
|
|
|
|
|
|
for (SortedRecords::iterator
|
|
|
|
I = sortedPackages.begin(), E = sortedPackages.end(); I != E; ++I) {
|
|
|
|
const Record &R = *I->second;
|
|
|
|
|
|
|
|
OS << "PACKAGE(" << "\"";
|
2018-11-13 01:49:51 +08:00
|
|
|
OS.write_escaped(getPackageFullName(&R)) << '\"';
|
2011-10-06 21:03:08 +08:00
|
|
|
OS << ")\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OS << "#endif // GET_PACKAGES\n\n";
|
|
|
|
|
|
|
|
OS << "\n#ifdef GET_CHECKERS\n";
|
|
|
|
for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
|
|
|
|
const Record &R = *checkers[i];
|
|
|
|
|
|
|
|
OS << "CHECKER(" << "\"";
|
2018-11-13 01:49:51 +08:00
|
|
|
OS.write_escaped(getCheckerFullName(&R)) << "\", ";
|
2011-10-06 21:03:08 +08:00
|
|
|
OS << R.getName() << ", ";
|
|
|
|
OS << "\"";
|
2018-11-13 01:49:51 +08:00
|
|
|
OS.write_escaped(getStringValue(R, "HelpText")) << '\"';
|
2011-10-06 21:03:08 +08:00
|
|
|
OS << ")\n";
|
|
|
|
}
|
|
|
|
OS << "#endif // GET_CHECKERS\n\n";
|
|
|
|
}
|
2012-06-13 13:12:41 +08:00
|
|
|
} // end namespace clang
|