Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,16 @@
set(LLVM_LINK_COMPONENTS Support)
add_tablegen(clang-tblgen CLANG
ClangASTNodesEmitter.cpp
ClangAttrEmitter.cpp
ClangCommentCommandInfoEmitter.cpp
ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
ClangCommentHTMLTagsEmitter.cpp
ClangDataCollectorsEmitter.cpp
ClangDiagnosticsEmitter.cpp
ClangOptionDocEmitter.cpp
ClangSACheckersEmitter.cpp
NeonEmitter.cpp
TableGen.cpp
)
set_target_properties(clang-tblgen PROPERTIES FOLDER "Clang tablegenning")

View File

@@ -0,0 +1,229 @@
//=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// These tablegen backends emit Clang AST node tables
//
//===----------------------------------------------------------------------===//
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cctype>
#include <map>
#include <set>
#include <string>
using namespace llvm;
/// ClangASTNodesEmitter - The top-level class emits .inc files containing
/// declarations of Clang statements.
///
namespace {
class ClangASTNodesEmitter {
// A map from a node to each of its derived nodes.
typedef std::multimap<Record*, Record*> ChildMap;
typedef ChildMap::const_iterator ChildIterator;
RecordKeeper &Records;
Record Root;
const std::string &BaseSuffix;
// Create a macro-ized version of a name
static std::string macroName(std::string S) {
for (unsigned i = 0; i < S.size(); ++i)
S[i] = std::toupper(S[i]);
return S;
}
// Return the name to be printed in the base field. Normally this is
// the record's name plus the base suffix, but if it is the root node and
// the suffix is non-empty, it's just the suffix.
std::string baseName(Record &R) {
if (&R == &Root && !BaseSuffix.empty())
return BaseSuffix;
return R.getName().str() + BaseSuffix;
}
std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS,
Record *Base);
public:
explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N,
const std::string &S)
: Records(R), Root(N, SMLoc(), R), BaseSuffix(S)
{}
// run - Output the .inc file contents
void run(raw_ostream &OS);
};
} // end anonymous namespace
//===----------------------------------------------------------------------===//
// Statement Node Tables (.inc file) generation.
//===----------------------------------------------------------------------===//
// Returns the first and last non-abstract subrecords
// Called recursively to ensure that nodes remain contiguous
std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
const ChildMap &Tree,
raw_ostream &OS,
Record *Base) {
std::string BaseName = macroName(Base->getName());
ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
Record *First = nullptr, *Last = nullptr;
// This might be the pseudo-node for Stmt; don't assume it has an Abstract
// bit
if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
First = Last = Base;
for (; i != e; ++i) {
Record *R = i->second;
bool Abstract = R->getValueAsBit("Abstract");
std::string NodeName = macroName(R->getName());
OS << "#ifndef " << NodeName << "\n";
OS << "# define " << NodeName << "(Type, Base) "
<< BaseName << "(Type, Base)\n";
OS << "#endif\n";
if (Abstract)
OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "("
<< R->getName() << ", " << baseName(*Base) << "))\n";
else
OS << NodeName << "(" << R->getName() << ", "
<< baseName(*Base) << ")\n";
if (Tree.find(R) != Tree.end()) {
const std::pair<Record *, Record *> &Result
= EmitNode(Tree, OS, R);
if (!First && Result.first)
First = Result.first;
if (Result.second)
Last = Result.second;
} else {
if (!Abstract) {
Last = R;
if (!First)
First = R;
}
}
OS << "#undef " << NodeName << "\n\n";
}
if (First) {
assert (Last && "Got a first node but not a last node for a range!");
if (Base == &Root)
OS << "LAST_" << macroName(Root.getName()) << "_RANGE(";
else
OS << macroName(Root.getName()) << "_RANGE(";
OS << Base->getName() << ", " << First->getName() << ", "
<< Last->getName() << ")\n\n";
}
return std::make_pair(First, Last);
}
void ClangASTNodesEmitter::run(raw_ostream &OS) {
emitSourceFileHeader("List of AST nodes of a particular kind", OS);
// Write the preamble
OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
OS << "#endif\n";
OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
OS << "# define "
<< macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
OS << "#endif\n\n";
OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
OS << "# define LAST_"
<< macroName(Root.getName()) << "_RANGE(Base, First, Last) "
<< macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
OS << "#endif\n\n";
// Emit statements
const std::vector<Record*> Stmts
= Records.getAllDerivedDefinitions(Root.getName());
ChildMap Tree;
for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
Record *R = Stmts[i];
if (R->getValue("Base"))
Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
else
Tree.insert(std::make_pair(&Root, R));
}
EmitNode(Tree, OS, &Root);
OS << "#undef " << macroName(Root.getName()) << "\n";
OS << "#undef " << macroName(Root.getName()) << "_RANGE\n";
OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n";
OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
}
namespace clang {
void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
const std::string &N, const std::string &S) {
ClangASTNodesEmitter(RK, N, S).run(OS);
}
// Emits and addendum to a .inc file to enumerate the clang declaration
// contexts.
void EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) {
// FIXME: Find a .td file format to allow for this to be represented better.
emitSourceFileHeader("List of AST Decl nodes", OS);
OS << "#ifndef DECL_CONTEXT\n";
OS << "# define DECL_CONTEXT(DECL)\n";
OS << "#endif\n";
OS << "#ifndef DECL_CONTEXT_BASE\n";
OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n";
OS << "#endif\n";
typedef std::set<Record*> RecordSet;
typedef std::vector<Record*> RecordVector;
RecordVector DeclContextsVector
= Records.getAllDerivedDefinitions("DeclContext");
RecordVector Decls = Records.getAllDerivedDefinitions("Decl");
RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end());
for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) {
Record *R = *i;
if (R->getValue("Base")) {
Record *B = R->getValueAsDef("Base");
if (DeclContexts.find(B) != DeclContexts.end()) {
OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n";
DeclContexts.erase(B);
}
}
}
// To keep identical order, RecordVector may be used
// instead of RecordSet.
for (RecordVector::iterator
i = DeclContextsVector.begin(), e = DeclContextsVector.end();
i != e; ++i)
if (DeclContexts.find(*i) != DeclContexts.end())
OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n";
OS << "#undef DECL_CONTEXT\n";
OS << "#undef DECL_CONTEXT_BASE\n";
}
} // end namespace clang

