================
@@ -1200,6 +1202,74 @@ static bool IsRecordFullyDefined(const CXXRecordDecl *RD,
return Complete;
}
+static void DiagnoseInvalidFlagEnumOperators(Sema &S, const EnumDecl *ED) {
+ assert(ED->hasAttr<FlagEnumAttr>() && "not a flag-like enum");
+ if (!ED->isScoped())
+ return;
+
+ QualType T = S.Context.getCanonicalTagType(ED);
+
+ auto LHS = OpaqueValueExpr(SourceLocation(), T, VK_PRValue);
+ auto RHS = OpaqueValueExpr(SourceLocation(), T, VK_PRValue);
+
+ OverloadedOperatorKind OPs[] = {OO_Pipe, OO_Amp, OO_Caret, OO_Tilde};
+ for (const auto OP : OPs) {
+ auto Name = S.Context.DeclarationNames.getCXXOperatorName(OP);
+ LookupResult R(S, Name, SourceLocation(), Sema::LookupOperatorName);
+
+ S.LookupName(R, S.TUScope);
+
+ OverloadCandidateSet CandidateSet{SourceLocation(),
+ OverloadCandidateSet::CSK_Operator};
+
+ SmallVector<Expr *, 2> Args;
+ if (OP == OO_Tilde) {
+ Args = {&LHS};
+ S.LookupOverloadedUnaryOp(CandidateSet, OP, R.asUnresolvedSet(), Args);
+ } else {
+ Args = {&LHS, &RHS};
+ S.LookupOverloadedBinOp(CandidateSet, OP, R.asUnresolvedSet(), Args);
+ }
+
+ OverloadCandidateSet::iterator Best;
+ OverloadingResult Result =
+ CandidateSet.BestViableFunction(S, SourceLocation(), Best);
+
+ switch (Result) {
+ case OR_Success:
+ break;
+ case OR_No_Viable_Function: {
+ S.Diag(ED->getLocation(), diag::warn_flag_enum_operator)
+ << ED->getName() << Name.getAsString() << OR_No_Viable_Function
----------------
zwuis wrote:
How about
```suggestion
<< ED << Name << OR_No_Viable_Function
```
https://github.com/llvm/llvm-project/pull/218290
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits