1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/AST/ComparisonCategories.h" |
15 | #include "clang/AST/Decl.h" |
16 | #include "clang/AST/DeclCXX.h" |
17 | #include "clang/AST/Type.h" |
18 | #include "llvm/ADT/SmallVector.h" |
19 | |
20 | using namespace clang; |
21 | |
22 | bool ComparisonCategoryInfo::ValueInfo::hasValidIntValue() const { |
23 | (0) . __assert_fail ("VD && \"must have var decl\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ComparisonCategories.cpp", 23, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(VD && "must have var decl"); |
24 | if (!VD->checkInitIsICE()) |
25 | return false; |
26 | |
27 | |
28 | |
29 | auto *Record = VD->getType()->getAsCXXRecordDecl(); |
30 | if (std::distance(Record->field_begin(), Record->field_end()) != 1 || |
31 | !Record->field_begin()->getType()->isIntegralOrEnumerationType()) |
32 | return false; |
33 | |
34 | return true; |
35 | } |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | llvm::APSInt ComparisonCategoryInfo::ValueInfo::getIntValue() const { |
46 | (0) . __assert_fail ("hasValidIntValue() && \"must have a valid value\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ComparisonCategories.cpp", 46, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(hasValidIntValue() && "must have a valid value"); |
47 | return VD->evaluateValue()->getStructField(0).getInt(); |
48 | } |
49 | |
50 | ComparisonCategoryInfo::ValueInfo *ComparisonCategoryInfo::lookupValueInfo( |
51 | ComparisonCategoryResult ValueKind) const { |
52 | |
53 | auto It = llvm::find_if( |
54 | Objects, [&](ValueInfo const &Info) { return Info.Kind == ValueKind; }); |
55 | if (It != Objects.end()) |
56 | return &(*It); |
57 | |
58 | |
59 | |
60 | DeclContextLookupResult Lookup = Record->getCanonicalDecl()->lookup( |
61 | &Ctx.Idents.get(ComparisonCategories::getResultString(ValueKind))); |
62 | if (Lookup.size() != 1 || !isa<VarDecl>(Lookup.front())) |
63 | return nullptr; |
64 | Objects.emplace_back(ValueKind, cast<VarDecl>(Lookup.front())); |
65 | return &Objects.back(); |
66 | } |
67 | |
68 | static const NamespaceDecl *lookupStdNamespace(const ASTContext &Ctx, |
69 | NamespaceDecl *&StdNS) { |
70 | if (!StdNS) { |
71 | DeclContextLookupResult Lookup = |
72 | Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get("std")); |
73 | if (Lookup.size() == 1) |
74 | StdNS = dyn_cast<NamespaceDecl>(Lookup.front()); |
75 | } |
76 | return StdNS; |
77 | } |
78 | |
79 | static CXXRecordDecl *lookupCXXRecordDecl(const ASTContext &Ctx, |
80 | const NamespaceDecl *StdNS, |
81 | ComparisonCategoryType Kind) { |
82 | StringRef Name = ComparisonCategories::getCategoryString(Kind); |
83 | DeclContextLookupResult Lookup = StdNS->lookup(&Ctx.Idents.get(Name)); |
84 | if (Lookup.size() == 1) |
85 | if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Lookup.front())) |
86 | return RD; |
87 | return nullptr; |
88 | } |
89 | |
90 | const ComparisonCategoryInfo * |
91 | ComparisonCategories::lookupInfo(ComparisonCategoryType Kind) const { |
92 | auto It = Data.find(static_cast<char>(Kind)); |
93 | if (It != Data.end()) |
94 | return &It->second; |
95 | |
96 | if (const NamespaceDecl *NS = lookupStdNamespace(Ctx, StdNS)) |
97 | if (CXXRecordDecl *RD = lookupCXXRecordDecl(Ctx, NS, Kind)) |
98 | return &Data.try_emplace((char)Kind, Ctx, RD, Kind).first->second; |
99 | |
100 | return nullptr; |
101 | } |
102 | |
103 | const ComparisonCategoryInfo * |
104 | ComparisonCategories::lookupInfoForType(QualType Ty) const { |
105 | (0) . __assert_fail ("!Ty.isNull() && \"type must be non-null\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ComparisonCategories.cpp", 105, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Ty.isNull() && "type must be non-null"); |
106 | using CCT = ComparisonCategoryType; |
107 | auto *RD = Ty->getAsCXXRecordDecl(); |
108 | if (!RD) |
109 | return nullptr; |
110 | |
111 | |
112 | const auto *CanonRD = RD->getCanonicalDecl(); |
113 | for (auto &KV : Data) { |
114 | const ComparisonCategoryInfo &Info = KV.second; |
115 | if (CanonRD == Info.Record->getCanonicalDecl()) |
116 | return &Info; |
117 | } |
118 | |
119 | if (!RD->getEnclosingNamespaceContext()->isStdNamespace()) |
120 | return nullptr; |
121 | |
122 | |
123 | |
124 | for (unsigned I = static_cast<unsigned>(CCT::First), |
125 | End = static_cast<unsigned>(CCT::Last); |
126 | I <= End; ++I) { |
127 | CCT Kind = static_cast<CCT>(I); |
128 | |
129 | |
130 | |
131 | if (getCategoryString(Kind) == RD->getName()) |
132 | return &Data.try_emplace((char)Kind, Ctx, RD, Kind).first->second; |
133 | } |
134 | |
135 | |
136 | return nullptr; |
137 | } |
138 | |
139 | const ComparisonCategoryInfo &ComparisonCategories::getInfoForType(QualType Ty) const { |
140 | const ComparisonCategoryInfo *Info = lookupInfoForType(Ty); |
141 | (0) . __assert_fail ("Info && \"info for comparison category not found\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ComparisonCategories.cpp", 141, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Info && "info for comparison category not found"); |
142 | return *Info; |
143 | } |
144 | |
145 | QualType ComparisonCategoryInfo::getType() const { |
146 | assert(Record); |
147 | return QualType(Record->getTypeForDecl(), 0); |
148 | } |
149 | |
150 | StringRef ComparisonCategories::getCategoryString(ComparisonCategoryType Kind) { |
151 | using CCKT = ComparisonCategoryType; |
152 | switch (Kind) { |
153 | case CCKT::WeakEquality: |
154 | return "weak_equality"; |
155 | case CCKT::StrongEquality: |
156 | return "strong_equality"; |
157 | case CCKT::PartialOrdering: |
158 | return "partial_ordering"; |
159 | case CCKT::WeakOrdering: |
160 | return "weak_ordering"; |
161 | case CCKT::StrongOrdering: |
162 | return "strong_ordering"; |
163 | } |
164 | llvm_unreachable("unhandled cases in switch"); |
165 | } |
166 | |
167 | StringRef ComparisonCategories::getResultString(ComparisonCategoryResult Kind) { |
168 | using CCVT = ComparisonCategoryResult; |
169 | switch (Kind) { |
170 | case CCVT::Equal: |
171 | return "equal"; |
172 | case CCVT::Nonequal: |
173 | return "nonequal"; |
174 | case CCVT::Equivalent: |
175 | return "equivalent"; |
176 | case CCVT::Nonequivalent: |
177 | return "nonequivalent"; |
178 | case CCVT::Less: |
179 | return "less"; |
180 | case CCVT::Greater: |
181 | return "greater"; |
182 | case CCVT::Unordered: |
183 | return "unordered"; |
184 | } |
185 | llvm_unreachable("unhandled case in switch"); |
186 | } |
187 | |
188 | std::vector<ComparisonCategoryResult> |
189 | ComparisonCategories::getPossibleResultsForType(ComparisonCategoryType Type) { |
190 | using CCT = ComparisonCategoryType; |
191 | using CCR = ComparisonCategoryResult; |
192 | std::vector<CCR> Values; |
193 | Values.reserve(6); |
194 | Values.push_back(CCR::Equivalent); |
195 | bool IsStrong = (Type == CCT::StrongEquality || Type == CCT::StrongOrdering); |
196 | if (IsStrong) |
197 | Values.push_back(CCR::Equal); |
198 | if (Type == CCT::StrongOrdering || Type == CCT::WeakOrdering || |
199 | Type == CCT::PartialOrdering) { |
200 | Values.push_back(CCR::Less); |
201 | Values.push_back(CCR::Greater); |
202 | } else { |
203 | Values.push_back(CCR::Nonequivalent); |
204 | if (IsStrong) |
205 | Values.push_back(CCR::Nonequal); |
206 | } |
207 | if (Type == CCT::PartialOrdering) |
208 | Values.push_back(CCR::Unordered); |
209 | return Values; |
210 | } |
211 | |