/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====// |
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 command lists and efficient matchers for command |
10 | | // names that are used in documentation comments. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "TableGenBackends.h" |
15 | | |
16 | | #include "llvm/TableGen/Record.h" |
17 | | #include "llvm/TableGen/StringMatcher.h" |
18 | | #include "llvm/TableGen/TableGenBackend.h" |
19 | | #include <vector> |
20 | | |
21 | | using namespace llvm; |
22 | | |
23 | 0 | void clang::EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) { |
24 | 0 | emitSourceFileHeader("A list of commands useable in documentation " |
25 | 0 | "comments", OS); |
26 | |
|
27 | 0 | OS << "namespace {\n" |
28 | 0 | "const CommandInfo Commands[] = {\n"; |
29 | 0 | std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); |
30 | 0 | for (size_t i = 0, e = Tags.size(); i != e; ++i) { |
31 | 0 | Record &Tag = *Tags[i]; |
32 | 0 | OS << " { " |
33 | 0 | << "\"" << Tag.getValueAsString("Name") << "\", " |
34 | 0 | << "\"" << Tag.getValueAsString("EndCommandName") << "\", " |
35 | 0 | << i << ", " |
36 | 0 | << Tag.getValueAsInt("NumArgs") << ", " |
37 | 0 | << Tag.getValueAsBit("IsInlineCommand") << ", " |
38 | 0 | << Tag.getValueAsBit("IsBlockCommand") << ", " |
39 | 0 | << Tag.getValueAsBit("IsBriefCommand") << ", " |
40 | 0 | << Tag.getValueAsBit("IsReturnsCommand") << ", " |
41 | 0 | << Tag.getValueAsBit("IsParamCommand") << ", " |
42 | 0 | << Tag.getValueAsBit("IsTParamCommand") << ", " |
43 | 0 | << Tag.getValueAsBit("IsThrowsCommand") << ", " |
44 | 0 | << Tag.getValueAsBit("IsDeprecatedCommand") << ", " |
45 | 0 | << Tag.getValueAsBit("IsHeaderfileCommand") << ", " |
46 | 0 | << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", " |
47 | 0 | << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", " |
48 | 0 | << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", " |
49 | 0 | << Tag.getValueAsBit("IsVerbatimLineCommand") << ", " |
50 | 0 | << Tag.getValueAsBit("IsDeclarationCommand") << ", " |
51 | 0 | << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", " |
52 | 0 | << Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", " |
53 | 0 | << Tag.getValueAsBit("IsRecordLikeDeclarationCommand") << ", " |
54 | 0 | << /* IsUnknownCommand = */ "0" |
55 | 0 | << " }"; |
56 | 0 | if (i + 1 != e) |
57 | 0 | OS << ","; |
58 | 0 | OS << "\n"; |
59 | 0 | } |
60 | 0 | OS << "};\n" |
61 | 0 | "} // unnamed namespace\n\n"; |
62 | |
|
63 | 0 | std::vector<StringMatcher::StringPair> Matches; |
64 | 0 | for (size_t i = 0, e = Tags.size(); i != e; ++i) { |
65 | 0 | Record &Tag = *Tags[i]; |
66 | 0 | std::string Name = std::string(Tag.getValueAsString("Name")); |
67 | 0 | std::string Return; |
68 | 0 | raw_string_ostream(Return) << "return &Commands[" << i << "];"; |
69 | 0 | Matches.emplace_back(std::move(Name), std::move(Return)); |
70 | 0 | } |
71 | |
|
72 | 0 | OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n" |
73 | 0 | << " StringRef Name) {\n"; |
74 | 0 | StringMatcher("Name", Matches, OS).Emit(); |
75 | 0 | OS << " return nullptr;\n" |
76 | 0 | << "}\n\n"; |
77 | 0 | } |
78 | | |
79 | 0 | static std::string MangleName(StringRef Str) { |
80 | 0 | std::string Mangled; |
81 | 0 | for (unsigned i = 0, e = Str.size(); i != e; ++i) { |
82 | 0 | switch (Str[i]) { |
83 | 0 | default: |
84 | 0 | Mangled += Str[i]; |
85 | 0 | break; |
86 | 0 | case '(': |
87 | 0 | Mangled += "lparen"; |
88 | 0 | break; |
89 | 0 | case ')': |
90 | 0 | Mangled += "rparen"; |
91 | 0 | break; |
92 | 0 | case '[': |
93 | 0 | Mangled += "lsquare"; |
94 | 0 | break; |
95 | 0 | case ']': |
96 | 0 | Mangled += "rsquare"; |
97 | 0 | break; |
98 | 0 | case '{': |
99 | 0 | Mangled += "lbrace"; |
100 | 0 | break; |
101 | 0 | case '}': |
102 | 0 | Mangled += "rbrace"; |
103 | 0 | break; |
104 | 0 | case '$': |
105 | 0 | Mangled += "dollar"; |
106 | 0 | break; |
107 | 0 | case '/': |
108 | 0 | Mangled += "slash"; |
109 | 0 | break; |
110 | 0 | } |
111 | 0 | } |
112 | 0 | return Mangled; |
113 | 0 | } |
114 | | |
115 | 0 | void clang::EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) { |
116 | 0 | emitSourceFileHeader("A list of commands useable in documentation " |
117 | 0 | "comments", OS); |
118 | |
|
119 | 0 | OS << "#ifndef COMMENT_COMMAND\n" |
120 | 0 | << "# define COMMENT_COMMAND(NAME)\n" |
121 | 0 | << "#endif\n"; |
122 | |
|
123 | 0 | std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); |
124 | 0 | for (size_t i = 0, e = Tags.size(); i != e; ++i) { |
125 | 0 | Record &Tag = *Tags[i]; |
126 | 0 | std::string MangledName = MangleName(Tag.getValueAsString("Name")); |
127 | |
|
128 | 0 | OS << "COMMENT_COMMAND(" << MangledName << ")\n"; |
129 | 0 | } |
130 | 0 | } |