@@ -129,51 +129,120 @@ findFirstParentInfo(
129
129
}
130
130
}
131
131
132
+ template <bool isInner>
132
133
bool
133
- isDecayedEqual (
134
+ isDecayedEqualImpl (
134
135
Polymorphic<TypeInfo> const & lhs,
135
136
Polymorphic<TypeInfo> const & rhs)
136
137
{
137
- // When comparing two parameters, we need to compare
138
- // them as if they are decayed at the top level
139
- // the same way function parameters are decayed to
140
- // consider if they redefine an overload.
141
- if (lhs == rhs)
138
+ // Polymorphic
139
+ MRDOCS_CHECK_OR (static_cast <bool >(lhs) == static_cast <bool >(rhs), false );
140
+ MRDOCS_CHECK_OR (static_cast <bool >(lhs) && static_cast <bool >(rhs), true );
141
+ // TypeInfo
142
+ bool const decayToPointer = !isInner && (lhs->isArray () || rhs->isArray ());
143
+ if (!decayToPointer)
144
+ {
145
+ MRDOCS_CHECK_OR (lhs->Kind == rhs->Kind , false );
146
+ }
147
+ else
142
148
{
143
- return true ;
149
+ // in root types, arrays are decayed to pointers
150
+ MRDOCS_CHECK_OR (lhs->isArray () || lhs->isPointer (), false );
151
+ MRDOCS_CHECK_OR (rhs->isArray () || rhs->isPointer (), false );
144
152
}
145
-
146
- // const and volatile are ignored at the top level
147
- auto lhsDecay = lhs;
148
- lhsDecay->IsConst = false ;
149
- lhsDecay->IsVolatile = false ;
150
- auto rhsDecay = rhs;
151
- rhsDecay->IsConst = false ;
152
- rhsDecay->IsVolatile = false ;
153
-
154
- // Arrays decay to pointer
155
- if (lhsDecay->isArray ())
153
+ MRDOCS_CHECK_OR (lhs->IsPackExpansion == rhs->IsPackExpansion , false );
154
+ if constexpr (isInner)
155
+ {
156
+ // const and volative are ignored from root types
157
+ // in function parameters
158
+ MRDOCS_CHECK_OR (lhs->IsConst == rhs->IsConst , false );
159
+ MRDOCS_CHECK_OR (lhs->IsVolatile == rhs->IsVolatile , false );
160
+ }
161
+ MRDOCS_CHECK_OR (lhs->Constraints == rhs->Constraints , false );
162
+ switch (lhs->Kind )
163
+ {
164
+ // Types that never decay are compared directly
165
+ case TypeKind::Named:
166
+ {
167
+ // Compare only the fields of NameInfo, without
168
+ // TypeInfo, to avoid evaluating TypeInfo::IsConst
169
+ return dynamic_cast <NamedTypeInfo const &>(*lhs).Name ==
170
+ dynamic_cast <NamedTypeInfo const &>(*rhs).Name ;
171
+ }
172
+ case TypeKind::Decltype:
173
+ {
174
+ return dynamic_cast <DecltypeTypeInfo const &>(*lhs).Operand ==
175
+ dynamic_cast <DecltypeTypeInfo const &>(*rhs).Operand ;
176
+ }
177
+ case TypeKind::Auto:
178
+ {
179
+ auto const & lhsAuto = dynamic_cast <AutoTypeInfo const &>(*lhs);
180
+ auto const & rhsAuto = dynamic_cast <AutoTypeInfo const &>(*rhs);
181
+ return lhsAuto.Keyword == rhsAuto.Keyword &&
182
+ lhsAuto.Constraint == rhsAuto.Constraint ;
183
+ }
184
+ case TypeKind::LValueReference:
156
185
{
157
- auto & lhsAsArray = dynamic_cast <ArrayTypeInfo&>(*lhsDecay);
158
- PointerTypeInfo lhsAsPtr;
159
- lhsAsPtr.PointeeType = std::move (lhsAsArray.ElementType );
160
- // Copy all fields from base type
161
- dynamic_cast <TypeInfo&>(lhsAsPtr) = dynamic_cast <TypeInfo&>(lhsAsArray);
162
- lhsAsPtr.Kind = TypeKind::Pointer;
163
- lhsDecay = std::move (lhsAsPtr);
186
+ return
187
+ isDecayedEqualImpl<true >(
188
+ dynamic_cast <LValueReferenceTypeInfo const &>(*lhs).PointeeType ,
189
+ dynamic_cast <LValueReferenceTypeInfo const &>(*rhs).PointeeType );
164
190
}
165
- if (rhsDecay-> isArray ())
191
+ case TypeKind::RValueReference:
166
192
{
167
- auto & rhsAsArray = dynamic_cast <ArrayTypeInfo&>(*rhsDecay);
168
- PointerTypeInfo rhsAsPtr;
169
- rhsAsPtr.PointeeType = std::move (rhsAsArray.ElementType );
170
- // Copy all fields from base type
171
- dynamic_cast <TypeInfo&>(rhsAsPtr) = dynamic_cast <TypeInfo&>(rhsAsArray);
172
- rhsAsPtr.Kind = TypeKind::Pointer;
173
- rhsDecay = std::move (rhsAsPtr);
193
+ return
194
+ isDecayedEqualImpl<true >(
195
+ dynamic_cast <RValueReferenceTypeInfo const &>(*lhs).PointeeType ,
196
+ dynamic_cast <RValueReferenceTypeInfo const &>(*rhs).PointeeType );
174
197
}
198
+ case TypeKind::MemberPointer:
199
+ {
200
+ auto const & lhsMP = dynamic_cast <MemberPointerTypeInfo const &>(*lhs);
201
+ auto const & rhsMP = dynamic_cast <MemberPointerTypeInfo const &>(*rhs);
202
+ return
203
+ isDecayedEqualImpl<true >(lhsMP.PointeeType , rhsMP.PointeeType ) &&
204
+ isDecayedEqualImpl<true >(lhsMP.ParentType , rhsMP.ParentType );
205
+ }
206
+ case TypeKind::Function:
207
+ {
208
+ auto const & lhsF = dynamic_cast <FunctionTypeInfo const &>(*lhs);
209
+ auto const & rhsF = dynamic_cast <FunctionTypeInfo const &>(*rhs);
210
+ MRDOCS_CHECK_OR (lhsF.RefQualifier == rhsF.RefQualifier , false );
211
+ MRDOCS_CHECK_OR (lhsF.ExceptionSpec == rhsF.ExceptionSpec , false );
212
+ MRDOCS_CHECK_OR (lhsF.IsVariadic == rhsF.IsVariadic , false );
213
+ MRDOCS_CHECK_OR (isDecayedEqualImpl<true >(lhsF.ReturnType , rhsF.ReturnType ), false );
214
+ MRDOCS_CHECK_OR (lhsF.ParamTypes .size () == rhsF.ParamTypes .size (), false );
215
+ for (std::size_t i = 0 ; i < lhsF.ParamTypes .size (); ++i)
216
+ {
217
+ MRDOCS_CHECK_OR (isDecayedEqualImpl<false >(lhsF.ParamTypes [i], rhsF.ParamTypes [i]), false );
218
+ }
219
+ return true ;
220
+ }
221
+ // Types that should decay
222
+ case TypeKind::Pointer:
223
+ case TypeKind::Array:
224
+ {
225
+ auto const I1 = innerType (*lhs);
226
+ auto const I2 = innerType (*rhs);
227
+ MRDOCS_CHECK_OR (static_cast <bool >(I1) == static_cast <bool >(I2), false );
228
+ MRDOCS_CHECK_OR (static_cast <bool >(I1) && static_cast <bool >(I2), true );
229
+ return isDecayedEqualImpl<true >(I1->get (), I2->get ());
230
+ }
231
+ default :
232
+ MRDOCS_UNREACHABLE ();
233
+ }
234
+ return true ;
235
+ }
175
236
176
- return lhsDecay == rhsDecay;
237
+ /* Compare two types for equality for the purposes of
238
+ overload resolution.
239
+ */
240
+ bool
241
+ isDecayedEqual (
242
+ Polymorphic<TypeInfo> const & lhs,
243
+ Polymorphic<TypeInfo> const & rhs)
244
+ {
245
+ return isDecayedEqualImpl<false >(lhs, rhs);
177
246
}
178
247
}
179
248
0 commit comments