View File

@@ -0,0 +1 @@
b0e2ddd91362a3ef17f591e8d08d4be7738cb2be

View File

@@ -0,0 +1,125 @@
//===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====//
//
// 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 command lists and efficient matchers for command
// names that are used in documentation comments.
//
//===----------------------------------------------------------------------===//
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
using namespace llvm;
namespace clang {
void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("A list of commands useable in documentation "
"comments", OS);
OS << "namespace {\n"
"const CommandInfo Commands[] = {\n";
std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
for (size_t i = 0, e = Tags.size(); i != e; ++i) {
Record &Tag = *Tags[i];
OS << " { "
<< "\"" << Tag.getValueAsString("Name") << "\", "
<< "\"" << Tag.getValueAsString("EndCommandName") << "\", "
<< i << ", "
<< Tag.getValueAsInt("NumArgs") << ", "
<< Tag.getValueAsBit("IsInlineCommand") << ", "
<< Tag.getValueAsBit("IsBlockCommand") << ", "
<< Tag.getValueAsBit("IsBriefCommand") << ", "
<< Tag.getValueAsBit("IsReturnsCommand") << ", "
<< Tag.getValueAsBit("IsParamCommand") << ", "
<< Tag.getValueAsBit("IsTParamCommand") << ", "
<< Tag.getValueAsBit("IsThrowsCommand") << ", "
<< Tag.getValueAsBit("IsDeprecatedCommand") << ", "
<< Tag.getValueAsBit("IsHeaderfileCommand") << ", "
<< Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", "
<< Tag.getValueAsBit("IsVerbatimBlockCommand") << ", "
<< Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", "
<< Tag.getValueAsBit("IsVerbatimLineCommand") << ", "
<< Tag.getValueAsBit("IsDeclarationCommand") << ", "
<< Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", "
<< Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", "
<< Tag.getValueAsBit("IsRecordLikeDeclarationCommand") << ", "
<< /* IsUnknownCommand = */ "0"
<< " }";
if (i + 1 != e)
OS << ",";
OS << "\n";
}
OS << "};\n"
"} // unnamed namespace\n\n";
std::vector<StringMatcher::StringPair> Matches;
for (size_t i = 0, e = Tags.size(); i != e; ++i) {
Record &Tag = *Tags[i];
std::string Name = Tag.getValueAsString("Name");
std::string Return;
raw_string_ostream(Return) << "return &Commands[" << i << "];";
Matches.emplace_back(std::move(Name), std::move(Return));
}
OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n"
<< " StringRef Name) {\n";
StringMatcher("Name", Matches, OS).Emit();
OS << " return nullptr;\n"
<< "}\n\n";
}
static std::string MangleName(StringRef Str) {
std::string Mangled;
for (unsigned i = 0, e = Str.size(); i != e; ++i) {
switch (Str[i]) {
default:
Mangled += Str[i];
break;
case '[':
Mangled += "lsquare";
break;
case ']':
Mangled += "rsquare";
break;
case '{':
Mangled += "lbrace";
break;
case '}':
Mangled += "rbrace";
break;
case '$':
Mangled += "dollar";
break;
case '/':
Mangled += "slash";
break;
}
}
return Mangled;
}
void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("A list of commands useable in documentation "
"comments", OS);
OS << "#ifndef COMMENT_COMMAND\n"
<< "# define COMMENT_COMMAND(NAME)\n"
<< "#endif\n";
std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
for (size_t i = 0, e = Tags.size(); i != e; ++i) {
Record &Tag = *Tags[i];
std::string MangledName = MangleName(Tag.getValueAsString("Name"));
OS << "COMMENT_COMMAND(" << MangledName << ")\n";
}
}
} // end namespace clang

View File

@@ -0,0 +1,85 @@
//===--- ClangCommentHTMLNamedCharacterReferenceEmitter.cpp -----------------=//
//
// 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 an fficient function to translate HTML named
// character references to UTF-8 sequences.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
using namespace llvm;
/// \brief Convert a code point to the corresponding UTF-8 sequence represented
/// as a C string literal.
///
/// \returns true on success.
static bool translateCodePointToUTF8(unsigned CodePoint,
SmallVectorImpl<char> &CLiteral) {
char Translated[UNI_MAX_UTF8_BYTES_PER_CODE_POINT];
char *TranslatedPtr = Translated;
if (!ConvertCodePointToUTF8(CodePoint, TranslatedPtr))
return false;
StringRef UTF8(Translated, TranslatedPtr - Translated);
raw_svector_ostream OS(CLiteral);
OS << "\"";
for (size_t i = 0, e = UTF8.size(); i != e; ++i) {
OS << "\\x";
OS.write_hex(static_cast<unsigned char>(UTF8[i]));
}
OS << "\"";
return true;
}
namespace clang {
void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records,
raw_ostream &OS) {
std::vector<Record *> Tags = Records.getAllDerivedDefinitions("NCR");
std::vector<StringMatcher::StringPair> NameToUTF8;
SmallString<32> CLiteral;
for (std::vector<Record *>::iterator I = Tags.begin(), E = Tags.end();
I != E; ++I) {
Record &Tag = **I;
std::string Spelling = Tag.getValueAsString("Spelling");
uint64_t CodePoint = Tag.getValueAsInt("CodePoint");
CLiteral.clear();
CLiteral.append("return ");
if (!translateCodePointToUTF8(CodePoint, CLiteral)) {
SrcMgr.PrintMessage(Tag.getLoc().front(),
SourceMgr::DK_Error,
Twine("invalid code point"));
continue;
}
CLiteral.append(";");
StringMatcher::StringPair Match(Spelling, CLiteral.str());
NameToUTF8.push_back(Match);
}
emitSourceFileHeader("HTML named character reference to UTF-8 "
"translation", OS);
OS << "StringRef translateHTMLNamedCharacterReferenceToUTF8(\n"
" StringRef Name) {\n";
StringMatcher("Name", NameToUTF8, OS).Emit();
OS << " return StringRef();\n"
<< "}\n\n";
}
} // end namespace clang

View File

