mizvekov created this revision.
Herald added subscribers: manas, steakhal, ASDenysPetrov, dkrupp, donat.nagy,
Szelethus, a.sidorin, baloghadamsoftware.
mizvekov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
This implements a more comprehensive fix than was done at D95409
<https://reviews.llvm.org/D95409>.
Instead of excluding just function pointer subobjects, we also
exclude any user-defined function pointer conversion operators.
Signed-off-by: Matheus Izvekov <[email protected]>
Depends on D103850 <https://reviews.llvm.org/D103850>
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D103855
Files:
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaOverload.cpp
clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
Index: clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
+++ clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
@@ -197,8 +197,7 @@
operator fp() const;
};
struct b3 {
- auto operator<=>(b3 const &) const = default; // expected-error {{cannot be deduced because three-way comparison for member 'f' would compare as builtin type 'void (*)()' which is not currently supported}}
- // expected-warning@-1 {{implicitly deleted}}
- a3 f;
+ auto operator<=>(b3 const &) const = default; // expected-warning {{implicitly deleted}}
+ a3 f; // expected-note {{because there is no viable three-way comparison function for member 'f'}}
};
}
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -7834,10 +7834,10 @@
SemaRef(SemaRef),
Context(SemaRef.Context) { }
- void AddTypesConvertedFrom(QualType Ty,
- SourceLocation Loc,
+ void AddTypesConvertedFrom(QualType Ty, SourceLocation Loc,
bool AllowUserConversions,
bool AllowExplicitConversions,
+ bool DisallowNonRelationalComparableTypes,
const Qualifiers &VisibleTypeConversionsQuals);
llvm::iterator_range<iterator> pointer_types() { return PointerTypes; }
@@ -7974,15 +7974,14 @@
/// primarily interested in pointer types and enumeration types. We also
/// take member pointer types, for the conditional operator.
/// AllowUserConversions is true if we should look at the conversion
-/// functions of a class type, and AllowExplicitConversions if we
+/// functions of a class type, AllowExplicitConversions if we
/// should also include the explicit conversion functions of a class
-/// type.
-void
-BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
- SourceLocation Loc,
- bool AllowUserConversions,
- bool AllowExplicitConversions,
- const Qualifiers &VisibleQuals) {
+/// type, and DisallowNonRelationalComparableTypes if we should exclude types
+/// which cannot be compared with relational operators.
+void BuiltinCandidateTypeSet::AddTypesConvertedFrom(
+ QualType Ty, SourceLocation Loc, bool AllowUserConversions,
+ bool AllowExplicitConversions, bool DisallowNonRelationalComparableTypes,
+ const Qualifiers &VisibleQuals) {
// Only deal with canonical types.
Ty = Context.getCanonicalType(Ty);
@@ -8009,6 +8008,10 @@
if (Ty->isObjCIdType() || Ty->isObjCClassType())
PointerTypes.insert(Ty);
else if (Ty->getAs<PointerType>() || Ty->getAs<ObjCObjectPointerType>()) {
+ // The builtin operator for relational comparisons on function pointers
+ // is the only known case which cannot be used for three-way comparisons.
+ if (DisallowNonRelationalComparableTypes && Ty->isFunctionPointerType())
+ return;
// Insert our type, and its more-qualified variants, into the set
// of types.
if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals))
@@ -8050,6 +8053,7 @@
CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
if (AllowExplicitConversions || !Conv->isExplicit()) {
AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false,
+ DisallowNonRelationalComparableTypes,
VisibleQuals);
}
}
@@ -9132,13 +9136,10 @@
SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
CandidateTypes.emplace_back(*this);
- CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(),
- OpLoc,
- true,
- (Op == OO_Exclaim ||
- Op == OO_AmpAmp ||
- Op == OO_PipePipe),
- VisibleTypeConversionsQuals);
+ CandidateTypes[ArgIdx].AddTypesConvertedFrom(
+ Args[ArgIdx]->getType(), OpLoc, true,
+ (Op == OO_Exclaim || Op == OO_AmpAmp || Op == OO_PipePipe),
+ (Op == OO_Less || Op == OO_Spaceship), VisibleTypeConversionsQuals);
HasNonRecordCandidateType = HasNonRecordCandidateType ||
CandidateTypes[ArgIdx].hasNonRecordTypes();
HasArithmeticOrEnumeralCandidateType =
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -7747,16 +7747,11 @@
if (Args[0]->getType()->isOverloadableType())
S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args);
- else if (OO == OO_EqualEqual ||
- !Args[0]->getType()->isFunctionPointerType()) {
+ else
// FIXME: We determine whether this is a valid expression by checking to
// see if there's a viable builtin operator candidate for it. That isn't
// really what the rules ask us to do, but should give the right results.
- //
- // Note that the builtin operator for relational comparisons on function
- // pointers is the only known case which cannot be used.
S.AddBuiltinOperatorCandidates(OO, FD->getLocation(), Args, CandidateSet);
- }
Result R;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits