Skip to content

Commit e8c5b5a

Browse files
committed
lazy decayed type comparison
#improvement
1 parent 502bf32 commit e8c5b5a

File tree

1 file changed

+103
-34
lines changed

1 file changed

+103
-34
lines changed

src/lib/Lib/CorpusImpl.cpp

Lines changed: 103 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -129,51 +129,120 @@ findFirstParentInfo(
129129
}
130130
}
131131

132+
template <bool isInner>
132133
bool
133-
isDecayedEqual(
134+
isDecayedEqualImpl(
134135
Polymorphic<TypeInfo> const& lhs,
135136
Polymorphic<TypeInfo> const& rhs)
136137
{
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
142148
{
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);
144152
}
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:
156185
{
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);
164190
}
165-
if (rhsDecay->isArray())
191+
case TypeKind::RValueReference:
166192
{
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);
174197
}
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+
}
175236

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);
177246
}
178247
}
179248

0 commit comments

Comments
 (0)