xref: /llvm-project/llvm/utils/TableGen/Common/Utils.cpp (revision 3ae71d154e5dfb5e5a5d27b3699b27ce2b55f44d)
1 //===- Utils.cpp - Common Utilities -----------------------------*- C++ -*-===//
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 #include "Utils.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/TableGen/Error.h"
12 #include "llvm/TableGen/Record.h"
13 #include <algorithm>
14 
15 using namespace llvm;
16 
17 namespace {
18 /// Sorting predicate to sort record pointers by their Name field, and break
19 /// ties using record ID (which corresponds to creation/parse order).
20 struct LessRecordFieldNameAndID {
21   bool operator()(const Record *Rec1, const Record *Rec2) const {
22     return std::tuple(Rec1->getValueAsString("Name"), Rec1->getID()) <
23            std::tuple(Rec2->getValueAsString("Name"), Rec2->getID());
24   }
25 };
26 } // End anonymous namespace
27 
28 /// Sort an array of Records on the "Name" field, and check for records with
29 /// duplicate "Name" field. If duplicates are found, report a fatal error.
30 void llvm::sortAndReportDuplicates(MutableArrayRef<const Record *> Records,
31                                    StringRef ObjectName) {
32   llvm::sort(Records, LessRecordFieldNameAndID());
33 
34   auto I = std::adjacent_find(Records.begin(), Records.end(),
35                               [](const Record *Rec1, const Record *Rec2) {
36                                 return Rec1->getValueAsString("Name") ==
37                                        Rec2->getValueAsString("Name");
38                               });
39   if (I == Records.end())
40     return;
41 
42   // Found a duplicate name.
43   const Record *First = *I;
44   const Record *Second = *(I + 1);
45   StringRef Name = First->getValueAsString("Name");
46   PrintError(Second, ObjectName + " `" + Name + "` is already defined.");
47   PrintFatalNote(First, "Previous definition here.");
48 }
49