clang 20.0.0git
Marshallers.cpp
Go to the documentation of this file.
1//===--- Marshallers.cpp ----------------------------------------*- 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 "Marshallers.h"
10#include "llvm/ADT/ArrayRef.h"
11#include "llvm/ADT/StringRef.h"
12#include "llvm/Support/Regex.h"
13#include <optional>
14#include <string>
15
16static std::optional<std::string>
17getBestGuess(llvm::StringRef Search, llvm::ArrayRef<llvm::StringRef> Allowed,
18 llvm::StringRef DropPrefix = "", unsigned MaxEditDistance = 3) {
19 if (MaxEditDistance != ~0U)
20 ++MaxEditDistance;
21 llvm::StringRef Res;
22 for (const llvm::StringRef &Item : Allowed) {
23 if (Item.equals_insensitive(Search)) {
24 assert(Item != Search && "This should be handled earlier on.");
25 MaxEditDistance = 1;
26 Res = Item;
27 continue;
28 }
29 unsigned Distance = Item.edit_distance(Search);
30 if (Distance < MaxEditDistance) {
31 MaxEditDistance = Distance;
32 Res = Item;
33 }
34 }
35 if (!Res.empty())
36 return Res.str();
37 if (!DropPrefix.empty()) {
38 --MaxEditDistance; // Treat dropping the prefix as 1 edit
39 for (const llvm::StringRef &Item : Allowed) {
40 auto NoPrefix = Item;
41 if (!NoPrefix.consume_front(DropPrefix))
42 continue;
43 if (NoPrefix.equals_insensitive(Search)) {
44 if (NoPrefix == Search)
45 return Item.str();
46 MaxEditDistance = 1;
47 Res = Item;
48 continue;
49 }
50 unsigned Distance = NoPrefix.edit_distance(Search);
51 if (Distance < MaxEditDistance) {
52 MaxEditDistance = Distance;
53 Res = Item;
54 }
55 }
56 if (!Res.empty())
57 return Res.str();
58 }
59 return std::nullopt;
60}
61
62std::optional<std::string>
64 clang::attr::Kind>::getBestGuess(const VariantValue &Value) {
65 static constexpr llvm::StringRef Allowed[] = {
66#define ATTR(X) "attr::" #X,
67#include "clang/Basic/AttrList.inc"
68 };
69 if (Value.isString())
70 return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "attr::");
71 return std::nullopt;
72}
73
74std::optional<std::string>
76 clang::CastKind>::getBestGuess(const VariantValue &Value) {
77 static constexpr llvm::StringRef Allowed[] = {
78#define CAST_OPERATION(Name) "CK_" #Name,
79#include "clang/AST/OperationKinds.def"
80 };
81 if (Value.isString())
82 return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "CK_");
83 return std::nullopt;
84}
85
86std::optional<std::string>
88 clang::OpenMPClauseKind>::getBestGuess(const VariantValue &Value) {
89 static constexpr llvm::StringRef Allowed[] = {
90#define GEN_CLANG_CLAUSE_CLASS
91#define CLAUSE_CLASS(Enum, Str, Class) #Enum,
92#include "llvm/Frontend/OpenMP/OMP.inc"
93 };
94 if (Value.isString())
95 return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "OMPC_");
96 return std::nullopt;
97}
98
99std::optional<std::string>
102 static constexpr llvm::StringRef Allowed[] = {
103#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,
104#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name,
105#include "clang/Basic/TokenKinds.def"
106 };
107 if (Value.isString())
108 return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "UETT_");
109 return std::nullopt;
110}
111
112static constexpr std::pair<llvm::StringRef, llvm::Regex::RegexFlags>
114 {"NoFlags", llvm::Regex::RegexFlags::NoFlags},
115 {"IgnoreCase", llvm::Regex::RegexFlags::IgnoreCase},
116 {"Newline", llvm::Regex::RegexFlags::Newline},
117 {"BasicRegex", llvm::Regex::RegexFlags::BasicRegex},
118};
119
120static std::optional<llvm::Regex::RegexFlags>
121getRegexFlag(llvm::StringRef Flag) {
122 for (const auto &StringFlag : RegexMap) {
123 if (Flag == StringFlag.first)
124 return StringFlag.second;
125 }
126 return std::nullopt;
127}
128
129static std::optional<llvm::StringRef> getCloseRegexMatch(llvm::StringRef Flag) {
130 for (const auto &StringFlag : RegexMap) {
131 if (Flag.edit_distance(StringFlag.first) < 3)
132 return StringFlag.first;
133 }
134 return std::nullopt;
135}
136
137std::optional<llvm::Regex::RegexFlags>
139 llvm::Regex::RegexFlags>::getFlags(llvm::StringRef Flags) {
140 std::optional<llvm::Regex::RegexFlags> Flag;
141 SmallVector<StringRef, 4> Split;
142 Flags.split(Split, '|', -1, false);
143 for (StringRef OrFlag : Split) {
144 if (std::optional<llvm::Regex::RegexFlags> NextFlag =
145 getRegexFlag(OrFlag.trim()))
146 Flag = Flag.value_or(llvm::Regex::NoFlags) | *NextFlag;
147 else
148 return std::nullopt;
149 }
150 return Flag;
151}
152
153std::optional<std::string>
155 llvm::Regex::RegexFlags>::getBestGuess(const VariantValue &Value) {
156 if (!Value.isString())
157 return std::nullopt;
159 llvm::StringRef(Value.getString()).split(Split, '|', -1, false);
160 for (llvm::StringRef &Flag : Split) {
161 if (std::optional<llvm::StringRef> BestGuess =
162 getCloseRegexMatch(Flag.trim()))
163 Flag = *BestGuess;
164 else
165 return std::nullopt;
166 }
167 if (Split.empty())
168 return std::nullopt;
169 return llvm::join(Split, " | ");
170}
static std::optional< llvm::StringRef > getCloseRegexMatch(llvm::StringRef Flag)
static constexpr std::pair< llvm::StringRef, llvm::Regex::RegexFlags > RegexMap[]
static std::optional< llvm::Regex::RegexFlags > getRegexFlag(llvm::StringRef Flag)
static std::optional< std::string > getBestGuess(llvm::StringRef Search, llvm::ArrayRef< llvm::StringRef > Allowed, llvm::StringRef DropPrefix="", unsigned MaxEditDistance=3)
Definition: Marshallers.cpp:17
Functions templates and classes to wrap matcher construct functions.
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:27
UnaryExprOrTypeTrait
Names for the "expression or type" traits.
Definition: TypeTraits.h:51
CastKind
CastKind - The kind of operation required for a conversion.
Helper template class to just from argument type to the right is/get functions in VariantValue.
Definition: Marshallers.h:55