@@ -0,0 +1,64 @@
//===--- ClangCommentHTMLTagsEmitter.cpp - Generate HTML tag list for Clang -=//
//
// 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 efficient matchers for HTML tags that are used
// in documentation comments.
//
//===----------------------------------------------------------------------===//
#include "TableGenBackends.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
using namespace llvm;
void clang::EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS) {
std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Tag");
std::vector<StringMatcher::StringPair> Matches;
for (Record *Tag : Tags) {
Matches.emplace_back(Tag->getValueAsString("Spelling"), "return true;");
}
emitSourceFileHeader("HTML tag name matcher", OS);
OS << "bool isHTMLTagName(StringRef Name) {\n";
StringMatcher("Name", Matches, OS).Emit();
OS << " return false;\n"
<< "}\n\n";
}
void clang::EmitClangCommentHTMLTagsProperties(RecordKeeper &Records,
raw_ostream &OS) {
std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Tag");
std::vector<StringMatcher::StringPair> MatchesEndTagOptional;
std::vector<StringMatcher::StringPair> MatchesEndTagForbidden;
for (Record *Tag : Tags) {
std::string Spelling = Tag->getValueAsString("Spelling");
StringMatcher::StringPair Match(Spelling, "return true;");
if (Tag->getValueAsBit("EndTagOptional"))
MatchesEndTagOptional.push_back(Match);
if (Tag->getValueAsBit("EndTagForbidden"))
MatchesEndTagForbidden.push_back(Match);
}
emitSourceFileHeader("HTML tag properties", OS);
OS << "bool isHTMLEndTagOptional(StringRef Name) {\n";
StringMatcher("Name", MatchesEndTagOptional, OS).Emit();
OS << " return false;\n"
<< "}\n\n";
OS << "bool isHTMLEndTagForbidden(StringRef Name) {\n";
StringMatcher("Name", MatchesEndTagForbidden, OS).Emit();
OS << " return false;\n"
<< "}\n\n";
}

View File

@@ -0,0 +1,18 @@
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
using namespace llvm;
namespace clang {
void EmitClangDataCollectors(RecordKeeper &RK, raw_ostream &OS) {
const auto &Defs = RK.getClasses();
for (const auto &Entry : Defs) {
Record &R = *Entry.second;
OS << "DEF_ADD_DATA(" << R.getName() << ", {\n";
auto Code = R.getValue("Code")->getValue();
OS << Code->getAsUnquotedString() << "}\n)";
OS << "\n";
}
OS << "#undef DEF_ADD_DATA\n";
}
} // end namespace clang

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,392 @@
//===- ClangOptionDocEmitter.cpp - Documentation for command line flags ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
// FIXME: Once this has stabilized, consider moving it to LLVM.
//
//===----------------------------------------------------------------------===//
#include "llvm/TableGen/Error.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cctype>
#include <cstring>
#include <map>
using namespace llvm;
namespace clang {
namespace docs {
namespace {
struct DocumentedOption {
Record *Option;
std::vector<Record*> Aliases;
};
struct DocumentedGroup;
struct Documentation {
std::vector<DocumentedGroup> Groups;
std::vector<DocumentedOption> Options;
};
struct DocumentedGroup : Documentation {
Record *Group;
};
// Reorganize the records into a suitable form for emitting documentation.
Documentation extractDocumentation(RecordKeeper &Records) {
Documentation Result;
// Build the tree of groups. The root in the tree is the fake option group
// (Record*)nullptr, which contains all top-level groups and options.
std::map<Record*, std::vector<Record*> > OptionsInGroup;
std::map<Record*, std::vector<Record*> > GroupsInGroup;
std::map<Record*, std::vector<Record*> > Aliases;
std::map<std::string, Record*> OptionsByName;
for (Record *R : Records.getAllDerivedDefinitions("Option"))
OptionsByName[R->getValueAsString("Name")] = R;
auto Flatten = [](Record *R) {
return R->getValue("DocFlatten") && R->getValueAsBit("DocFlatten");
};
auto SkipFlattened = [&](Record *R) -> Record* {
while (R && Flatten(R)) {
auto *G = dyn_cast<DefInit>(R->getValueInit("Group"));
if (!G)
return nullptr;
R = G->getDef();
}
return R;
};
for (Record *R : Records.getAllDerivedDefinitions("OptionGroup")) {
if (Flatten(R))
continue;
Record *Group = nullptr;
if (auto *G = dyn_cast<DefInit>(R->getValueInit("Group")))
Group = SkipFlattened(G->getDef());
GroupsInGroup[Group].push_back(R);
}
for (Record *R : Records.getAllDerivedDefinitions("Option")) {
if (auto *A = dyn_cast<DefInit>(R->getValueInit("Alias"))) {
Aliases[A->getDef()].push_back(R);
continue;
}
// Pretend no-X and Xno-Y options are aliases of X and XY.
std::string Name = R->getValueAsString("Name");
if (Name.size() >= 4) {
if (Name.substr(0, 3) == "no-" && OptionsByName[Name.substr(3)]) {
Aliases[OptionsByName[Name.substr(3)]].push_back(R);
continue;
}
if (Name.substr(1, 3) == "no-" && OptionsByName[Name[0] + Name.substr(4)]) {
Aliases[OptionsByName[Name[0] + Name.substr(4)]].push_back(R);
continue;
}
}
Record *Group = nullptr;
if (auto *G = dyn_cast<DefInit>(R->getValueInit("Group")))
Group = SkipFlattened(G->getDef());
OptionsInGroup[Group].push_back(R);
}
auto CompareByName = [](Record *A, Record *B) {
return A->getValueAsString("Name") < B->getValueAsString("Name");
};
auto CompareByLocation = [](Record *A, Record *B) {
return A->getLoc()[0].getPointer() < B->getLoc()[0].getPointer();
};
auto DocumentationForOption = [&](Record *R) -> DocumentedOption {
auto &A = Aliases[R];
std::sort(A.begin(), A.end(), CompareByName);
return {R, std::move(A)};
};
std::function<Documentation(Record *)> DocumentationForGroup =
[&](Record *R) -> Documentation {
Documentation D;
auto &Groups = GroupsInGroup[R];
std::sort(Groups.begin(), Groups.end(), CompareByLocation);
for (Record *G : Groups) {
D.Groups.emplace_back();
D.Groups.back().Group = G;
Documentation &Base = D.Groups.back();
Base = DocumentationForGroup(G);
}
auto &Options = OptionsInGroup[R];
std::sort(Options.begin(), Options.end(), CompareByName);
for (Record *O : Options)
D.Options.push_back(DocumentationForOption(O));
return D;
};
return DocumentationForGroup(nullptr);
}
// Get the first and successive separators to use for an OptionKind.
std::pair<StringRef,StringRef> getSeparatorsForKind(const Record *OptionKind) {
return StringSwitch<std::pair<StringRef, StringRef>>(OptionKind->getName())
.Cases("KIND_JOINED", "KIND_JOINED_OR_SEPARATE",
"KIND_JOINED_AND_SEPARATE",
"KIND_REMAINING_ARGS_JOINED", {"", " "})
.Case("KIND_COMMAJOINED", {"", ","})
.Default({" ", " "});
}
const unsigned UnlimitedArgs = unsigned(-1);
// Get the number of arguments expected for an option, or -1 if any number of
// arguments are accepted.
unsigned getNumArgsForKind(Record *OptionKind, const Record *Option) {
return StringSwitch<unsigned>(OptionKind->getName())
.Cases("KIND_JOINED", "KIND_JOINED_OR_SEPARATE", "KIND_SEPARATE", 1)
.Cases("KIND_REMAINING_ARGS", "KIND_REMAINING_ARGS_JOINED",
"KIND_COMMAJOINED", UnlimitedArgs)
.Case("KIND_JOINED_AND_SEPARATE", 2)
.Case("KIND_MULTIARG", Option->getValueAsInt("NumArgs"))
.Default(0);
}
bool hasFlag(const Record *OptionOrGroup, StringRef OptionFlag) {
for (const Record *Flag : OptionOrGroup->getValueAsListOfDefs("Flags"))
if (Flag->getName() == OptionFlag)
return true;
return false;
}
bool isExcluded(const Record *OptionOrGroup, const Record *DocInfo) {
// FIXME: Provide a flag to specify the set of exclusions.
for (StringRef Exclusion : DocInfo->getValueAsListOfStrings("ExcludedFlags"))
if (hasFlag(OptionOrGroup, Exclusion))
return true;
return false;
}
std::string escapeRST(StringRef Str) {
std::string Out;
for (auto K : Str) {
if (StringRef("`*|_[]\\").count(K))
Out.push_back('\\');
Out.push_back(K);
}
return Out;
}
StringRef getSphinxOptionID(StringRef OptionName) {
for (auto I = OptionName.begin(), E = OptionName.end(); I != E; ++I)
if (!isalnum(*I) && *I != '-')
return OptionName.substr(0, I - OptionName.begin());
return OptionName;
}
bool canSphinxCopeWithOption(const Record *Option) {
// HACK: Work arond sphinx's inability to cope with punctuation-only options
// such as /? by suppressing them from the option list.
for (char C : Option->getValueAsString("Name"))
if (isalnum(C))
return true;
return false;
}
void emitHeading(int Depth, std::string Heading, raw_ostream &OS) {
assert(Depth < 8 && "groups nested too deeply");
OS << Heading << '\n'
<< std::string(Heading.size(), "=~-_'+<>"[Depth]) << "\n";
}
/// Get the value of field \p Primary, if possible. If \p Primary does not
/// exist, get the value of \p Fallback and escape it for rST emission.
std::string getRSTStringWithTextFallback(const Record *R, StringRef Primary,
StringRef Fallback) {
for (auto Field : {Primary, Fallback}) {
if (auto *V = R->getValue(Field)) {
StringRef Value;
if (auto *SV = dyn_cast_or_null<StringInit>(V->getValue()))
Value = SV->getValue();
else if (auto *CV = dyn_cast_or_null<CodeInit>(V->getValue()))
Value = CV->getValue();
if (!Value.empty())
return Field == Primary ? Value.str() : escapeRST(Value);
}
}
return StringRef();
}
void emitOptionWithArgs(StringRef Prefix, const Record *Option,
ArrayRef<StringRef> Args, raw_ostream &OS) {
OS << Prefix << escapeRST(Option->getValueAsString("Name"));
std::pair<StringRef, StringRef> Separators =
getSeparatorsForKind(Option->getValueAsDef("Kind"));
StringRef Separator = Separators.first;
for (auto Arg : Args) {
OS << Separator << escapeRST(Arg);
Separator = Separators.second;
}
}
void emitOptionName(StringRef Prefix, const Record *Option, raw_ostream &OS) {
// Find the arguments to list after the option.
unsigned NumArgs = getNumArgsForKind(Option->getValueAsDef("Kind"), Option);
std::vector<std::string> Args;
if (!Option->isValueUnset("MetaVarName"))
Args.push_back(Option->getValueAsString("MetaVarName"));
else if (NumArgs == 1)
Args.push_back("<arg>");
while (Args.size() < NumArgs) {
Args.push_back(("<arg" + Twine(Args.size() + 1) + ">").str());
// Use '--args <arg1> <arg2>...' if any number of args are allowed.
if (Args.size() == 2 && NumArgs == UnlimitedArgs) {
Args.back() += "...";
break;
}
}
emitOptionWithArgs(Prefix, Option, std::vector<StringRef>(Args.begin(), Args.end()), OS);
auto AliasArgs = Option->getValueAsListOfStrings("AliasArgs");
if (!AliasArgs.empty()) {
Record *Alias = Option->getValueAsDef("Alias");
OS << " (equivalent to ";
emitOptionWithArgs(
Alias->getValueAsListOfStrings("Prefixes").front(), Alias,
AliasArgs, OS);
OS << ")";
}
}
bool emitOptionNames(const Record *Option, raw_ostream &OS, bool EmittedAny) {
for (auto &Prefix : Option->getValueAsListOfStrings("Prefixes")) {
if (EmittedAny)
OS << ", ";
emitOptionName(Prefix, Option, OS);
EmittedAny = true;
}
return EmittedAny;
}
template <typename Fn>
void forEachOptionName(const DocumentedOption &Option, const Record *DocInfo,
Fn F) {
F(Option.Option);
for (auto *Alias : Option.Aliases)
if (!isExcluded(Alias, DocInfo) && canSphinxCopeWithOption(Option.Option))
F(Alias);
}
void emitOption(const DocumentedOption &Option, const Record *DocInfo,
raw_ostream &OS) {
if (isExcluded(Option.Option, DocInfo))
return;
if (Option.Option->getValueAsDef("Kind")->getName() == "KIND_UNKNOWN" ||
Option.Option->getValueAsDef("Kind")->getName() == "KIND_INPUT")
return;
if (!canSphinxCopeWithOption(Option.Option))
return;
// HACK: Emit a different program name with each option to work around
// sphinx's inability to cope with options that differ only by punctuation
// (eg -ObjC vs -ObjC++, -G vs -G=).
std::vector<std::string> SphinxOptionIDs;
forEachOptionName(Option, DocInfo, [&](const Record *Option) {
for (auto &Prefix : Option->getValueAsListOfStrings("Prefixes"))
SphinxOptionIDs.push_back(
getSphinxOptionID((Prefix + Option->getValueAsString("Name")).str()));
});
assert(!SphinxOptionIDs.empty() && "no flags for option");
static std::map<std::string, int> NextSuffix;
int SphinxWorkaroundSuffix = NextSuffix[*std::max_element(
SphinxOptionIDs.begin(), SphinxOptionIDs.end(),
[&](const std::string &A, const std::string &B) {
return NextSuffix[A] < NextSuffix[B];
})];
for (auto &S : SphinxOptionIDs)
NextSuffix[S] = SphinxWorkaroundSuffix + 1;
if (SphinxWorkaroundSuffix)
OS << ".. program:: " << DocInfo->getValueAsString("Program")
<< SphinxWorkaroundSuffix << "\n";
// Emit the names of the option.
OS << ".. option:: ";
bool EmittedAny = false;
forEachOptionName(Option, DocInfo, [&](const Record *Option) {
EmittedAny = emitOptionNames(Option, OS, EmittedAny);
});
if (SphinxWorkaroundSuffix)
OS << "\n.. program:: " << DocInfo->getValueAsString("Program");
OS << "\n\n";
// Emit the description, if we have one.
std::string Description =
getRSTStringWithTextFallback(Option.Option, "DocBrief", "HelpText");
if (!Description.empty())
OS << Description << "\n\n";
}
void emitDocumentation(int Depth, const Documentation &Doc,
const Record *DocInfo, raw_ostream &OS);
void emitGroup(int Depth, const DocumentedGroup &Group, const Record *DocInfo,
raw_ostream &OS) {
if (isExcluded(Group.Group, DocInfo))
return;
emitHeading(Depth,
getRSTStringWithTextFallback(Group.Group, "DocName", "Name"), OS);
// Emit the description, if we have one.
std::string Description =
getRSTStringWithTextFallback(Group.Group, "DocBrief", "HelpText");
if (!Description.empty())
OS << Description << "\n\n";
// Emit contained options and groups.
emitDocumentation(Depth + 1, Group, DocInfo, OS);
}
void emitDocumentation(int Depth, const Documentation &Doc,
const Record *DocInfo, raw_ostream &OS) {
for (auto &O : Doc.Options)
emitOption(O, DocInfo, OS);
for (auto &G : Doc.Groups)
emitGroup(Depth, G, DocInfo, OS);
}
} // namespace
} // namespace docs
void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS) {
using namespace docs;
const Record *DocInfo = Records.getDef("GlobalDocumentation");
if (!DocInfo) {
PrintFatalError("The GlobalDocumentation top-level definition is missing, "
"no documentation will be generated.");
return;
}
OS << DocInfo->getValueAsString("Intro") << "\n";
OS << ".. program:: " << DocInfo->getValueAsString("Program") << "\n";
emitDocumentation(0, extractDocumentation(Records), DocInfo, OS);
}
} // end namespace clang

