Bug Summary

File:tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
Warning:line 1178, column 1
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ClangDiagnosticsEmitter.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/clang/utils/TableGen -I /build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen -I /build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn329677/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/clang/utils/TableGen -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-04-11-031539-24776-1 -x c++ /build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp

/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp

1//=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*-
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These tablegen backends emit Clang diagnostics tables.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/ADT/DenseSet.h"
15#include "llvm/ADT/Optional.h"
16#include "llvm/ADT/PointerUnion.h"
17#include "llvm/ADT/SmallPtrSet.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/StringMap.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/Twine.h"
23#include "llvm/TableGen/Error.h"
24#include "llvm/TableGen/Record.h"
25#include "llvm/TableGen/StringToOffsetTable.h"
26#include "llvm/TableGen/TableGenBackend.h"
27#include <algorithm>
28#include <cctype>
29#include <functional>
30#include <map>
31#include <set>
32using namespace llvm;
33
34//===----------------------------------------------------------------------===//
35// Diagnostic category computation code.
36//===----------------------------------------------------------------------===//
37
38namespace {
39class DiagGroupParentMap {
40 RecordKeeper &Records;
41 std::map<const Record*, std::vector<Record*> > Mapping;
42public:
43 DiagGroupParentMap(RecordKeeper &records) : Records(records) {
44 std::vector<Record*> DiagGroups
45 = Records.getAllDerivedDefinitions("DiagGroup");
46 for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
47 std::vector<Record*> SubGroups =
48 DiagGroups[i]->getValueAsListOfDefs("SubGroups");
49 for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
50 Mapping[SubGroups[j]].push_back(DiagGroups[i]);
51 }
52 }
53
54 const std::vector<Record*> &getParents(const Record *Group) {
55 return Mapping[Group];
56 }
57};
58} // end anonymous namespace.
59
60static std::string
61getCategoryFromDiagGroup(const Record *Group,
62 DiagGroupParentMap &DiagGroupParents) {
63 // If the DiagGroup has a category, return it.
64 std::string CatName = Group->getValueAsString("CategoryName");
65 if (!CatName.empty()) return CatName;
66
67 // The diag group may the subgroup of one or more other diagnostic groups,
68 // check these for a category as well.
69 const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
70 for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
71 CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
72 if (!CatName.empty()) return CatName;
73 }
74 return "";
75}
76
77/// getDiagnosticCategory - Return the category that the specified diagnostic
78/// lives in.
79static std::string getDiagnosticCategory(const Record *R,
80 DiagGroupParentMap &DiagGroupParents) {
81 // If the diagnostic is in a group, and that group has a category, use it.
82 if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
83 // Check the diagnostic's diag group for a category.
84 std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
85 DiagGroupParents);
86 if (!CatName.empty()) return CatName;
87 }
88
89 // If the diagnostic itself has a category, get it.
90 return R->getValueAsString("CategoryName");
91}
92
93namespace {
94 class DiagCategoryIDMap {
95 RecordKeeper &Records;
96 StringMap<unsigned> CategoryIDs;
97 std::vector<std::string> CategoryStrings;
98 public:
99 DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
100 DiagGroupParentMap ParentInfo(Records);
101
102 // The zero'th category is "".
103 CategoryStrings.push_back("");
104 CategoryIDs[""] = 0;
105
106 std::vector<Record*> Diags =
107 Records.getAllDerivedDefinitions("Diagnostic");
108 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
109 std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
110 if (Category.empty()) continue; // Skip diags with no category.
111
112 unsigned &ID = CategoryIDs[Category];
113 if (ID != 0) continue; // Already seen.
114
115 ID = CategoryStrings.size();
116 CategoryStrings.push_back(Category);
117 }
118 }
119
120 unsigned getID(StringRef CategoryString) {
121 return CategoryIDs[CategoryString];
122 }
123
124 typedef std::vector<std::string>::const_iterator const_iterator;
125 const_iterator begin() const { return CategoryStrings.begin(); }
126 const_iterator end() const { return CategoryStrings.end(); }
127 };
128
129 struct GroupInfo {
130 std::vector<const Record*> DiagsInGroup;
131 std::vector<std::string> SubGroups;
132 unsigned IDNo;
133
134 const Record *ExplicitDef;
135
136 GroupInfo() : ExplicitDef(nullptr) {}
137 };
138} // end anonymous namespace.
139
140static bool beforeThanCompare(const Record *LHS, const Record *RHS) {
141 assert(!LHS->getLoc().empty() && !RHS->getLoc().empty())(static_cast <bool> (!LHS->getLoc().empty() &&
!RHS->getLoc().empty()) ? void (0) : __assert_fail ("!LHS->getLoc().empty() && !RHS->getLoc().empty()"
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 141, __extension__ __PRETTY_FUNCTION__))
;
142 return
143 LHS->getLoc().front().getPointer() < RHS->getLoc().front().getPointer();
144}
145
146static bool diagGroupBeforeByName(const Record *LHS, const Record *RHS) {
147 return LHS->getValueAsString("GroupName") <
148 RHS->getValueAsString("GroupName");
149}
150
151static bool beforeThanCompareGroups(const GroupInfo *LHS, const GroupInfo *RHS){
152 assert(!LHS->DiagsInGroup.empty() && !RHS->DiagsInGroup.empty())(static_cast <bool> (!LHS->DiagsInGroup.empty() &&
!RHS->DiagsInGroup.empty()) ? void (0) : __assert_fail ("!LHS->DiagsInGroup.empty() && !RHS->DiagsInGroup.empty()"
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 152, __extension__ __PRETTY_FUNCTION__))
;
153 return beforeThanCompare(LHS->DiagsInGroup.front(),
154 RHS->DiagsInGroup.front());
155}
156
157/// \brief Invert the 1-[0/1] mapping of diags to group into a one to many
158/// mapping of groups to diags in the group.
159static void groupDiagnostics(const std::vector<Record*> &Diags,
160 const std::vector<Record*> &DiagGroups,
161 std::map<std::string, GroupInfo> &DiagsInGroup) {
162
163 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
164 const Record *R = Diags[i];
165 DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group"));
166 if (!DI)
167 continue;
168 assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" &&(static_cast <bool> (R->getValueAsDef("Class")->getName
() != "CLASS_NOTE" && "Note can't be in a DiagGroup")
? void (0) : __assert_fail ("R->getValueAsDef(\"Class\")->getName() != \"CLASS_NOTE\" && \"Note can't be in a DiagGroup\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 169, __extension__ __PRETTY_FUNCTION__))
169 "Note can't be in a DiagGroup")(static_cast <bool> (R->getValueAsDef("Class")->getName
() != "CLASS_NOTE" && "Note can't be in a DiagGroup")
? void (0) : __assert_fail ("R->getValueAsDef(\"Class\")->getName() != \"CLASS_NOTE\" && \"Note can't be in a DiagGroup\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 169, __extension__ __PRETTY_FUNCTION__))
;
170 std::string GroupName = DI->getDef()->getValueAsString("GroupName");
171 DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
172 }
173
174 typedef SmallPtrSet<GroupInfo *, 16> GroupSetTy;
175 GroupSetTy ImplicitGroups;
176
177 // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
178 // groups (these are warnings that GCC supports that clang never produces).
179 for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
180 Record *Group = DiagGroups[i];
181 GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
182 if (Group->isAnonymous()) {
183 if (GI.DiagsInGroup.size() > 1)
184 ImplicitGroups.insert(&GI);
185 } else {
186 if (GI.ExplicitDef)
187 assert(GI.ExplicitDef == Group)(static_cast <bool> (GI.ExplicitDef == Group) ? void (0
) : __assert_fail ("GI.ExplicitDef == Group", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 187, __extension__ __PRETTY_FUNCTION__))
;
188 else
189 GI.ExplicitDef = Group;
190 }
191
192 std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
193 for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
194 GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
195 }
196
197 // Assign unique ID numbers to the groups.
198 unsigned IDNo = 0;
199 for (std::map<std::string, GroupInfo>::iterator
200 I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
201 I->second.IDNo = IDNo;
202
203 // Sort the implicit groups, so we can warn about them deterministically.
204 SmallVector<GroupInfo *, 16> SortedGroups(ImplicitGroups.begin(),
205 ImplicitGroups.end());
206 for (SmallVectorImpl<GroupInfo *>::iterator I = SortedGroups.begin(),
207 E = SortedGroups.end();
208 I != E; ++I) {
209 MutableArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
210 llvm::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare);
211 }
212 llvm::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups);
213
214 // Warn about the same group being used anonymously in multiple places.
215 for (SmallVectorImpl<GroupInfo *>::const_iterator I = SortedGroups.begin(),
216 E = SortedGroups.end();
217 I != E; ++I) {
218 ArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
219
220 if ((*I)->ExplicitDef) {
221 std::string Name = (*I)->ExplicitDef->getValueAsString("GroupName");
222 for (ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
223 DE = GroupDiags.end();
224 DI != DE; ++DI) {
225 const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
226 const Record *NextDiagGroup = GroupInit->getDef();
227 if (NextDiagGroup == (*I)->ExplicitDef)
228 continue;
229
230 SrcMgr.PrintMessage((*DI)->getLoc().front(),
231 SourceMgr::DK_Error,
232 Twine("group '") + Name +
233 "' is referred to anonymously");
234 SrcMgr.PrintMessage((*I)->ExplicitDef->getLoc().front(),
235 SourceMgr::DK_Note, "group defined here");
236 }
237 } else {
238 // If there's no existing named group, we should just warn once and use
239 // notes to list all the other cases.
240 ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
241 DE = GroupDiags.end();
242 assert(DI != DE && "We only care about groups with multiple uses!")(static_cast <bool> (DI != DE && "We only care about groups with multiple uses!"
) ? void (0) : __assert_fail ("DI != DE && \"We only care about groups with multiple uses!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 242, __extension__ __PRETTY_FUNCTION__))
;
243
244 const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
245 const Record *NextDiagGroup = GroupInit->getDef();
246 std::string Name = NextDiagGroup->getValueAsString("GroupName");
247
248 SrcMgr.PrintMessage((*DI)->getLoc().front(),
249 SourceMgr::DK_Error,
250 Twine("group '") + Name +
251 "' is referred to anonymously");
252
253 for (++DI; DI != DE; ++DI) {
254 SrcMgr.PrintMessage((*DI)->getLoc().front(),
255 SourceMgr::DK_Note, "also referenced here");
256 }
257 }
258 }
259}
260
261//===----------------------------------------------------------------------===//
262// Infer members of -Wpedantic.
263//===----------------------------------------------------------------------===//
264
265typedef std::vector<const Record *> RecordVec;
266typedef llvm::DenseSet<const Record *> RecordSet;
267typedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet;
268
269namespace {
270class InferPedantic {
271 typedef llvm::DenseMap<const Record*,
272 std::pair<unsigned, Optional<unsigned> > > GMap;
273
274 DiagGroupParentMap &DiagGroupParents;
275 const std::vector<Record*> &Diags;
276 const std::vector<Record*> DiagGroups;
277 std::map<std::string, GroupInfo> &DiagsInGroup;
278 llvm::DenseSet<const Record*> DiagsSet;
279 GMap GroupCount;
280public:
281 InferPedantic(DiagGroupParentMap &DiagGroupParents,
282 const std::vector<Record*> &Diags,
283 const std::vector<Record*> &DiagGroups,
284 std::map<std::string, GroupInfo> &DiagsInGroup)
285 : DiagGroupParents(DiagGroupParents),
286 Diags(Diags),
287 DiagGroups(DiagGroups),
288 DiagsInGroup(DiagsInGroup) {}
289
290 /// Compute the set of diagnostics and groups that are immediately
291 /// in -Wpedantic.
292 void compute(VecOrSet DiagsInPedantic,
293 VecOrSet GroupsInPedantic);
294
295private:
296 /// Determine whether a group is a subgroup of another group.
297 bool isSubGroupOfGroup(const Record *Group,
298 llvm::StringRef RootGroupName);
299
300 /// Determine if the diagnostic is an extension.
301 bool isExtension(const Record *Diag);
302
303 /// Determine if the diagnostic is off by default.
304 bool isOffByDefault(const Record *Diag);
305
306 /// Increment the count for a group, and transitively marked
307 /// parent groups when appropriate.
308 void markGroup(const Record *Group);
309
310 /// Return true if the diagnostic is in a pedantic group.
311 bool groupInPedantic(const Record *Group, bool increment = false);
312};
313} // end anonymous namespace
314
315bool InferPedantic::isSubGroupOfGroup(const Record *Group,
316 llvm::StringRef GName) {
317
318 const std::string &GroupName = Group->getValueAsString("GroupName");
319 if (GName == GroupName)
320 return true;
321
322 const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
323 for (unsigned i = 0, e = Parents.size(); i != e; ++i)
324 if (isSubGroupOfGroup(Parents[i], GName))
325 return true;
326
327 return false;
328}
329
330/// Determine if the diagnostic is an extension.
331bool InferPedantic::isExtension(const Record *Diag) {
332 const std::string &ClsName = Diag->getValueAsDef("Class")->getName();
333 return ClsName == "CLASS_EXTENSION";
334}
335
336bool InferPedantic::isOffByDefault(const Record *Diag) {
337 const std::string &DefSeverity =
338 Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name");
339 return DefSeverity == "Ignored";
340}
341
342bool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
343 GMap::mapped_type &V = GroupCount[Group];
344 // Lazily compute the threshold value for the group count.
345 if (!V.second.hasValue()) {
346 const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
347 V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
348 }
349
350 if (increment)
351 ++V.first;
352
353 // Consider a group in -Wpendatic IFF if has at least one diagnostic
354 // or subgroup AND all of those diagnostics and subgroups are covered
355 // by -Wpedantic via our computation.
356 return V.first != 0 && V.first == V.second.getValue();
357}
358
359void InferPedantic::markGroup(const Record *Group) {
360 // If all the diagnostics and subgroups have been marked as being
361 // covered by -Wpedantic, increment the count of parent groups. Once the
362 // group's count is equal to the number of subgroups and diagnostics in
363 // that group, we can safely add this group to -Wpedantic.
364 if (groupInPedantic(Group, /* increment */ true)) {
365 const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
366 for (unsigned i = 0, e = Parents.size(); i != e; ++i)
367 markGroup(Parents[i]);
368 }
369}
370
371void InferPedantic::compute(VecOrSet DiagsInPedantic,
372 VecOrSet GroupsInPedantic) {
373 // All extensions that are not on by default are implicitly in the
374 // "pedantic" group. For those that aren't explicitly included in -Wpedantic,
375 // mark them for consideration to be included in -Wpedantic directly.
376 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
377 Record *R = Diags[i];
378 if (isExtension(R) && isOffByDefault(R)) {
379 DiagsSet.insert(R);
380 if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
381 const Record *GroupRec = Group->getDef();
382 if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
383 markGroup(GroupRec);
384 }
385 }
386 }
387 }
388
389 // Compute the set of diagnostics that are directly in -Wpedantic. We
390 // march through Diags a second time to ensure the results are emitted
391 // in deterministic order.
392 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
393 Record *R = Diags[i];
394 if (!DiagsSet.count(R))
395 continue;
396 // Check if the group is implicitly in -Wpedantic. If so,
397 // the diagnostic should not be directly included in the -Wpedantic
398 // diagnostic group.
399 if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group")))
400 if (groupInPedantic(Group->getDef()))
401 continue;
402
403 // The diagnostic is not included in a group that is (transitively) in
404 // -Wpedantic. Include it in -Wpedantic directly.
405 if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>())
406 V->push_back(R);
407 else {
408 DiagsInPedantic.get<RecordSet*>()->insert(R);
409 }
410 }
411
412 if (!GroupsInPedantic)
413 return;
414
415 // Compute the set of groups that are directly in -Wpedantic. We
416 // march through the groups to ensure the results are emitted
417 /// in a deterministc order.
418 for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) {
419 Record *Group = DiagGroups[i];
420 if (!groupInPedantic(Group))
421 continue;
422
423 unsigned ParentsInPedantic = 0;
424 const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
425 for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) {
426 if (groupInPedantic(Parents[j]))
427 ++ParentsInPedantic;
428 }
429 // If all the parents are in -Wpedantic, this means that this diagnostic
430 // group will be indirectly included by -Wpedantic already. In that
431 // case, do not add it directly to -Wpedantic. If the group has no
432 // parents, obviously it should go into -Wpedantic.
433 if (Parents.size() > 0 && ParentsInPedantic == Parents.size())
434 continue;
435
436 if (RecordVec *V = GroupsInPedantic.dyn_cast<RecordVec*>())
437 V->push_back(Group);
438 else {
439 GroupsInPedantic.get<RecordSet*>()->insert(Group);
440 }
441 }
442}
443
444//===----------------------------------------------------------------------===//
445// Warning Tables (.inc file) generation.
446//===----------------------------------------------------------------------===//
447
448static bool isError(const Record &Diag) {
449 const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
450 return ClsName == "CLASS_ERROR";
451}
452
453static bool isRemark(const Record &Diag) {
454 const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
455 return ClsName == "CLASS_REMARK";
456}
457
458/// ClangDiagsDefsEmitter - The top-level class emits .def files containing
459/// declarations of Clang diagnostics.
460namespace clang {
461void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
462 const std::string &Component) {
463 // Write the #if guard
464 if (!Component.empty()) {
465 std::string ComponentName = StringRef(Component).upper();
466 OS << "#ifdef " << ComponentName << "START\n";
467 OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
468 << ",\n";
469 OS << "#undef " << ComponentName << "START\n";
470 OS << "#endif\n\n";
471 }
472
473 const std::vector<Record*> &Diags =
474 Records.getAllDerivedDefinitions("Diagnostic");
475
476 std::vector<Record*> DiagGroups
477 = Records.getAllDerivedDefinitions("DiagGroup");
478
479 std::map<std::string, GroupInfo> DiagsInGroup;
480 groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
481
482 DiagCategoryIDMap CategoryIDs(Records);
483 DiagGroupParentMap DGParentMap(Records);
484
485 // Compute the set of diagnostics that are in -Wpedantic.
486 RecordSet DiagsInPedantic;
487 InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
488 inferPedantic.compute(&DiagsInPedantic, (RecordVec*)nullptr);
489
490 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
491 const Record &R = *Diags[i];
492
493 // Check if this is an error that is accidentally in a warning
494 // group.
495 if (isError(R)) {
496 if (DefInit *Group = dyn_cast<DefInit>(R.getValueInit("Group"))) {
497 const Record *GroupRec = Group->getDef();
498 const std::string &GroupName = GroupRec->getValueAsString("GroupName");
499 PrintFatalError(R.getLoc(), "Error " + R.getName() +
500 " cannot be in a warning group [" + GroupName + "]");
501 }
502 }
503
504 // Check that all remarks have an associated diagnostic group.
505 if (isRemark(R)) {
506 if (!isa<DefInit>(R.getValueInit("Group"))) {
507 PrintFatalError(R.getLoc(), "Error " + R.getName() +
508 " not in any diagnostic group");
509 }
510 }
511
512 // Filter by component.
513 if (!Component.empty() && Component != R.getValueAsString("Component"))
514 continue;
515
516 OS << "DIAG(" << R.getName() << ", ";
517 OS << R.getValueAsDef("Class")->getName();
518 OS << ", (unsigned)diag::Severity::"
519 << R.getValueAsDef("DefaultSeverity")->getValueAsString("Name");
520
521 // Description string.
522 OS << ", \"";
523 OS.write_escaped(R.getValueAsString("Text")) << '"';
524
525 // Warning associated with the diagnostic. This is stored as an index into
526 // the alphabetically sorted warning table.
527 if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
528 std::map<std::string, GroupInfo>::iterator I =
529 DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
530 assert(I != DiagsInGroup.end())(static_cast <bool> (I != DiagsInGroup.end()) ? void (0
) : __assert_fail ("I != DiagsInGroup.end()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 530, __extension__ __PRETTY_FUNCTION__))
;
531 OS << ", " << I->second.IDNo;
532 } else if (DiagsInPedantic.count(&R)) {
533 std::map<std::string, GroupInfo>::iterator I =
534 DiagsInGroup.find("pedantic");
535 assert(I != DiagsInGroup.end() && "pedantic group not defined")(static_cast <bool> (I != DiagsInGroup.end() &&
"pedantic group not defined") ? void (0) : __assert_fail ("I != DiagsInGroup.end() && \"pedantic group not defined\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 535, __extension__ __PRETTY_FUNCTION__))
;
536 OS << ", " << I->second.IDNo;
537 } else {
538 OS << ", 0";
539 }
540
541 // SFINAE response.
542 OS << ", " << R.getValueAsDef("SFINAE")->getName();
543
544 // Default warning has no Werror bit.
545 if (R.getValueAsBit("WarningNoWerror"))
546 OS << ", true";
547 else
548 OS << ", false";
549
550 if (R.getValueAsBit("ShowInSystemHeader"))
551 OS << ", true";
552 else
553 OS << ", false";
554
555 // Category number.
556 OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
557 OS << ")\n";
558 }
559}
560} // end namespace clang
561
562//===----------------------------------------------------------------------===//
563// Warning Group Tables generation
564//===----------------------------------------------------------------------===//
565
566static std::string getDiagCategoryEnum(llvm::StringRef name) {
567 if (name.empty())
568 return "DiagCat_None";
569 SmallString<256> enumName = llvm::StringRef("DiagCat_");
570 for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
571 enumName += isalnum(*I) ? *I : '_';
572 return enumName.str();
573}
574
575/// \brief Emit the array of diagnostic subgroups.
576///
577/// The array of diagnostic subgroups contains for each group a list of its
578/// subgroups. The individual lists are separated by '-1'. Groups with no
579/// subgroups are skipped.
580///
581/// \code
582/// static const int16_t DiagSubGroups[] = {
583/// /* Empty */ -1,
584/// /* DiagSubGroup0 */ 142, -1,
585/// /* DiagSubGroup13 */ 265, 322, 399, -1
586/// }
587/// \endcode
588///
589static void emitDiagSubGroups(std::map<std::string, GroupInfo> &DiagsInGroup,
590 RecordVec &GroupsInPedantic, raw_ostream &OS) {
591 OS << "static const int16_t DiagSubGroups[] = {\n"
592 << " /* Empty */ -1,\n";
593 for (auto const &I : DiagsInGroup) {
594 const bool IsPedantic = I.first == "pedantic";
595
596 const std::vector<std::string> &SubGroups = I.second.SubGroups;
597 if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
598 OS << " /* DiagSubGroup" << I.second.IDNo << " */ ";
599 for (auto const &SubGroup : SubGroups) {
600 std::map<std::string, GroupInfo>::const_iterator RI =
601 DiagsInGroup.find(SubGroup);
602 assert(RI != DiagsInGroup.end() && "Referenced without existing?")(static_cast <bool> (RI != DiagsInGroup.end() &&
"Referenced without existing?") ? void (0) : __assert_fail (
"RI != DiagsInGroup.end() && \"Referenced without existing?\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 602, __extension__ __PRETTY_FUNCTION__))
;
603 OS << RI->second.IDNo << ", ";
604 }
605 // Emit the groups implicitly in "pedantic".
606 if (IsPedantic) {
607 for (auto const &Group : GroupsInPedantic) {
608 const std::string &GroupName = Group->getValueAsString("GroupName");
609 std::map<std::string, GroupInfo>::const_iterator RI =
610 DiagsInGroup.find(GroupName);
611 assert(RI != DiagsInGroup.end() && "Referenced without existing?")(static_cast <bool> (RI != DiagsInGroup.end() &&
"Referenced without existing?") ? void (0) : __assert_fail (
"RI != DiagsInGroup.end() && \"Referenced without existing?\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 611, __extension__ __PRETTY_FUNCTION__))
;
612 OS << RI->second.IDNo << ", ";
613 }
614 }
615
616 OS << "-1,\n";
617 }
618 }
619 OS << "};\n\n";
620}
621
622/// \brief Emit the list of diagnostic arrays.
623///
624/// This data structure is a large array that contains itself arrays of varying
625/// size. Each array represents a list of diagnostics. The different arrays are
626/// separated by the value '-1'.
627///
628/// \code
629/// static const int16_t DiagArrays[] = {
630/// /* Empty */ -1,
631/// /* DiagArray1 */ diag::warn_pragma_message,
632/// -1,
633/// /* DiagArray2 */ diag::warn_abs_too_small,
634/// diag::warn_unsigned_abs,
635/// diag::warn_wrong_absolute_value_type,
636/// -1
637/// };
638/// \endcode
639///
640static void emitDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
641 RecordVec &DiagsInPedantic, raw_ostream &OS) {
642 OS << "static const int16_t DiagArrays[] = {\n"
643 << " /* Empty */ -1,\n";
644 for (auto const &I : DiagsInGroup) {
645 const bool IsPedantic = I.first == "pedantic";
646
647 const std::vector<const Record *> &V = I.second.DiagsInGroup;
648 if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
649 OS << " /* DiagArray" << I.second.IDNo << " */ ";
650 for (auto *Record : V)
651 OS << "diag::" << Record->getName() << ", ";
652 // Emit the diagnostics implicitly in "pedantic".
653 if (IsPedantic) {
654 for (auto const &Diag : DiagsInPedantic)
655 OS << "diag::" << Diag->getName() << ", ";
656 }
657 OS << "-1,\n";
658 }
659 }
660 OS << "};\n\n";
661}
662
663/// \brief Emit a list of group names.
664///
665/// This creates a long string which by itself contains a list of pascal style
666/// strings, which consist of a length byte directly followed by the string.
667///
668/// \code
669/// static const char DiagGroupNames[] = {
670/// \000\020#pragma-messages\t#warnings\020CFString-literal"
671/// };
672/// \endcode
673static void emitDiagGroupNames(StringToOffsetTable &GroupNames,
674 raw_ostream &OS) {
675 OS << "static const char DiagGroupNames[] = {\n";
676 GroupNames.EmitString(OS);
677 OS << "};\n\n";
678}
679
680/// \brief Emit diagnostic arrays and related data structures.
681///
682/// This creates the actual diagnostic array, an array of diagnostic subgroups
683/// and an array of subgroup names.
684///
685/// \code
686/// #ifdef GET_DIAG_ARRAYS
687/// static const int16_t DiagArrays[];
688/// static const int16_t DiagSubGroups[];
689/// static const char DiagGroupNames[];
690/// #endif
691/// \endcode
692static void emitAllDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
693 RecordVec &DiagsInPedantic,
694 RecordVec &GroupsInPedantic,
695 StringToOffsetTable &GroupNames,
696 raw_ostream &OS) {
697 OS << "\n#ifdef GET_DIAG_ARRAYS\n";
698 emitDiagArrays(DiagsInGroup, DiagsInPedantic, OS);
699 emitDiagSubGroups(DiagsInGroup, GroupsInPedantic, OS);
700 emitDiagGroupNames(GroupNames, OS);
701 OS << "#endif // GET_DIAG_ARRAYS\n\n";
702}
703
704/// \brief Emit diagnostic table.
705///
706/// The table is sorted by the name of the diagnostic group. Each element
707/// consists of the name of the diagnostic group (given as offset in the
708/// group name table), a reference to a list of diagnostics (optional) and a
709/// reference to a set of subgroups (optional).
710///
711/// \code
712/// #ifdef GET_DIAG_TABLE
713/// {/* abi */ 159, /* DiagArray11 */ 19, /* Empty */ 0},
714/// {/* aggregate-return */ 180, /* Empty */ 0, /* Empty */ 0},
715/// {/* all */ 197, /* Empty */ 0, /* DiagSubGroup13 */ 3},
716/// {/* deprecated */ 1981,/* DiagArray1 */ 348, /* DiagSubGroup3 */ 9},
717/// #endif
718/// \endcode
719static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
720 RecordVec &DiagsInPedantic,
721 RecordVec &GroupsInPedantic,
722 StringToOffsetTable &GroupNames, raw_ostream &OS) {
723 unsigned MaxLen = 0;
724
725 for (auto const &I: DiagsInGroup)
726 MaxLen = std::max(MaxLen, (unsigned)I.first.size());
727
728 OS << "\n#ifdef GET_DIAG_TABLE\n";
729 unsigned SubGroupIndex = 1, DiagArrayIndex = 1;
730 for (auto const &I: DiagsInGroup) {
731 // Group option string.
732 OS << " { /* ";
733 if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
734 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
735 "0123456789!@#$%^*-+=:?") !=
736 std::string::npos)
737 PrintFatalError("Invalid character in diagnostic group '" + I.first +
738 "'");
739 OS << I.first << " */ " << std::string(MaxLen - I.first.size(), ' ');
740 // Store a pascal-style length byte at the beginning of the string.
741 std::string Name = char(I.first.size()) + I.first;
742 OS << GroupNames.GetOrAddStringOffset(Name, false) << ", ";
743
744 // Special handling for 'pedantic'.
745 const bool IsPedantic = I.first == "pedantic";
746
747 // Diagnostics in the group.
748 const std::vector<const Record *> &V = I.second.DiagsInGroup;
749 const bool hasDiags =
750 !V.empty() || (IsPedantic && !DiagsInPedantic.empty());
751 if (hasDiags) {
752 OS << "/* DiagArray" << I.second.IDNo << " */ " << DiagArrayIndex
753 << ", ";
754 if (IsPedantic)
755 DiagArrayIndex += DiagsInPedantic.size();
756 DiagArrayIndex += V.size() + 1;
757 } else {
758 OS << "/* Empty */ 0, ";
759 }
760
761 // Subgroups.
762 const std::vector<std::string> &SubGroups = I.second.SubGroups;
763 const bool hasSubGroups =
764 !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty());
765 if (hasSubGroups) {
766 OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex;
767 if (IsPedantic)
768 SubGroupIndex += GroupsInPedantic.size();
769 SubGroupIndex += SubGroups.size() + 1;
770 } else {
771 OS << "/* Empty */ 0";
772 }
773
774 OS << " },\n";
775 }
776 OS << "#endif // GET_DIAG_TABLE\n\n";
777}
778
779/// \brief Emit the table of diagnostic categories.
780///
781/// The table has the form of macro calls that have two parameters. The
782/// category's name as well as an enum that represents the category. The
783/// table can be used by defining the macro 'CATEGORY' and including this
784/// table right after.
785///
786/// \code
787/// #ifdef GET_CATEGORY_TABLE
788/// CATEGORY("Semantic Issue", DiagCat_Semantic_Issue)
789/// CATEGORY("Lambda Issue", DiagCat_Lambda_Issue)
790/// #endif
791/// \endcode
792static void emitCategoryTable(RecordKeeper &Records, raw_ostream &OS) {
793 DiagCategoryIDMap CategoriesByID(Records);
794 OS << "\n#ifdef GET_CATEGORY_TABLE\n";
795 for (auto const &C : CategoriesByID)
796 OS << "CATEGORY(\"" << C << "\", " << getDiagCategoryEnum(C) << ")\n";
797 OS << "#endif // GET_CATEGORY_TABLE\n\n";
798}
799
800namespace clang {
801void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
802 // Compute a mapping from a DiagGroup to all of its parents.
803 DiagGroupParentMap DGParentMap(Records);
804
805 std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic");
806
807 std::vector<Record *> DiagGroups =
808 Records.getAllDerivedDefinitions("DiagGroup");
809
810 std::map<std::string, GroupInfo> DiagsInGroup;
811 groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
812
813 // All extensions are implicitly in the "pedantic" group. Record the
814 // implicit set of groups in the "pedantic" group, and use this information
815 // later when emitting the group information for Pedantic.
816 RecordVec DiagsInPedantic;
817 RecordVec GroupsInPedantic;
818 InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
819 inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
820
821 StringToOffsetTable GroupNames;
822 for (std::map<std::string, GroupInfo>::const_iterator
823 I = DiagsInGroup.begin(),
824 E = DiagsInGroup.end();
825 I != E; ++I) {
826 // Store a pascal-style length byte at the beginning of the string.
827 std::string Name = char(I->first.size()) + I->first;
828 GroupNames.GetOrAddStringOffset(Name, false);
829 }
830
831 emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
832 OS);
833 emitDiagTable(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
834 OS);
835 emitCategoryTable(Records, OS);
836}
837} // end namespace clang
838
839//===----------------------------------------------------------------------===//
840// Diagnostic name index generation
841//===----------------------------------------------------------------------===//
842
843namespace {
844struct RecordIndexElement
845{
846 RecordIndexElement() {}
847 explicit RecordIndexElement(Record const &R):
848 Name(R.getName()) {}
849
850 std::string Name;
851};
852} // end anonymous namespace.
853
854namespace clang {
855void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
856 const std::vector<Record*> &Diags =
857 Records.getAllDerivedDefinitions("Diagnostic");
858
859 std::vector<RecordIndexElement> Index;
860 Index.reserve(Diags.size());
861 for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
862 const Record &R = *(Diags[i]);
863 Index.push_back(RecordIndexElement(R));
864 }
865
866 llvm::sort(Index.begin(), Index.end(),
867 [](const RecordIndexElement &Lhs, const RecordIndexElement &Rhs) {
868 return Lhs.Name < Rhs.Name;
869 });
870
871 for (unsigned i = 0, e = Index.size(); i != e; ++i) {
872 const RecordIndexElement &R = Index[i];
873
874 OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
875 }
876}
877
878//===----------------------------------------------------------------------===//
879// Diagnostic documentation generation
880//===----------------------------------------------------------------------===//
881
882namespace docs {
883namespace {
884
885/// Diagnostic text, parsed into pieces.
886struct DiagText {
887 struct Piece {
888 // This type and its derived classes are move-only.
889 Piece() {}
890 Piece(Piece &&O) {}
891 Piece &operator=(Piece &&O) { return *this; }
892
893 virtual void print(std::vector<std::string> &RST) = 0;
894 virtual ~Piece() {}
895 };
896 struct TextPiece : Piece {
897 StringRef Role;
898 std::string Text;
899 void print(std::vector<std::string> &RST) override;
900 };
901 struct PlaceholderPiece : Piece {
902 int Index;
903 void print(std::vector<std::string> &RST) override;
904 };
905 struct SelectPiece : Piece {
906 SelectPiece() {}
907 SelectPiece(SelectPiece &&O) noexcept : Options(std::move(O.Options)) {}
908 std::vector<DiagText> Options;
909 void print(std::vector<std::string> &RST) override;
910 };
911
912 std::vector<std::unique_ptr<Piece>> Pieces;
913
914 DiagText();
915 DiagText(DiagText &&O) noexcept : Pieces(std::move(O.Pieces)) {}
916
917 DiagText(StringRef Text);
918 DiagText(StringRef Kind, StringRef Text);
919
920 template<typename P> void add(P Piece) {
921 Pieces.push_back(llvm::make_unique<P>(std::move(Piece)));
922 }
923 void print(std::vector<std::string> &RST);
924};
925
926DiagText parseDiagText(StringRef &Text, bool Nested = false) {
927 DiagText Parsed;
928
929 while (!Text.empty()) {
930 size_t End = (size_t)-2;
931 do
932 End = Nested ? Text.find_first_of("%|}", End + 2)
933 : Text.find_first_of('%', End + 2);
934 while (End < Text.size() - 1 && Text[End] == '%' && Text[End + 1] == '%');
935
936 if (End) {
937 DiagText::TextPiece Piece;
938 Piece.Role = "diagtext";
939 Piece.Text = Text.slice(0, End);
940 Parsed.add(std::move(Piece));
941 Text = Text.slice(End, StringRef::npos);
942 if (Text.empty()) break;
943 }
944
945 if (Text[0] == '|' || Text[0] == '}')
946 break;
947
948 // Drop the '%'.
949 Text = Text.drop_front();
950
951 // Extract the (optional) modifier.
952 size_t ModLength = Text.find_first_of("0123456789{");
953 StringRef Modifier = Text.slice(0, ModLength);
954 Text = Text.slice(ModLength, StringRef::npos);
955
956 // FIXME: Handle %ordinal here.
957 if (Modifier == "select" || Modifier == "plural") {
958 DiagText::SelectPiece Select;
959 do {
960 Text = Text.drop_front();
961 if (Modifier == "plural")
962 while (Text[0] != ':')
963 Text = Text.drop_front();
964 Select.Options.push_back(parseDiagText(Text, true));
965 assert(!Text.empty() && "malformed %select")(static_cast <bool> (!Text.empty() && "malformed %select"
) ? void (0) : __assert_fail ("!Text.empty() && \"malformed %select\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 965, __extension__ __PRETTY_FUNCTION__))
;
966 } while (Text.front() == '|');
967 Parsed.add(std::move(Select));
968
969 // Drop the trailing '}n'.
970 Text = Text.drop_front(2);
971 continue;
972 }
973
974 // For %diff, just take the second alternative (tree diagnostic). It would
975 // be preferable to take the first one, and replace the $ with the suitable
976 // placeholders.
977 if (Modifier == "diff") {
978 Text = Text.drop_front(); // '{'
979 parseDiagText(Text, true);
980 Text = Text.drop_front(); // '|'
981
982 DiagText D = parseDiagText(Text, true);
983 for (auto &P : D.Pieces)
984 Parsed.Pieces.push_back(std::move(P));
985
986 Text = Text.drop_front(4); // '}n,m'
987 continue;
988 }
989
990 if (Modifier == "s") {
991 Text = Text.drop_front();
992 DiagText::SelectPiece Select;
993 Select.Options.push_back(DiagText(""));
994 Select.Options.push_back(DiagText("s"));
995 Parsed.add(std::move(Select));
996 continue;
997 }
998
999 assert(!Text.empty() && isdigit(Text[0]) && "malformed placeholder")(static_cast <bool> (!Text.empty() && isdigit(Text
[0]) && "malformed placeholder") ? void (0) : __assert_fail
("!Text.empty() && isdigit(Text[0]) && \"malformed placeholder\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp"
, 999, __extension__ __PRETTY_FUNCTION__))
;
1000 DiagText::PlaceholderPiece Placeholder;
1001 Placeholder.Index = Text[0] - '0';
1002 Parsed.add(std::move(Placeholder));
1003 Text = Text.drop_front();
1004 continue;
1005 }
1006 return Parsed;
1007}
1008
1009DiagText::DiagText() {}
1010
1011DiagText::DiagText(StringRef Text) : DiagText(parseDiagText(Text, false)) {}
1012
1013DiagText::DiagText(StringRef Kind, StringRef Text) : DiagText(parseDiagText(Text, false)) {
1014 TextPiece Prefix;
1015 Prefix.Role = Kind;
1016 Prefix.Text = Kind;
1017 Prefix.Text += ": ";
1018 Pieces.insert(Pieces.begin(),
1019 llvm::make_unique<TextPiece>(std::move(Prefix)));
1020}
1021
1022void escapeRST(StringRef Str, std::string &Out) {
1023 for (auto K : Str) {
1024 if (StringRef("`*|_[]\\").count(K))
1025 Out.push_back('\\');
1026 Out.push_back(K);
1027 }
1028}
1029
1030template<typename It> void padToSameLength(It Begin, It End) {
1031 size_t Width = 0;
1032 for (It I = Begin; I != End; ++I)
1033 Width = std::max(Width, I->size());
1034 for (It I = Begin; I != End; ++I)
1035 (*I) += std::string(Width - I->size(), ' ');
1036}
1037
1038template<typename It> void makeTableRows(It Begin, It End) {
1039 if (Begin == End) return;
1040 padToSameLength(Begin, End);
1041 for (It I = Begin; I != End; ++I)
1042 *I = "|" + *I + "|";
1043}
1044
1045void makeRowSeparator(std::string &Str) {
1046 for (char &K : Str)
1047 K = (K == '|' ? '+' : '-');
1048}
1049
1050void DiagText::print(std::vector<std::string> &RST) {
1051 if (Pieces.empty()) {
1052 RST.push_back("");
1053 return;
1054 }
1055
1056 if (Pieces.size() == 1)
1057 return Pieces[0]->print(RST);
1058
1059 std::string EmptyLinePrefix;
1060 size_t Start = RST.size();
1061 bool HasMultipleLines = true;
1062 for (auto &P : Pieces) {
1063 std::vector<std::string> Lines;
1064 P->print(Lines);
1065 if (Lines.empty())
1066 continue;
1067
1068 // We need a vertical separator if either this or the previous piece is a
1069 // multi-line piece, or this is the last piece.
1070 const char *Separator = (Lines.size() > 1 || HasMultipleLines) ? "|" : "";
1071 HasMultipleLines = Lines.size() > 1;
1072
1073 if (Start + Lines.size() > RST.size())
1074 RST.resize(Start + Lines.size(), EmptyLinePrefix);
1075
1076 padToSameLength(Lines.begin(), Lines.end());
1077 for (size_t I = 0; I != Lines.size(); ++I)
1078 RST[Start + I] += Separator + Lines[I];
1079 std::string Empty(Lines[0].size(), ' ');
1080 for (size_t I = Start + Lines.size(); I != RST.size(); ++I)
1081 RST[I] += Separator + Empty;
1082 EmptyLinePrefix += Separator + Empty;
1083 }
1084 for (size_t I = Start; I != RST.size(); ++I)
1085 RST[I] += "|";
1086 EmptyLinePrefix += "|";
1087
1088 makeRowSeparator(EmptyLinePrefix);
1089 RST.insert(RST.begin() + Start, EmptyLinePrefix);
1090 RST.insert(RST.end(), EmptyLinePrefix);
1091}
1092
1093void DiagText::TextPiece::print(std::vector<std::string> &RST) {
1094 RST.push_back("");
1095 auto &S = RST.back();
1096
1097 StringRef T = Text;
1098 while (!T.empty() && T.front() == ' ') {
1099 RST.back() += " |nbsp| ";
1100 T = T.drop_front();
1101 }
1102
1103 std::string Suffix;
1104 while (!T.empty() && T.back() == ' ') {
1105 Suffix += " |nbsp| ";
1106 T = T.drop_back();
1107 }
1108
1109 if (!T.empty()) {
1110 S += ':';
1111 S += Role;
1112 S += ":`";
1113 escapeRST(T, S);
1114 S += '`';
1115 }
1116
1117 S += Suffix;
1118}
1119
1120void DiagText::PlaceholderPiece::print(std::vector<std::string> &RST) {
1121 RST.push_back(std::string(":placeholder:`") + char('A' + Index) + "`");
1122}
1123
1124void DiagText::SelectPiece::print(std::vector<std::string> &RST) {
1125 std::vector<size_t> SeparatorIndexes;
1126 SeparatorIndexes.push_back(RST.size());
1127 RST.emplace_back();
1128 for (auto &O : Options) {
1129 O.print(RST);
1130 SeparatorIndexes.push_back(RST.size());
1131 RST.emplace_back();
1132 }
1133
1134 makeTableRows(RST.begin() + SeparatorIndexes.front(),
1135 RST.begin() + SeparatorIndexes.back() + 1);
1136 for (size_t I : SeparatorIndexes)
1137 makeRowSeparator(RST[I]);
1138}
1139
1140bool isRemarkGroup(const Record *DiagGroup,
1141 const std::map<std::string, GroupInfo> &DiagsInGroup) {
1142 bool AnyRemarks = false, AnyNonRemarks = false;
1143
1144 std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
1145 auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
1146 for (const Record *Diag : GroupInfo.DiagsInGroup)
1147 (isRemark(*Diag) ? AnyRemarks : AnyNonRemarks) = true;
1148 for (const auto &Name : GroupInfo.SubGroups)
1149 Visit(Name);
1150 };
1151 Visit(DiagGroup->getValueAsString("GroupName"));
1152
1153 if (AnyRemarks && AnyNonRemarks)
1154 PrintFatalError(
1155 DiagGroup->getLoc(),
1156 "Diagnostic group contains both remark and non-remark diagnostics");
1157 return AnyRemarks;
1158}
1159
1160std::string getDefaultSeverity(const Record *Diag) {
1161 return Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name");
1162}
1163
1164std::set<std::string>
1165getDefaultSeverities(const Record *DiagGroup,
1166 const std::map<std::string, GroupInfo> &DiagsInGroup) {
1167 std::set<std::string> States;
1168
1169 std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
7
Calling constructor for 'function'
14
Returning from constructor for 'function'
1170 auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
1171 for (const Record *Diag : GroupInfo.DiagsInGroup)
1172 States.insert(getDefaultSeverity(Diag));
1173 for (const auto &Name : GroupInfo.SubGroups)
1174 Visit(Name);
1175 };
1176 Visit(DiagGroup->getValueAsString("GroupName"));
1177 return States;
1178}
15
Potential memory leak
1179
1180void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
1181 OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
1182}
1183
1184void writeDiagnosticText(StringRef Role, StringRef Text, raw_ostream &OS) {
1185 if (Text == "%0")
1186 OS << "The text of this diagnostic is not controlled by Clang.\n\n";
1187 else {
1188 std::vector<std::string> Out;
1189 DiagText(Role, Text).print(Out);
1190 for (auto &Line : Out)
1191 OS << Line << "\n";
1192 OS << "\n";
1193 }
1194}
1195
1196} // namespace
1197} // namespace docs
1198
1199void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
1200 using namespace docs;
1201
1202 // Get the documentation introduction paragraph.
1203 const Record *Documentation = Records.getDef("GlobalDocumentation");
1204 if (!Documentation) {
1
Assuming 'Documentation' is non-null
2
Taking false branch
1205 PrintFatalError("The Documentation top-level definition is missing, "
1206 "no documentation will be generated.");
1207 return;
1208 }
1209
1210 OS << Documentation->getValueAsString("Intro") << "\n";
1211
1212 std::vector<Record*> Diags =
1213 Records.getAllDerivedDefinitions("Diagnostic");
1214 std::vector<Record*> DiagGroups =
1215 Records.getAllDerivedDefinitions("DiagGroup");
1216 llvm::sort(DiagGroups.begin(), DiagGroups.end(), diagGroupBeforeByName);
1217
1218 DiagGroupParentMap DGParentMap(Records);
1219
1220 std::map<std::string, GroupInfo> DiagsInGroup;
1221 groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
1222
1223 // Compute the set of diagnostics that are in -Wpedantic.
1224 {
1225 RecordSet DiagsInPedanticSet;
1226 RecordSet GroupsInPedanticSet;
1227 InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
1228 inferPedantic.compute(&DiagsInPedanticSet, &GroupsInPedanticSet);
1229 auto &PedDiags = DiagsInGroup["pedantic"];
1230 // Put the diagnostics into a deterministic order.
1231 RecordVec DiagsInPedantic(DiagsInPedanticSet.begin(),
1232 DiagsInPedanticSet.end());
1233 RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(),
1234 GroupsInPedanticSet.end());
1235 llvm::sort(DiagsInPedantic.begin(), DiagsInPedantic.end(),
1236 beforeThanCompare);
1237 llvm::sort(GroupsInPedantic.begin(), GroupsInPedantic.end(),
1238 beforeThanCompare);
1239 PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(),
1240 DiagsInPedantic.begin(),
1241 DiagsInPedantic.end());
1242 for (auto *Group : GroupsInPedantic)
1243 PedDiags.SubGroups.push_back(Group->getValueAsString("GroupName"));
1244 }
1245
1246 // FIXME: Write diagnostic categories and link to diagnostic groups in each.
1247
1248 // Write out the diagnostic groups.
1249 for (const Record *G : DiagGroups) {
1250 bool IsRemarkGroup = isRemarkGroup(G, DiagsInGroup);
1251 auto &GroupInfo = DiagsInGroup[G->getValueAsString("GroupName")];
1252 bool IsSynonym = GroupInfo.DiagsInGroup.empty() &&
3
Assuming the condition is false
1253 GroupInfo.SubGroups.size() == 1;
1254
1255 writeHeader(((IsRemarkGroup ? "-R" : "-W") +
4
'?' condition is false
1256 G->getValueAsString("GroupName")).str(),
1257 OS);
1258
1259 if (!IsSynonym) {
5
Taking true branch
1260 // FIXME: Ideally, all the diagnostics in a group should have the same
1261 // default state, but that is not currently the case.
1262 auto DefaultSeverities = getDefaultSeverities(G, DiagsInGroup);
6
Calling 'getDefaultSeverities'
1263 if (!DefaultSeverities.empty() && !DefaultSeverities.count("Ignored")) {
1264 bool AnyNonErrors = DefaultSeverities.count("Warning") ||
1265 DefaultSeverities.count("Remark");
1266 if (!AnyNonErrors)
1267 OS << "This diagnostic is an error by default, but the flag ``-Wno-"
1268 << G->getValueAsString("GroupName") << "`` can be used to disable "
1269 << "the error.\n\n";
1270 else
1271 OS << "This diagnostic is enabled by default.\n\n";
1272 } else if (DefaultSeverities.size() > 1) {
1273 OS << "Some of the diagnostics controlled by this flag are enabled "
1274 << "by default.\n\n";
1275 }
1276 }
1277
1278 if (!GroupInfo.SubGroups.empty()) {
1279 if (IsSynonym)
1280 OS << "Synonym for ";
1281 else if (GroupInfo.DiagsInGroup.empty())
1282 OS << "Controls ";
1283 else
1284 OS << "Also controls ";
1285
1286 bool First = true;
1287 llvm::sort(GroupInfo.SubGroups.begin(), GroupInfo.SubGroups.end());
1288 for (const auto &Name : GroupInfo.SubGroups) {
1289 if (!First) OS << ", ";
1290 OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_";
1291 First = false;
1292 }
1293 OS << ".\n\n";
1294 }
1295
1296 if (!GroupInfo.DiagsInGroup.empty()) {
1297 OS << "**Diagnostic text:**\n\n";
1298 for (const Record *D : GroupInfo.DiagsInGroup) {
1299 auto Severity = getDefaultSeverity(D);
1300 Severity[0] = tolower(Severity[0]);
1301 if (Severity == "ignored")
1302 Severity = IsRemarkGroup ? "remark" : "warning";
1303 writeDiagnosticText(Severity, D->getValueAsString("Text"), OS);
1304 }
1305 }
1306
1307 auto Doc = G->getValueAsString("Documentation");
1308 if (!Doc.empty())
1309 OS << Doc;
1310 else if (GroupInfo.SubGroups.empty() && GroupInfo.DiagsInGroup.empty())
1311 OS << "This diagnostic flag exists for GCC compatibility, and has no "
1312 "effect in Clang.\n";
1313 OS << "\n";
1314 }
1315}
1316
1317} // end namespace clang

/usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/bits/std_function.h

1// Implementation of std::function -*- C++ -*-
2
3// Copyright (C) 2004-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/bits/function.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{functional}
28 */
29
30#ifndef _GLIBCXX_STD_FUNCTION_H1
31#define _GLIBCXX_STD_FUNCTION_H1 1
32
33#pragma GCC system_header
34
35#if __cplusplus201103L < 201103L
36# include <bits/c++0x_warning.h>
37#else
38
39#if __cpp_rtti199711
40# include <typeinfo>
41#endif
42#include <bits/stl_function.h>
43#include <bits/invoke.h>
44#include <bits/refwrap.h>
45#include <bits/functexcept.h>
46
47namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
48{
49_GLIBCXX_BEGIN_NAMESPACE_VERSION
50
51 /**
52 * Derives from @c unary_function or @c binary_function, or perhaps
53 * nothing, depending on the number of arguments provided. The
54 * primary template is the basis case, which derives nothing.
55 */
56 template<typename _Res, typename... _ArgTypes>
57 struct _Maybe_unary_or_binary_function { };
58
59 /// Derives from @c unary_function, as appropriate.
60 template<typename _Res, typename _T1>
61 struct _Maybe_unary_or_binary_function<_Res, _T1>
62 : std::unary_function<_T1, _Res> { };
63
64 /// Derives from @c binary_function, as appropriate.
65 template<typename _Res, typename _T1, typename _T2>
66 struct _Maybe_unary_or_binary_function<_Res, _T1, _T2>
67 : std::binary_function<_T1, _T2, _Res> { };
68
69
70 /**
71 * @brief Exception class thrown when class template function's
72 * operator() is called with an empty target.
73 * @ingroup exceptions
74 */
75 class bad_function_call : public std::exception
76 {
77 public:
78 virtual ~bad_function_call() noexcept;
79
80 const char* what() const noexcept;
81 };
82
83 /**
84 * Trait identifying "location-invariant" types, meaning that the
85 * address of the object (or any of its members) will not escape.
86 * Trivially copyable types are location-invariant and users can
87 * specialize this trait for other types.
88 */
89 template<typename _Tp>
90 struct __is_location_invariant
91 : is_trivially_copyable<_Tp>::type
92 { };
93
94 class _Undefined_class;
95
96 union _Nocopy_types
97 {
98 void* _M_object;
99 const void* _M_const_object;
100 void (*_M_function_pointer)();
101 void (_Undefined_class::*_M_member_pointer)();
102 };
103
104 union [[gnu::may_alias]] _Any_data
105 {
106 void* _M_access() { return &_M_pod_data[0]; }
107 const void* _M_access() const { return &_M_pod_data[0]; }
108
109 template<typename _Tp>
110 _Tp&
111 _M_access()
112 { return *static_cast<_Tp*>(_M_access()); }
113
114 template<typename _Tp>
115 const _Tp&
116 _M_access() const
117 { return *static_cast<const _Tp*>(_M_access()); }
118
119 _Nocopy_types _M_unused;
120 char _M_pod_data[sizeof(_Nocopy_types)];
121 };
122
123 enum _Manager_operation
124 {
125 __get_type_info,
126 __get_functor_ptr,
127 __clone_functor,
128 __destroy_functor
129 };
130
131 // Simple type wrapper that helps avoid annoying const problems
132 // when casting between void pointers and pointers-to-pointers.
133 template<typename _Tp>
134 struct _Simple_type_wrapper
135 {
136 _Simple_type_wrapper(_Tp __value) : __value(__value) { }
137
138 _Tp __value;
139 };
140
141 template<typename _Tp>
142 struct __is_location_invariant<_Simple_type_wrapper<_Tp> >
143 : __is_location_invariant<_Tp>
144 { };
145
146 template<typename _Signature>
147 class function;
148
149 /// Base class of all polymorphic function object wrappers.
150 class _Function_base
151 {
152 public:
153 static const std::size_t _M_max_size = sizeof(_Nocopy_types);
154 static const std::size_t _M_max_align = __alignof__(_Nocopy_types);
155
156 template<typename _Functor>
157 class _Base_manager
158 {
159 protected:
160 static const bool __stored_locally =
161 (__is_location_invariant<_Functor>::value
162 && sizeof(_Functor) <= _M_max_size
163 && __alignof__(_Functor) <= _M_max_align
164 && (_M_max_align % __alignof__(_Functor) == 0));
165
166 typedef integral_constant<bool, __stored_locally> _Local_storage;
167
168 // Retrieve a pointer to the function object
169 static _Functor*
170 _M_get_pointer(const _Any_data& __source)
171 {
172 const _Functor* __ptr =
173 __stored_locally? std::__addressof(__source._M_access<_Functor>())
174 /* have stored a pointer */ : __source._M_access<_Functor*>();
175 return const_cast<_Functor*>(__ptr);
176 }
177
178 // Clone a location-invariant function object that fits within
179 // an _Any_data structure.
180 static void
181 _M_clone(_Any_data& __dest, const _Any_data& __source, true_type)
182 {
183 ::new (__dest._M_access()) _Functor(__source._M_access<_Functor>());
184 }
185
186 // Clone a function object that is not location-invariant or
187 // that cannot fit into an _Any_data structure.
188 static void
189 _M_clone(_Any_data& __dest, const _Any_data& __source, false_type)
190 {
191 __dest._M_access<_Functor*>() =
192 new _Functor(*__source._M_access<_Functor*>());
193 }
194
195 // Destroying a location-invariant object may still require
196 // destruction.
197 static void
198 _M_destroy(_Any_data& __victim, true_type)
199 {
200 __victim._M_access<_Functor>().~_Functor();
201 }
202
203 // Destroying an object located on the heap.
204 static void
205 _M_destroy(_Any_data& __victim, false_type)
206 {
207 delete __victim._M_access<_Functor*>();
208 }
209
210 public:
211 static bool
212 _M_manager(_Any_data& __dest, const _Any_data& __source,
213 _Manager_operation __op)
214 {
215 switch (__op)
216 {
217#if __cpp_rtti199711
218 case __get_type_info:
219 __dest._M_access<const type_info*>() = &typeid(_Functor);
220 break;
221#endif
222 case __get_functor_ptr:
223 __dest._M_access<_Functor*>() = _M_get_pointer(__source);
224 break;
225
226 case __clone_functor:
227 _M_clone(__dest, __source, _Local_storage());
228 break;
229
230 case __destroy_functor:
231 _M_destroy(__dest, _Local_storage());
232 break;
233 }
234 return false;
235 }
236
237 static void
238 _M_init_functor(_Any_data& __functor, _Functor&& __f)
239 { _M_init_functor(__functor, std::move(__f), _Local_storage()); }
10
Calling '_Base_manager::_M_init_functor'
12
Returned allocated memory
240
241 template<typename _Signature>
242 static bool
243 _M_not_empty_function(const function<_Signature>& __f)
244 { return static_cast<bool>(__f); }
245
246 template<typename _Tp>
247 static bool
248 _M_not_empty_function(_Tp* __fp)
249 { return __fp != nullptr; }
250
251 template<typename _Class, typename _Tp>
252 static bool
253 _M_not_empty_function(_Tp _Class::* __mp)
254 { return __mp != nullptr; }
255
256 template<typename _Tp>
257 static bool
258 _M_not_empty_function(const _Tp&)
259 { return true; }
260
261 private:
262 static void
263 _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
264 { ::new (__functor._M_access()) _Functor(std::move(__f)); }
265
266 static void
267 _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
268 { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
11
Memory is allocated
269 };
270
271 _Function_base() : _M_manager(nullptr) { }
272
273 ~_Function_base()
274 {
275 if (_M_manager)
276 _M_manager(_M_functor, _M_functor, __destroy_functor);
277 }
278
279 bool _M_empty() const { return !_M_manager; }
280
281 typedef bool (*_Manager_type)(_Any_data&, const _Any_data&,
282 _Manager_operation);
283
284 _Any_data _M_functor;
285 _Manager_type _M_manager;
286 };
287
288 template<typename _Signature, typename _Functor>
289 class _Function_handler;
290
291 template<typename _Res, typename _Functor, typename... _ArgTypes>
292 class _Function_handler<_Res(_ArgTypes...), _Functor>
293 : public _Function_base::_Base_manager<_Functor>
294 {
295 typedef _Function_base::_Base_manager<_Functor> _Base;
296
297 public:
298 static _Res
299 _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
300 {
301 return (*_Base::_M_get_pointer(__functor))(
302 std::forward<_ArgTypes>(__args)...);
303 }
304 };
305
306 template<typename _Functor, typename... _ArgTypes>
307 class _Function_handler<void(_ArgTypes...), _Functor>
308 : public _Function_base::_Base_manager<_Functor>
309 {
310 typedef _Function_base::_Base_manager<_Functor> _Base;
311
312 public:
313 static void
314 _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
315 {
316 (*_Base::_M_get_pointer(__functor))(
317 std::forward<_ArgTypes>(__args)...);
318 }
319 };
320
321 template<typename _Class, typename _Member, typename _Res,
322 typename... _ArgTypes>
323 class _Function_handler<_Res(_ArgTypes...), _Member _Class::*>
324 : public _Function_handler<void(_ArgTypes...), _Member _Class::*>
325 {
326 typedef _Function_handler<void(_ArgTypes...), _Member _Class::*>
327 _Base;
328
329 public:
330 static _Res
331 _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
332 {
333 return std::__invoke(_Base::_M_get_pointer(__functor)->__value,
334 std::forward<_ArgTypes>(__args)...);
335 }
336 };
337
338 template<typename _Class, typename _Member, typename... _ArgTypes>
339 class _Function_handler<void(_ArgTypes...), _Member _Class::*>
340 : public _Function_base::_Base_manager<
341 _Simple_type_wrapper< _Member _Class::* > >
342 {
343 typedef _Member _Class::* _Functor;
344 typedef _Simple_type_wrapper<_Functor> _Wrapper;
345 typedef _Function_base::_Base_manager<_Wrapper> _Base;
346
347 public:
348 static bool
349 _M_manager(_Any_data& __dest, const _Any_data& __source,
350 _Manager_operation __op)
351 {
352 switch (__op)
353 {
354#if __cpp_rtti199711
355 case __get_type_info:
356 __dest._M_access<const type_info*>() = &typeid(_Functor);
357 break;
358#endif
359 case __get_functor_ptr:
360 __dest._M_access<_Functor*>() =
361 &_Base::_M_get_pointer(__source)->__value;
362 break;
363
364 default:
365 _Base::_M_manager(__dest, __source, __op);
366 }
367 return false;
368 }
369
370 static void
371 _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
372 {
373 std::__invoke(_Base::_M_get_pointer(__functor)->__value,
374 std::forward<_ArgTypes>(__args)...);
375 }
376 };
377
378 template<typename _From, typename _To>
379 using __check_func_return_type
380 = __or_<is_void<_To>, is_same<_From, _To>, is_convertible<_From, _To>>;
381
382 /**
383 * @brief Primary class template for std::function.
384 * @ingroup functors
385 *
386 * Polymorphic function wrapper.
387 */
388 template<typename _Res, typename... _ArgTypes>
389 class function<_Res(_ArgTypes...)>
390 : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
391 private _Function_base
392 {
393 template<typename _Func,
394 typename _Res2 = typename result_of<_Func&(_ArgTypes...)>::type>
395 struct _Callable : __check_func_return_type<_Res2, _Res> { };
396
397 // Used so the return type convertibility checks aren't done when
398 // performing overload resolution for copy construction/assignment.
399 template<typename _Tp>
400 struct _Callable<function, _Tp> : false_type { };
401
402 template<typename _Cond, typename _Tp>
403 using _Requires = typename enable_if<_Cond::value, _Tp>::type;
404
405 public:
406 typedef _Res result_type;
407
408 // [3.7.2.1] construct/copy/destroy
409
410 /**
411 * @brief Default construct creates an empty function call wrapper.
412 * @post @c !(bool)*this
413 */
414 function() noexcept
415 : _Function_base() { }
416
417 /**
418 * @brief Creates an empty function call wrapper.
419 * @post @c !(bool)*this
420 */
421 function(nullptr_t) noexcept
422 : _Function_base() { }
423
424 /**
425 * @brief %Function copy constructor.
426 * @param __x A %function object with identical call signature.
427 * @post @c bool(*this) == bool(__x)
428 *
429 * The newly-created %function contains a copy of the target of @a
430 * __x (if it has one).
431 */
432 function(const function& __x);
433
434 /**
435 * @brief %Function move constructor.
436 * @param __x A %function object rvalue with identical call signature.
437 *
438 * The newly-created %function contains the target of @a __x
439 * (if it has one).
440 */
441 function(function&& __x) noexcept : _Function_base()
442 {
443 __x.swap(*this);
444 }
445
446 /**
447 * @brief Builds a %function that targets a copy of the incoming
448 * function object.
449 * @param __f A %function object that is callable with parameters of
450 * type @c T1, @c T2, ..., @c TN and returns a value convertible
451 * to @c Res.
452 *
453 * The newly-created %function object will target a copy of
454 * @a __f. If @a __f is @c reference_wrapper<F>, then this function
455 * object will contain a reference to the function object @c
456 * __f.get(). If @a __f is a NULL function pointer or NULL
457 * pointer-to-member, the newly-created object will be empty.
458 *
459 * If @a __f is a non-NULL function pointer or an object of type @c
460 * reference_wrapper<F>, this function will not throw.
461 */
462 template<typename _Functor,
463 typename = _Requires<__not_<is_same<_Functor, function>>, void>,
464 typename = _Requires<_Callable<_Functor>, void>>
465 function(_Functor);
466
467 /**
468 * @brief %Function assignment operator.
469 * @param __x A %function with identical call signature.
470 * @post @c (bool)*this == (bool)x
471 * @returns @c *this
472 *
473 * The target of @a __x is copied to @c *this. If @a __x has no
474 * target, then @c *this will be empty.
475 *
476 * If @a __x targets a function pointer or a reference to a function
477 * object, then this operation will not throw an %exception.
478 */
479 function&
480 operator=(const function& __x)
481 {
482 function(__x).swap(*this);
483 return *this;
484 }
485
486 /**
487 * @brief %Function move-assignment operator.
488 * @param __x A %function rvalue with identical call signature.
489 * @returns @c *this
490 *
491 * The target of @a __x is moved to @c *this. If @a __x has no
492 * target, then @c *this will be empty.
493 *
494 * If @a __x targets a function pointer or a reference to a function
495 * object, then this operation will not throw an %exception.
496 */
497 function&
498 operator=(function&& __x) noexcept
499 {
500 function(std::move(__x)).swap(*this);
501 return *this;
502 }
503
504 /**
505 * @brief %Function assignment to zero.
506 * @post @c !(bool)*this
507 * @returns @c *this
508 *
509 * The target of @c *this is deallocated, leaving it empty.
510 */
511 function&
512 operator=(nullptr_t) noexcept
513 {
514 if (_M_manager)
515 {
516 _M_manager(_M_functor, _M_functor, __destroy_functor);
517 _M_manager = nullptr;
518 _M_invoker = nullptr;
519 }
520 return *this;
521 }
522
523 /**
524 * @brief %Function assignment to a new target.
525 * @param __f A %function object that is callable with parameters of
526 * type @c T1, @c T2, ..., @c TN and returns a value convertible
527 * to @c Res.
528 * @return @c *this
529 *
530 * This %function object wrapper will target a copy of @a
531 * __f. If @a __f is @c reference_wrapper<F>, then this function
532 * object will contain a reference to the function object @c
533 * __f.get(). If @a __f is a NULL function pointer or NULL
534 * pointer-to-member, @c this object will be empty.
535 *
536 * If @a __f is a non-NULL function pointer or an object of type @c
537 * reference_wrapper<F>, this function will not throw.
538 */
539 template<typename _Functor>
540 _Requires<_Callable<typename decay<_Functor>::type>, function&>
541 operator=(_Functor&& __f)
542 {
543 function(std::forward<_Functor>(__f)).swap(*this);
544 return *this;
545 }
546
547 /// @overload
548 template<typename _Functor>
549 function&
550 operator=(reference_wrapper<_Functor> __f) noexcept
551 {
552 function(__f).swap(*this);
553 return *this;
554 }
555
556 // [3.7.2.2] function modifiers
557
558 /**
559 * @brief Swap the targets of two %function objects.
560 * @param __x A %function with identical call signature.
561 *
562 * Swap the targets of @c this function object and @a __f. This
563 * function will not throw an %exception.
564 */
565 void swap(function& __x) noexcept
566 {
567 std::swap(_M_functor, __x._M_functor);
568 std::swap(_M_manager, __x._M_manager);
569 std::swap(_M_invoker, __x._M_invoker);
570 }
571
572 // [3.7.2.3] function capacity
573
574 /**
575 * @brief Determine if the %function wrapper has a target.
576 *
577 * @return @c true when this %function object contains a target,
578 * or @c false when it is empty.
579 *
580 * This function will not throw an %exception.
581 */
582 explicit operator bool() const noexcept
583 { return !_M_empty(); }
584
585 // [3.7.2.4] function invocation
586
587 /**
588 * @brief Invokes the function targeted by @c *this.
589 * @returns the result of the target.
590 * @throws bad_function_call when @c !(bool)*this
591 *
592 * The function call operator invokes the target function object
593 * stored by @c this.
594 */
595 _Res operator()(_ArgTypes... __args) const;
596
597#if __cpp_rtti199711
598 // [3.7.2.5] function target access
599 /**
600 * @brief Determine the type of the target of this function object
601 * wrapper.
602 *
603 * @returns the type identifier of the target function object, or
604 * @c typeid(void) if @c !(bool)*this.
605 *
606 * This function will not throw an %exception.
607 */
608 const type_info& target_type() const noexcept;
609
610 /**
611 * @brief Access the stored target function object.
612 *
613 * @return Returns a pointer to the stored target function object,
614 * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL
615 * pointer.
616 *
617 * This function does not throw exceptions.
618 *
619 * @{
620 */
621 template<typename _Functor> _Functor* target() noexcept;
622
623 template<typename _Functor> const _Functor* target() const noexcept;
624 // @}
625#endif
626
627 private:
628 using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
629 _Invoker_type _M_invoker;
630 };
631
632#if __cpp_deduction_guides >= 201606
633 template<typename>
634 struct __function_guide_helper
635 { };
636
637 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
638 struct __function_guide_helper<
639 _Res (_Tp::*) (_Args...) noexcept(_Nx)
640 >
641 { using type = _Res(_Args...); };
642
643 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
644 struct __function_guide_helper<
645 _Res (_Tp::*) (_Args...) & noexcept(_Nx)
646 >
647 { using type = _Res(_Args...); };
648
649 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
650 struct __function_guide_helper<
651 _Res (_Tp::*) (_Args...) const noexcept(_Nx)
652 >
653 { using type = _Res(_Args...); };
654
655 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
656 struct __function_guide_helper<
657 _Res (_Tp::*) (_Args...) const & noexcept(_Nx)
658 >
659 { using type = _Res(_Args...); };
660
661 template<typename _Res, typename... _ArgTypes>
662 function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>;
663
664 template<typename _Functor, typename _Signature = typename
665 __function_guide_helper<decltype(&_Functor::operator())>::type>
666 function(_Functor) -> function<_Signature>;
667#endif
668
669 // Out-of-line member definitions.
670 template<typename _Res, typename... _ArgTypes>
671 function<_Res(_ArgTypes...)>::
672 function(const function& __x)
673 : _Function_base()
674 {
675 if (static_cast<bool>(__x))
676 {
677 __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
678 _M_invoker = __x._M_invoker;
679 _M_manager = __x._M_manager;
680 }
681 }
682
683 template<typename _Res, typename... _ArgTypes>
684 template<typename _Functor, typename, typename>
685 function<_Res(_ArgTypes...)>::
686 function(_Functor __f)
687 : _Function_base()
688 {
689 typedef _Function_handler<_Res(_ArgTypes...), _Functor> _My_handler;
690
691 if (_My_handler::_M_not_empty_function(__f))
8
Taking true branch
692 {
693 _My_handler::_M_init_functor(_M_functor, std::move(__f));
9
Calling '_Base_manager::_M_init_functor'
13
Returned allocated memory
694 _M_invoker = &_My_handler::_M_invoke;
695 _M_manager = &_My_handler::_M_manager;
696 }
697 }
698
699 template<typename _Res, typename... _ArgTypes>
700 _Res
701 function<_Res(_ArgTypes...)>::
702 operator()(_ArgTypes... __args) const
703 {
704 if (_M_empty())
705 __throw_bad_function_call();
706 return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
707 }
708
709#if __cpp_rtti199711
710 template<typename _Res, typename... _ArgTypes>
711 const type_info&
712 function<_Res(_ArgTypes...)>::
713 target_type() const noexcept
714 {
715 if (_M_manager)
716 {
717 _Any_data __typeinfo_result;
718 _M_manager(__typeinfo_result, _M_functor, __get_type_info);
719 return *__typeinfo_result._M_access<const type_info*>();
720 }
721 else
722 return typeid(void);
723 }
724
725 template<typename _Res, typename... _ArgTypes>
726 template<typename _Functor>
727 _Functor*
728 function<_Res(_ArgTypes...)>::
729 target() noexcept
730 {
731 const function* __const_this = this;
732 const _Functor* __func = __const_this->template target<_Functor>();
733 return const_cast<_Functor*>(__func);
734 }
735
736 template<typename _Res, typename... _ArgTypes>
737 template<typename _Functor>
738 const _Functor*
739 function<_Res(_ArgTypes...)>::
740 target() const noexcept
741 {
742 if (typeid(_Functor) == target_type() && _M_manager)
743 {
744 _Any_data __ptr;
745 _M_manager(__ptr, _M_functor, __get_functor_ptr);
746 return __ptr._M_access<const _Functor*>();
747 }
748 else
749 return nullptr;
750 }
751#endif
752
753 // [20.7.15.2.6] null pointer comparisons
754
755 /**
756 * @brief Compares a polymorphic function object wrapper against 0
757 * (the NULL pointer).
758 * @returns @c true if the wrapper has no target, @c false otherwise
759 *
760 * This function will not throw an %exception.
761 */
762 template<typename _Res, typename... _Args>
763 inline bool
764 operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
765 { return !static_cast<bool>(__f); }
766
767 /// @overload
768 template<typename _Res, typename... _Args>
769 inline bool
770 operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
771 { return !static_cast<bool>(__f); }
772
773 /**
774 * @brief Compares a polymorphic function object wrapper against 0
775 * (the NULL pointer).
776 * @returns @c false if the wrapper has no target, @c true otherwise
777 *
778 * This function will not throw an %exception.
779 */
780 template<typename _Res, typename... _Args>
781 inline bool
782 operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
783 { return static_cast<bool>(__f); }
784
785 /// @overload
786 template<typename _Res, typename... _Args>
787 inline bool
788 operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
789 { return static_cast<bool>(__f); }
790
791
792 // [20.7.15.2.7] specialized algorithms
793
794 /**
795 * @brief Swap the targets of two polymorphic function object wrappers.
796 *
797 * This function will not throw an %exception.
798 */
799 // _GLIBCXX_RESOLVE_LIB_DEFECTS
800 // 2062. Effect contradictions w/o no-throw guarantee of std::function swaps
801 template<typename _Res, typename... _Args>
802 inline void
803 swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept
804 { __x.swap(__y); }
805
806_GLIBCXX_END_NAMESPACE_VERSION
807} // namespace std
808
809#endif // C++11
810
811#endif // _GLIBCXX_STD_FUNCTION_H