@@ -8200,6 +8200,49 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
82008200 return VRQuals;
82018201}
82028202
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+
82038246namespace {
82048247
82058248/// Helper class to manage the addition of builtin operator overload
@@ -8210,7 +8253,7 @@ class BuiltinOperatorOverloadBuilder {
82108253 // Common instance state available to all overload candidate addition methods.
82118254 Sema &S;
82128255 ArrayRef<Expr *> Args;
8213- Qualifiers VisibleTypeConversionsQuals;
8256+ QualifiersAndAtomic VisibleTypeConversionsQuals;
82148257 bool HasArithmeticOrEnumeralCandidateType;
82158258 SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
82168259 OverloadCandidateSet &CandidateSet;
@@ -8334,7 +8377,7 @@ class BuiltinOperatorOverloadBuilder {
83348377public:
83358378 BuiltinOperatorOverloadBuilder(
83368379 Sema &S, ArrayRef<Expr *> Args,
8337- Qualifiers VisibleTypeConversionsQuals,
8380+ QualifiersAndAtomic VisibleTypeConversionsQuals,
83388381 bool HasArithmeticOrEnumeralCandidateType,
83398382 SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes,
83408383 OverloadCandidateSet &CandidateSet)
@@ -8955,18 +8998,14 @@ class BuiltinOperatorOverloadBuilder {
89558998 ParamTypes[1] = ArithmeticTypes[Right];
89568999 auto LeftBaseTy = AdjustAddressSpaceForBuiltinOperandType(
89579000 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);
89629001
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+ });
89709009 }
89719010 }
89729011
@@ -9013,16 +9052,13 @@ class BuiltinOperatorOverloadBuilder {
90139052 ParamTypes[1] = ArithmeticTypes[Right];
90149053 auto LeftBaseTy = AdjustAddressSpaceForBuiltinOperandType(
90159054 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+ });
90269062 }
90279063 }
90289064 }
@@ -9186,10 +9222,13 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
91869222 // if the operator we're looking at has built-in operator candidates
91879223 // that make use of these types. Also record whether we encounter non-record
91889224 // candidate types or either arithmetic or enumeral candidate types.
9189- Qualifiers VisibleTypeConversionsQuals;
9225+ QualifiersAndAtomic VisibleTypeConversionsQuals;
91909226 VisibleTypeConversionsQuals.addConst();
9191- for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx)
9227+ for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
91929228 VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
9229+ if (Args[ArgIdx]->getType()->isAtomicType())
9230+ VisibleTypeConversionsQuals.addAtomic();
9231+ }
91939232
91949233 bool HasNonRecordCandidateType = false;
91959234 bool HasArithmeticOrEnumeralCandidateType = false;
0 commit comments