Skip to content

Commit eb31970

Browse files
authored
Add bit-precise overloads for builtin operators (#84755)
We previously were not adding them to the candidate set and so use of a bit-precise integer as a class member could lead to ambiguous overload sets. Fixes #82998
1 parent a7ef83f commit eb31970

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ Bug Fixes in This Version
265265
operator.
266266
Fixes (#GH83267).
267267

268+
- Clang now correctly generates overloads for bit-precise integer types for
269+
builtin operators in C++. Fixes #GH82998.
270+
268271
Bug Fixes to Compiler Builtins
269272
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
270273

clang/lib/Sema/SemaOverload.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8516,6 +8516,9 @@ class BuiltinCandidateTypeSet {
85168516
/// candidates.
85178517
TypeSet MatrixTypes;
85188518

8519+
/// The set of _BitInt types that will be used in the built-in candidates.
8520+
TypeSet BitIntTypes;
8521+
85198522
/// A flag indicating non-record types are viable candidates
85208523
bool HasNonRecordTypes;
85218524

@@ -8564,6 +8567,7 @@ class BuiltinCandidateTypeSet {
85648567
}
85658568
llvm::iterator_range<iterator> vector_types() { return VectorTypes; }
85668569
llvm::iterator_range<iterator> matrix_types() { return MatrixTypes; }
8570+
llvm::iterator_range<iterator> bitint_types() { return BitIntTypes; }
85678571

85688572
bool containsMatrixType(QualType Ty) const { return MatrixTypes.count(Ty); }
85698573
bool hasNonRecordTypes() { return HasNonRecordTypes; }
@@ -8735,6 +8739,9 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
87358739
} else if (Ty->isEnumeralType()) {
87368740
HasArithmeticOrEnumeralTypes = true;
87378741
EnumerationTypes.insert(Ty);
8742+
} else if (Ty->isBitIntType()) {
8743+
HasArithmeticOrEnumeralTypes = true;
8744+
BitIntTypes.insert(Ty);
87388745
} else if (Ty->isVectorType()) {
87398746
// We treat vector types as arithmetic types in many contexts as an
87408747
// extension.
@@ -8913,7 +8920,7 @@ class BuiltinOperatorOverloadBuilder {
89138920
SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
89148921
OverloadCandidateSet &CandidateSet;
89158922

8916-
static constexpr int ArithmeticTypesCap = 24;
8923+
static constexpr int ArithmeticTypesCap = 26;
89178924
SmallVector<CanQualType, ArithmeticTypesCap> ArithmeticTypes;
89188925

89198926
// Define some indices used to iterate over the arithmetic types in
@@ -8955,6 +8962,20 @@ class BuiltinOperatorOverloadBuilder {
89558962
(S.Context.getAuxTargetInfo() &&
89568963
S.Context.getAuxTargetInfo()->hasInt128Type()))
89578964
ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty);
8965+
8966+
/// We add candidates for the unique, unqualified _BitInt types present in
8967+
/// the candidate type set. The candidate set already handled ensuring the
8968+
/// type is unqualified and canonical, but because we're adding from N
8969+
/// different sets, we need to do some extra work to unique things. Insert
8970+
/// the candidates into a unique set, then move from that set into the list
8971+
/// of arithmetic types.
8972+
llvm::SmallSetVector<CanQualType, 2> BitIntCandidates;
8973+
llvm::for_each(CandidateTypes, [&BitIntCandidates](
8974+
BuiltinCandidateTypeSet &Candidate) {
8975+
for (QualType BitTy : Candidate.bitint_types())
8976+
BitIntCandidates.insert(CanQualType::CreateUnsafe(BitTy));
8977+
});
8978+
llvm::move(BitIntCandidates, std::back_inserter(ArithmeticTypes));
89588979
LastPromotedIntegralType = ArithmeticTypes.size();
89598980
LastPromotedArithmeticType = ArithmeticTypes.size();
89608981
// End of promoted types.
@@ -8975,7 +8996,11 @@ class BuiltinOperatorOverloadBuilder {
89758996
// End of integral types.
89768997
// FIXME: What about complex? What about half?
89778998

8978-
assert(ArithmeticTypes.size() <= ArithmeticTypesCap &&
8999+
// We don't know for sure how many bit-precise candidates were involved, so
9000+
// we subtract those from the total when testing whether we're under the
9001+
// cap or not.
9002+
assert(ArithmeticTypes.size() - BitIntCandidates.size() <=
9003+
ArithmeticTypesCap &&
89799004
"Enough inline storage for all arithmetic types.");
89809005
}
89819006

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %clang_cc1 -std=c++20 %s -verify
2+
// expected-no-diagnostics
3+
4+
#include "Inputs/std-compare.h"
5+
6+
struct S {
7+
_BitInt(12) a;
8+
9+
constexpr operator _BitInt(12)() const { return a; }
10+
};
11+
12+
// None of these used to compile because we weren't adding _BitInt types to the
13+
// overload set for builtin operators. See GH82998.
14+
static_assert(S{10} < 11);
15+
static_assert(S{10} <= 11);
16+
static_assert(S{12} > 11);
17+
static_assert(S{12} >= 11);
18+
static_assert(S{10} == 10);
19+
static_assert((S{10} <=> 10) == 0);
20+
static_assert(S{10} != 11);
21+
static_assert(S{10} + 0 == 10);
22+
static_assert(S{10} - 0 == 10);
23+
static_assert(S{10} * 1 == 10);
24+
static_assert(S{10} / 1 == 10);
25+
static_assert(S{10} % 1 == 0);
26+
static_assert(S{10} << 0 == 10);
27+
static_assert(S{10} >> 0 == 10);
28+
static_assert((S{10} | 0) == 10);
29+
static_assert((S{10} & 10) == 10);
30+
static_assert((S{10} ^ 0) == 10);
31+
static_assert(-S{10} == -10);
32+
static_assert(+S{10} == +10);
33+
static_assert(~S{10} == ~10);
34+
35+
struct A {
36+
_BitInt(12) a;
37+
38+
bool operator==(const A&) const = default;
39+
bool operator!=(const A&) const = default;
40+
std::strong_ordering operator<=>(const A&) const = default;
41+
};
42+

0 commit comments

Comments
 (0)