View File

@@ -0,0 +1,323 @@
//=- 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.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DenseSet.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <map>
#include <string>
using namespace llvm;
//===----------------------------------------------------------------------===//
// Static Analyzer Checkers Tables generation
//===----------------------------------------------------------------------===//
/// \brief True if it is specified hidden or a parent package is specified
/// as hidden, otherwise false.
static bool isHidden(const Record &R) {
if (R.getValueAsBit("Hidden"))
return true;
// Not declared as hidden, check the parent package if it is hidden.
if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("ParentPackage")))
return isHidden(*DI->getDef());
return false;
}
static bool isCheckerNamed(const Record *R) {
return !R->getValueAsString("CheckerName").empty();
}
static std::string getPackageFullName(const Record *R);
static std::string getParentPackageFullName(const Record *R) {
std::string name;
if (DefInit *DI = dyn_cast<DefInit>(R->getValueInit("ParentPackage")))
name = getPackageFullName(DI->getDef());
return name;
}
static std::string getPackageFullName(const Record *R) {
std::string name = getParentPackageFullName(R);
if (!name.empty()) name += ".";
name += R->getValueAsString("PackageName");
return name;
}
static std::string getCheckerFullName(const Record *R) {
std::string name = getParentPackageFullName(R);
if (isCheckerNamed(R)) {
if (!name.empty()) name += ".";
name += R->getValueAsString("CheckerName");
}
return name;
}
static std::string getStringValue(const Record &R, StringRef field) {
if (StringInit *SI = dyn_cast<StringInit>(R.getValueInit(field)))
return SI->getValue();
return std::string();
}
namespace {
struct GroupInfo {
llvm::DenseSet<const Record*> Checkers;
llvm::DenseSet<const Record *> SubGroups;
bool Hidden;
unsigned Index;
GroupInfo() : Hidden(false) { }
};
}
static void addPackageToCheckerGroup(const Record *package, const Record *group,
llvm::DenseMap<const Record *, GroupInfo *> &recordGroupMap) {
llvm::DenseSet<const Record *> &checkers = recordGroupMap[package]->Checkers;
for (llvm::DenseSet<const Record *>::iterator
I = checkers.begin(), E = checkers.end(); I != E; ++I)
recordGroupMap[group]->Checkers.insert(*I);
llvm::DenseSet<const Record *> &subGroups = recordGroupMap[package]->SubGroups;
for (llvm::DenseSet<const Record *>::iterator
I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
addPackageToCheckerGroup(*I, group, recordGroupMap);
}
namespace clang {
void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker");
llvm::DenseMap<const Record *, unsigned> checkerRecIndexMap;
for (unsigned i = 0, e = checkers.size(); i != e; ++i)
checkerRecIndexMap[checkers[i]] = i;
// Invert the mapping of checkers to package/group into a one to many
// mapping of packages/groups to checkers.
std::map<std::string, GroupInfo> groupInfoByName;
llvm::DenseMap<const Record *, GroupInfo *> recordGroupMap;
std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package");
for (unsigned i = 0, e = packages.size(); i != e; ++i) {
Record *R = packages[i];
std::string fullName = getPackageFullName(R);
if (!fullName.empty()) {
GroupInfo &info = groupInfoByName[fullName];
info.Hidden = isHidden(*R);
recordGroupMap[R] = &info;
}
}
std::vector<Record*>
checkerGroups = Records.getAllDerivedDefinitions("CheckerGroup");
for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) {
Record *R = checkerGroups[i];
std::string name = R->getValueAsString("GroupName");
if (!name.empty()) {
GroupInfo &info = groupInfoByName[name];
recordGroupMap[R] = &info;
}
}
for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
Record *R = checkers[i];
Record *package = nullptr;
if (DefInit *
DI = dyn_cast<DefInit>(R->getValueInit("ParentPackage")))
package = DI->getDef();
if (!isCheckerNamed(R) && !package)
PrintFatalError(R->getLoc(), "Checker '" + R->getName() +
"' is neither named, nor in a package!");
if (isCheckerNamed(R)) {
// Create a pseudo-group to hold this checker.
std::string fullName = getCheckerFullName(R);
GroupInfo &info = groupInfoByName[fullName];
info.Hidden = R->getValueAsBit("Hidden");
recordGroupMap[R] = &info;
info.Checkers.insert(R);
} else {
recordGroupMap[package]->Checkers.insert(R);
}
Record *currR = isCheckerNamed(R) ? R : package;
// Insert the checker and its parent packages into the subgroups set of
// the corresponding parent package.
while (DefInit *DI
= dyn_cast<DefInit>(currR->getValueInit("ParentPackage"))) {
Record *parentPackage = DI->getDef();
recordGroupMap[parentPackage]->SubGroups.insert(currR);
currR = parentPackage;
}
// Insert the checker into the set of its group.
if (DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group")))
recordGroupMap[DI->getDef()]->Checkers.insert(R);
}
// If a package is in group, add all its checkers and its sub-packages
// checkers into the group.
for (unsigned i = 0, e = packages.size(); i != e; ++i)
if (DefInit *DI = dyn_cast<DefInit>(packages[i]->getValueInit("Group")))
addPackageToCheckerGroup(packages[i], DI->getDef(), recordGroupMap);
typedef std::map<std::string, const Record *> SortedRecords;
typedef llvm::DenseMap<const Record *, unsigned> RecToSortIndex;
SortedRecords sortedGroups;
RecToSortIndex groupToSortIndex;
OS << "\n#ifdef GET_GROUPS\n";
{
for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i)
sortedGroups[checkerGroups[i]->getValueAsString("GroupName")]
= checkerGroups[i];
unsigned sortIndex = 0;
for (SortedRecords::iterator
I = sortedGroups.begin(), E = sortedGroups.end(); I != E; ++I) {
const Record *R = I->second;
OS << "GROUP(" << "\"";
OS.write_escaped(R->getValueAsString("GroupName")) << "\"";
OS << ")\n";
groupToSortIndex[R] = sortIndex++;
}
}
OS << "#endif // GET_GROUPS\n\n";
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(" << "\"";
OS.write_escaped(getPackageFullName(&R)) << "\", ";
// Group index
if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
OS << groupToSortIndex[DI->getDef()] << ", ";
else
OS << "-1, ";
// Hidden bit
if (isHidden(R))
OS << "true";
else
OS << "false";
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(" << "\"";
std::string name;
if (isCheckerNamed(&R))
name = getCheckerFullName(&R);
OS.write_escaped(name) << "\", ";
OS << R.getName() << ", ";
OS << getStringValue(R, "DescFile") << ", ";
OS << "\"";
OS.write_escaped(getStringValue(R, "HelpText")) << "\", ";
// Group index
if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
OS << groupToSortIndex[DI->getDef()] << ", ";
else
OS << "-1, ";
// Hidden bit
if (isHidden(R))
OS << "true";
else
OS << "false";
OS << ")\n";
}
OS << "#endif // GET_CHECKERS\n\n";
unsigned index = 0;
for (std::map<std::string, GroupInfo>::iterator
I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I)
I->second.Index = index++;
// Walk through the packages/groups/checkers emitting an array for each
// set of checkers and an array for each set of subpackages.
OS << "\n#ifdef GET_MEMBER_ARRAYS\n";
unsigned maxLen = 0;
for (std::map<std::string, GroupInfo>::iterator
I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
maxLen = std::max(maxLen, (unsigned)I->first.size());
llvm::DenseSet<const Record *> &checkers = I->second.Checkers;
if (!checkers.empty()) {
OS << "static const short CheckerArray" << I->second.Index << "[] = { ";
// Make the output order deterministic.
std::map<int, const Record *> sorted;
for (llvm::DenseSet<const Record *>::iterator
I = checkers.begin(), E = checkers.end(); I != E; ++I)
sorted[(*I)->getID()] = *I;
for (std::map<int, const Record *>::iterator
I = sorted.begin(), E = sorted.end(); I != E; ++I)
OS << checkerRecIndexMap[I->second] << ", ";
OS << "-1 };\n";
}
llvm::DenseSet<const Record *> &subGroups = I->second.SubGroups;
if (!subGroups.empty()) {
OS << "static const short SubPackageArray" << I->second.Index << "[] = { ";
// Make the output order deterministic.
std::map<int, const Record *> sorted;
for (llvm::DenseSet<const Record *>::iterator
I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
sorted[(*I)->getID()] = *I;
for (std::map<int, const Record *>::iterator
I = sorted.begin(), E = sorted.end(); I != E; ++I) {
OS << recordGroupMap[I->second]->Index << ", ";
}
OS << "-1 };\n";
}
}
OS << "#endif // GET_MEMBER_ARRAYS\n\n";
OS << "\n#ifdef GET_CHECKNAME_TABLE\n";
for (std::map<std::string, GroupInfo>::iterator
I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
// Group option string.
OS << " { \"";
OS.write_escaped(I->first) << "\","
<< std::string(maxLen-I->first.size()+1, ' ');
if (I->second.Checkers.empty())
OS << "0, ";
else
OS << "CheckerArray" << I->second.Index << ", ";
// Subgroups.
if (I->second.SubGroups.empty())
OS << "0, ";
else
OS << "SubPackageArray" << I->second.Index << ", ";
OS << (I->second.Hidden ? "true" : "false");
OS << " },\n";
}
OS << "#endif // GET_CHECKNAME_TABLE\n\n";
}
} // end namespace clang

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,297 @@
//===- TableGen.cpp - Top-Level TableGen implementation for Clang ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the main function for Clang's TableGen.
//
//===----------------------------------------------------------------------===//
#include "TableGenBackends.h" // Declares all backends.
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Main.h"
#include "llvm/TableGen/Record.h"
using namespace llvm;
using namespace clang;
enum ActionType {
GenClangAttrClasses,
GenClangAttrParserStringSwitches,
GenClangAttrSubjectMatchRulesParserStringSwitches,
GenClangAttrImpl,
GenClangAttrList,
GenClangAttrSubjectMatchRuleList,
GenClangAttrPCHRead,
GenClangAttrPCHWrite,
GenClangAttrHasAttributeImpl,
GenClangAttrSpellingListIndex,
GenClangAttrASTVisitor,
GenClangAttrTemplateInstantiate,
GenClangAttrParsedAttrList,
GenClangAttrParsedAttrImpl,
GenClangAttrParsedAttrKinds,
GenClangAttrDump,
GenClangDiagsDefs,
GenClangDiagGroups,
GenClangDiagsIndexName,
GenClangCommentNodes,
GenClangDeclNodes,
GenClangStmtNodes,
GenClangSACheckers,
GenClangCommentHTMLTags,
GenClangCommentHTMLTagsProperties,
GenClangCommentHTMLNamedCharacterReferences,
GenClangCommentCommandInfo,
GenClangCommentCommandList,
GenArmNeon,
GenArmNeonSema,
GenArmNeonTest,
GenAttrDocs,
GenDiagDocs,
GenOptDocs,
GenDataCollectors,
GenTestPragmaAttributeSupportedAttributes
};
namespace {
cl::opt<ActionType> Action(
cl::desc("Action to perform:"),
cl::values(
clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
"Generate clang attribute clases"),
clEnumValN(GenClangAttrParserStringSwitches,
"gen-clang-attr-parser-string-switches",
"Generate all parser-related attribute string switches"),
clEnumValN(GenClangAttrSubjectMatchRulesParserStringSwitches,
"gen-clang-attr-subject-match-rules-parser-string-switches",
"Generate all parser-related attribute subject match rule"
"string switches"),
clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
"Generate clang attribute implementations"),
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
"Generate a clang attribute list"),
clEnumValN(GenClangAttrSubjectMatchRuleList,
"gen-clang-attr-subject-match-rule-list",
"Generate a clang attribute subject match rule list"),
clEnumValN(GenClangAttrPCHRead, "gen-clang-attr-pch-read",
"Generate clang PCH attribute reader"),
clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write",
"Generate clang PCH attribute writer"),
clEnumValN(GenClangAttrHasAttributeImpl,
"gen-clang-attr-has-attribute-impl",
"Generate a clang attribute spelling list"),
clEnumValN(GenClangAttrSpellingListIndex,
"gen-clang-attr-spelling-index",
"Generate a clang attribute spelling index"),
clEnumValN(GenClangAttrASTVisitor, "gen-clang-attr-ast-visitor",
"Generate a recursive AST visitor for clang attributes"),
clEnumValN(GenClangAttrTemplateInstantiate,
"gen-clang-attr-template-instantiate",
"Generate a clang template instantiate code"),
clEnumValN(GenClangAttrParsedAttrList,
"gen-clang-attr-parsed-attr-list",
"Generate a clang parsed attribute list"),
clEnumValN(GenClangAttrParsedAttrImpl,
"gen-clang-attr-parsed-attr-impl",
"Generate the clang parsed attribute helpers"),
clEnumValN(GenClangAttrParsedAttrKinds,
"gen-clang-attr-parsed-attr-kinds",
"Generate a clang parsed attribute kinds"),
clEnumValN(GenClangAttrDump, "gen-clang-attr-dump",
"Generate clang attribute dumper"),
clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
"Generate Clang diagnostics definitions"),
clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
"Generate Clang diagnostic groups"),
clEnumValN(GenClangDiagsIndexName, "gen-clang-diags-index-name",
"Generate Clang diagnostic name index"),
clEnumValN(GenClangCommentNodes, "gen-clang-comment-nodes",
"Generate Clang AST comment nodes"),
clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes",
"Generate Clang AST declaration nodes"),
clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
"Generate Clang AST statement nodes"),
clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
"Generate Clang Static Analyzer checkers"),
clEnumValN(GenClangCommentHTMLTags, "gen-clang-comment-html-tags",
"Generate efficient matchers for HTML tag "
"names that are used in documentation comments"),
clEnumValN(GenClangCommentHTMLTagsProperties,
"gen-clang-comment-html-tags-properties",
"Generate efficient matchers for HTML tag "
"properties"),
clEnumValN(GenClangCommentHTMLNamedCharacterReferences,
"gen-clang-comment-html-named-character-references",
"Generate function to translate named character "
"references to UTF-8 sequences"),
clEnumValN(GenClangCommentCommandInfo, "gen-clang-comment-command-info",
"Generate command properties for commands that "
"are used in documentation comments"),
clEnumValN(GenClangCommentCommandList, "gen-clang-comment-command-list",
"Generate list of commands that are used in "
"documentation comments"),
clEnumValN(GenArmNeon, "gen-arm-neon", "Generate arm_neon.h for clang"),
clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
"Generate ARM NEON sema support for clang"),
clEnumValN(GenArmNeonTest, "gen-arm-neon-test",
"Generate ARM NEON tests for clang"),
clEnumValN(GenAttrDocs, "gen-attr-docs",
"Generate attribute documentation"),
clEnumValN(GenDiagDocs, "gen-diag-docs",
"Generate diagnostic documentation"),
clEnumValN(GenOptDocs, "gen-opt-docs", "Generate option documentation"),
clEnumValN(GenDataCollectors, "gen-clang-data-collectors",
"Generate data collectors for AST nodes"),
clEnumValN(GenTestPragmaAttributeSupportedAttributes,
"gen-clang-test-pragma-attribute-supported-attributes",
"Generate a list of attributes supported by #pragma clang "
"attribute for testing purposes")));
cl::opt<std::string>
ClangComponent("clang-component",
cl::desc("Only use warnings from specified component"),
cl::value_desc("component"), cl::Hidden);
bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
switch (Action) {
case GenClangAttrClasses:
EmitClangAttrClass(Records, OS);
break;
case GenClangAttrParserStringSwitches:
EmitClangAttrParserStringSwitches(Records, OS);
break;
case GenClangAttrSubjectMatchRulesParserStringSwitches:
EmitClangAttrSubjectMatchRulesParserStringSwitches(Records, OS);
break;
case GenClangAttrImpl:
EmitClangAttrImpl(Records, OS);
break;
case GenClangAttrList:
EmitClangAttrList(Records, OS);
break;
case GenClangAttrSubjectMatchRuleList:
EmitClangAttrSubjectMatchRuleList(Records, OS);
break;
case GenClangAttrPCHRead:
EmitClangAttrPCHRead(Records, OS);
break;
case GenClangAttrPCHWrite:
EmitClangAttrPCHWrite(Records, OS);
break;
case GenClangAttrHasAttributeImpl:
EmitClangAttrHasAttrImpl(Records, OS);
break;
case GenClangAttrSpellingListIndex:
EmitClangAttrSpellingListIndex(Records, OS);
break;
case GenClangAttrASTVisitor:
EmitClangAttrASTVisitor(Records, OS);
break;
case GenClangAttrTemplateInstantiate:
EmitClangAttrTemplateInstantiate(Records, OS);
break;
case GenClangAttrParsedAttrList:
EmitClangAttrParsedAttrList(Records, OS);
break;
case GenClangAttrParsedAttrImpl:
EmitClangAttrParsedAttrImpl(Records, OS);
break;
case GenClangAttrParsedAttrKinds:
EmitClangAttrParsedAttrKinds(Records, OS);
break;
case GenClangAttrDump:
EmitClangAttrDump(Records, OS);
break;
case GenClangDiagsDefs:
EmitClangDiagsDefs(Records, OS, ClangComponent);
break;
case GenClangDiagGroups:
EmitClangDiagGroups(Records, OS);
break;
case GenClangDiagsIndexName:
EmitClangDiagsIndexName(Records, OS);
break;
case GenClangCommentNodes:
EmitClangASTNodes(Records, OS, "Comment", "");
break;
case GenClangDeclNodes:
EmitClangASTNodes(Records, OS, "Decl", "Decl");
EmitClangDeclContext(Records, OS);
break;
case GenClangStmtNodes:
EmitClangASTNodes(Records, OS, "Stmt", "");
break;
case GenClangSACheckers:
EmitClangSACheckers(Records, OS);
break;
case GenClangCommentHTMLTags:
EmitClangCommentHTMLTags(Records, OS);
break;
case GenClangCommentHTMLTagsProperties:
EmitClangCommentHTMLTagsProperties(Records, OS);
break;
case GenClangCommentHTMLNamedCharacterReferences:
EmitClangCommentHTMLNamedCharacterReferences(Records, OS);
break;
case GenClangCommentCommandInfo:
EmitClangCommentCommandInfo(Records, OS);
break;
case GenClangCommentCommandList:
EmitClangCommentCommandList(Records, OS);
break;
case GenArmNeon:
EmitNeon(Records, OS);
break;
case GenArmNeonSema:
EmitNeonSema(Records, OS);
break;
case GenArmNeonTest:
EmitNeonTest(Records, OS);
break;
case GenAttrDocs:
EmitClangAttrDocs(Records, OS);
break;
case GenDiagDocs:
EmitClangDiagDocs(Records, OS);
break;
case GenOptDocs:
EmitClangOptDocs(Records, OS);
break;
case GenDataCollectors:
EmitClangDataCollectors(Records, OS);
break;
case GenTestPragmaAttributeSupportedAttributes:
EmitTestPragmaAttributeSupportedAttributes(Records, OS);
break;
}
return false;
}
}
int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal(argv[0]);
PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
llvm_shutdown_obj Y;
return TableGenMain(argv[0], &ClangTableGenMain);
}
#ifdef __has_feature
#if __has_feature(address_sanitizer)
#include <sanitizer/lsan_interface.h>
// Disable LeakSanitizer for this binary as it has too many leaks that are not
// very interesting to fix. See compiler-rt/include/sanitizer/lsan_interface.h .
int __lsan_is_turned_off() { return 1; }
#endif // __has_feature(address_sanitizer)
#endif // defined(__has_feature)

View File

@@ -0,0 +1,85 @@
//===- TableGenBackends.h - Declarations for Clang TableGen Backends ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations for all of the Clang TableGen
// backends. A "TableGen backend" is just a function. See
// "$LLVM_ROOT/utils/TableGen/TableGenBackends.h" for more info.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_UTILS_TABLEGEN_TABLEGENBACKENDS_H
#define LLVM_CLANG_UTILS_TABLEGEN_TABLEGENBACKENDS_H
#include <string>
namespace llvm {
class raw_ostream;
class RecordKeeper;
}
using llvm::raw_ostream;
using llvm::RecordKeeper;
namespace clang {
void EmitClangDeclContext(RecordKeeper &RK, raw_ostream &OS);
void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
const std::string &N, const std::string &S);
void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records,
raw_ostream &OS);
void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS);
void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
const std::string &Component);
void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS);
void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS);
void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS);
void EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS);
void EmitClangCommentHTMLTagsProperties(RecordKeeper &Records, raw_ostream &OS);
void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records, raw_ostream &OS);
void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS);
void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS);
void EmitNeon(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS);
void EmitNeon2(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonSema2(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonTest2(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS);
void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS);
void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS);
void EmitClangDataCollectors(RecordKeeper &Records, raw_ostream &OS);
void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
raw_ostream &OS);
} // end namespace clang
#endif