================
@@ -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

Reply via email to