@@ -8200,6 +8200,49 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
8200
8200
return VRQuals;
8201
8201
}
8202
8202
8203
+ // Note: We're currently only handling qualifiers that are meaningful for the
8204
+ // LHS of compound assignment overloading.
8205
+ static void forAllQualifierCombinationsImpl(
8206
+ QualifiersAndAtomic Available, QualifiersAndAtomic Applied,
8207
+ llvm::function_ref<void(QualifiersAndAtomic)> Callback) {
8208
+ // _Atomic
8209
+ if (Available.hasAtomic()) {
8210
+ Available.removeAtomic();
8211
+ forAllQualifierCombinationsImpl(Available, Applied.withAtomic(), Callback);
8212
+ forAllQualifierCombinationsImpl(Available, Applied, Callback);
8213
+ return;
8214
+ }
8215
+
8216
+ // volatile
8217
+ if (Available.hasVolatile()) {
8218
+ Available.removeVolatile();
8219
+ assert(!Applied.hasVolatile());
8220
+ forAllQualifierCombinationsImpl(Available, Applied.withVolatile(),
8221
+ Callback);
8222
+ forAllQualifierCombinationsImpl(Available, Applied, Callback);
8223
+ return;
8224
+ }
8225
+
8226
+ Callback(Applied);
8227
+ }
8228
+
8229
+ static void forAllQualifierCombinations(
8230
+ QualifiersAndAtomic Quals,
8231
+ llvm::function_ref<void(QualifiersAndAtomic)> Callback) {
8232
+ return forAllQualifierCombinationsImpl(Quals, QualifiersAndAtomic(),
8233
+ Callback);
8234
+ }
8235
+
8236
+ static QualType makeQualifiedLValueReferenceType(QualType Base,
8237
+ QualifiersAndAtomic Quals,
8238
+ Sema &S) {
8239
+ if (Quals.hasAtomic())
8240
+ Base = S.Context.getAtomicType(Base);
8241
+ if (Quals.hasVolatile())
8242
+ Base = S.Context.getVolatileType(Base);
8243
+ return S.Context.getLValueReferenceType(Base);
8244
+ }
8245
+
8203
8246
namespace {
8204
8247
8205
8248
/// Helper class to manage the addition of builtin operator overload
@@ -8210,7 +8253,7 @@ class BuiltinOperatorOverloadBuilder {
8210
8253
// Common instance state available to all overload candidate addition methods.
8211
8254
Sema &S;
8212
8255
ArrayRef<Expr *> Args;
8213
- Qualifiers VisibleTypeConversionsQuals;
8256
+ QualifiersAndAtomic VisibleTypeConversionsQuals;
8214
8257
bool HasArithmeticOrEnumeralCandidateType;
8215
8258
SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
8216
8259
OverloadCandidateSet &CandidateSet;
@@ -8334,7 +8377,7 @@ class BuiltinOperatorOverloadBuilder {
8334
8377
public:
8335
8378
BuiltinOperatorOverloadBuilder(
8336
8379
Sema &S, ArrayRef<Expr *> Args,
8337
- Qualifiers VisibleTypeConversionsQuals,
8380
+ QualifiersAndAtomic VisibleTypeConversionsQuals,
8338
8381
bool HasArithmeticOrEnumeralCandidateType,
8339
8382
SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes,
8340
8383
OverloadCandidateSet &CandidateSet)
@@ -8955,18 +8998,14 @@ class BuiltinOperatorOverloadBuilder {
8955
8998
ParamTypes[1] = ArithmeticTypes[Right];
8956
8999
auto LeftBaseTy = AdjustAddressSpaceForBuiltinOperandType(
8957
9000
S, ArithmeticTypes[Left], Args[0]);
8958
- // Add this built-in operator as a candidate (VQ is empty).
8959
- ParamTypes[0] = S.Context.getLValueReferenceType(LeftBaseTy);
8960
- S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
8961
- /*IsAssignmentOperator=*/isEqualOp);
8962
9001
8963
- // Add this built-in operator as a candidate (VQ is 'volatile').
8964
- if ( VisibleTypeConversionsQuals.hasVolatile() ) {
8965
- ParamTypes[0] = S.Context.getVolatileType(LeftBaseTy);
8966
- ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0] );
8967
- S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
8968
- /*IsAssignmentOperator=*/isEqualOp);
8969
- }
9002
+ forAllQualifierCombinations(
9003
+ VisibleTypeConversionsQuals, [&](QualifiersAndAtomic Quals ) {
9004
+ ParamTypes[0] =
9005
+ makeQualifiedLValueReferenceType(LeftBaseTy, Quals, S );
9006
+ S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
9007
+ /*IsAssignmentOperator=*/isEqualOp);
9008
+ });
8970
9009
}
8971
9010
}
8972
9011
@@ -9013,16 +9052,13 @@ class BuiltinOperatorOverloadBuilder {
9013
9052
ParamTypes[1] = ArithmeticTypes[Right];
9014
9053
auto LeftBaseTy = AdjustAddressSpaceForBuiltinOperandType(
9015
9054
S, ArithmeticTypes[Left], Args[0]);
9016
- // Add this built-in operator as a candidate (VQ is empty).
9017
- ParamTypes[0] = S.Context.getLValueReferenceType(LeftBaseTy);
9018
- S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
9019
- if (VisibleTypeConversionsQuals.hasVolatile()) {
9020
- // Add this built-in operator as a candidate (VQ is 'volatile').
9021
- ParamTypes[0] = LeftBaseTy;
9022
- ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]);
9023
- ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
9024
- S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
9025
- }
9055
+
9056
+ forAllQualifierCombinations(
9057
+ VisibleTypeConversionsQuals, [&](QualifiersAndAtomic Quals) {
9058
+ ParamTypes[0] =
9059
+ makeQualifiedLValueReferenceType(LeftBaseTy, Quals, S);
9060
+ S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
9061
+ });
9026
9062
}
9027
9063
}
9028
9064
}
@@ -9186,10 +9222,13 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
9186
9222
// if the operator we're looking at has built-in operator candidates
9187
9223
// that make use of these types. Also record whether we encounter non-record
9188
9224
// candidate types or either arithmetic or enumeral candidate types.
9189
- Qualifiers VisibleTypeConversionsQuals;
9225
+ QualifiersAndAtomic VisibleTypeConversionsQuals;
9190
9226
VisibleTypeConversionsQuals.addConst();
9191
- for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx)
9227
+ for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
9192
9228
VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
9229
+ if (Args[ArgIdx]->getType()->isAtomicType())
9230
+ VisibleTypeConversionsQuals.addAtomic();
9231
+ }
9193
9232
9194
9233
bool HasNonRecordCandidateType = false;
9195
9234
bool HasArithmeticOrEnumeralCandidateType = false;
0 commit comments