@@ -809,14 +809,14 @@ void SimplifyBooleanExprCheck::replaceWithAssignment(const ASTContext &Context,
809809 Range, Replacement);
810810}
811811
812- // / Swaps a \c BinaryOperator opcode from `&&` to `||` or vice-versa.
812+ // / Swaps \p BO from `&&` to `||` or vice-versa.
813813static bool flipDemorganOperator (llvm::SmallVectorImpl<FixItHint> &Output,
814- const BinaryOperator *BO ) {
815- assert (BO-> isLogicalOp ());
816- if (BO-> getOperatorLoc () .isMacroID ())
814+ BinaryOperatorKind BO, SourceLocation BOLoc ) {
815+ assert (BinaryOperator:: isLogicalOp (BO ));
816+ if (BOLoc .isMacroID ())
817817 return true ;
818- Output.push_back (FixItHint::CreateReplacement (
819- BO-> getOperatorLoc () , BO-> getOpcode () == BO_LAnd ? " ||" : " &&" ));
818+ Output.push_back (
819+ FixItHint::CreateReplacement (BOLoc , BO == BO_LAnd ? " ||" : " &&" ));
820820 return false ;
821821}
822822
@@ -829,22 +829,24 @@ static bool flipDemorganSide(SmallVectorImpl<FixItHint> &Fixes,
829829 const ASTContext &Ctx, const Expr *E,
830830 std::optional<BinaryOperatorKind> OuterBO);
831831
832- // / Inverts \p BinOp, Removing \p Parens if they exist and are safe to remove.
833- // / returns \c true if there is any issue building the Fixes, \c false
834- // / otherwise.
832+ // / Inverts \p BO, \p LHS, and \p RHS, Removing \p Parens if they exist and are
833+ // / safe to remove. returns \c true if there is any issue building the Fixes, \c
834+ // / false otherwise.
835835static bool
836836flipDemorganBinaryOperator (SmallVectorImpl<FixItHint> &Fixes,
837- const ASTContext &Ctx, const BinaryOperator *BinOp,
837+ const ASTContext &Ctx, BinaryOperatorKind BO,
838+ const Expr *LHS, const Expr *RHS,
839+ SourceRange ExprRange, SourceLocation BOLoc,
838840 std::optional<BinaryOperatorKind> OuterBO,
839841 const ParenExpr *Parens = nullptr ) {
840- switch (BinOp-> getOpcode () ) {
842+ switch (BO ) {
841843 case BO_LAnd:
842844 case BO_LOr: {
843845 // if we have 'a && b' or 'a || b', use demorgan to flip it to '!a || !b'
844846 // or '!a && !b'.
845- if (flipDemorganOperator (Fixes, BinOp ))
847+ if (flipDemorganOperator (Fixes, BO, BOLoc ))
846848 return true ;
847- auto NewOp = getDemorganFlippedOperator (BinOp-> getOpcode () );
849+ auto NewOp = getDemorganFlippedOperator (BO );
848850 if (OuterBO) {
849851 // The inner parens are technically needed in a fix for
850852 // `!(!A1 && !(A2 || A3)) -> (A1 || (A2 && A3))`,
@@ -862,16 +864,16 @@ flipDemorganBinaryOperator(SmallVectorImpl<FixItHint> &Fixes,
862864 }
863865 }
864866 if (*OuterBO == BO_LAnd && NewOp == BO_LOr && !Parens) {
865- Fixes.push_back (FixItHint::CreateInsertion (BinOp-> getBeginLoc (), " (" ));
867+ Fixes.push_back (FixItHint::CreateInsertion (ExprRange. getBegin (), " (" ));
866868 Fixes.push_back (FixItHint::CreateInsertion (
867- Lexer::getLocForEndOfToken (BinOp-> getEndLoc (), 0 ,
869+ Lexer::getLocForEndOfToken (ExprRange. getEnd (), 0 ,
868870 Ctx.getSourceManager (),
869871 Ctx.getLangOpts ()),
870872 " )" ));
871873 }
872874 }
873- if (flipDemorganSide (Fixes, Ctx, BinOp-> getLHS () , NewOp) ||
874- flipDemorganSide (Fixes, Ctx, BinOp-> getRHS () , NewOp))
875+ if (flipDemorganSide (Fixes, Ctx, LHS , NewOp) ||
876+ flipDemorganSide (Fixes, Ctx, RHS , NewOp))
875877 return true ;
876878 return false ;
877879 };
@@ -882,12 +884,11 @@ flipDemorganBinaryOperator(SmallVectorImpl<FixItHint> &Fixes,
882884 case BO_EQ:
883885 case BO_NE:
884886 // For comparison operators, just negate the comparison.
885- if (BinOp-> getOperatorLoc () .isMacroID ())
887+ if (BOLoc .isMacroID ())
886888 return true ;
887889 Fixes.push_back (FixItHint::CreateReplacement (
888- BinOp->getOperatorLoc (),
889- BinaryOperator::getOpcodeStr (
890- BinaryOperator::negateComparisonOp (BinOp->getOpcode ()))));
890+ BOLoc,
891+ BinaryOperator::getOpcodeStr (BinaryOperator::negateComparisonOp (BO))));
891892 return false ;
892893 default :
893894 // for any other binary operator, just use logical not and wrap in
@@ -897,11 +898,11 @@ flipDemorganBinaryOperator(SmallVectorImpl<FixItHint> &Fixes,
897898 return true ;
898899 Fixes.push_back (FixItHint::CreateInsertion (Parens->getBeginLoc (), " !" ));
899900 } else {
900- if (BinOp-> getBeginLoc ().isMacroID () || BinOp-> getEndLoc ().isMacroID ())
901+ if (ExprRange. getBegin ().isMacroID () || ExprRange. getEnd ().isMacroID ())
901902 return true ;
902- Fixes.append ({FixItHint::CreateInsertion (BinOp-> getBeginLoc (), " !(" ),
903+ Fixes.append ({FixItHint::CreateInsertion (ExprRange. getBegin (), " !(" ),
903904 FixItHint::CreateInsertion (
904- Lexer::getLocForEndOfToken (BinOp-> getEndLoc (), 0 ,
905+ Lexer::getLocForEndOfToken (ExprRange. getEnd (), 0 ,
905906 Ctx.getSourceManager (),
906907 Ctx.getLangOpts ()),
907908 " )" )});
@@ -911,6 +912,28 @@ flipDemorganBinaryOperator(SmallVectorImpl<FixItHint> &Fixes,
911912 return false ;
912913}
913914
915+ static bool
916+ flipDemorganBinaryOperator (SmallVectorImpl<FixItHint> &Fixes,
917+ const ASTContext &Ctx, const BinaryOperator *BinOp,
918+ std::optional<BinaryOperatorKind> OuterBO,
919+ const ParenExpr *Parens = nullptr ) {
920+ return flipDemorganBinaryOperator (
921+ Fixes, Ctx, BinOp->getOpcode (), BinOp->getLHS (), BinOp->getRHS (),
922+ BinOp->getSourceRange (), BinOp->getOperatorLoc (), OuterBO, Parens);
923+ }
924+
925+ static bool
926+ flipDemorganOverloadedBinaryOperator (SmallVectorImpl<FixItHint> &Fixes,
927+ const ASTContext &Ctx,
928+ const CXXOperatorCallExpr *OpCall,
929+ std::optional<BinaryOperatorKind> OuterBO,
930+ const ParenExpr *Parens = nullptr ) {
931+ auto BO = BinaryOperator::getOverloadedOpcode (OpCall->getOperator ());
932+ return flipDemorganBinaryOperator (Fixes, Ctx, BO, OpCall->getArg (0 ),
933+ OpCall->getArg (1 ), OpCall->getSourceRange (),
934+ OpCall->getOperatorLoc (), OuterBO, Parens);
935+ }
936+
914937static bool flipDemorganSide (SmallVectorImpl<FixItHint> &Fixes,
915938 const ASTContext &Ctx, const Expr *E,
916939 std::optional<BinaryOperatorKind> OuterBO) {
@@ -930,6 +953,17 @@ static bool flipDemorganSide(SmallVectorImpl<FixItHint> &Fixes,
930953 return flipDemorganBinaryOperator (Fixes, Ctx, BinOp, OuterBO, Paren);
931954 }
932955 }
956+ if (const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(E);
957+ OpCall && OpCall->isInfixBinaryOp ()) {
958+ return flipDemorganOverloadedBinaryOperator (Fixes, Ctx, OpCall, OuterBO);
959+ }
960+ if (const auto *Paren = dyn_cast<ParenExpr>(E)) {
961+ if (const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(Paren->getSubExpr ());
962+ OpCall && OpCall->isInfixBinaryOp ()) {
963+ return flipDemorganOverloadedBinaryOperator (Fixes, Ctx, OpCall, OuterBO,
964+ Paren);
965+ }
966+ }
933967 // Fallback case just insert a logical not operator.
934968 if (E->getBeginLoc ().isMacroID ())
935969 return true ;
@@ -991,7 +1025,7 @@ bool SimplifyBooleanExprCheck::reportDeMorgan(const ASTContext &Context,
9911025 } else {
9921026 Fixes.push_back (FixItHint::CreateRemoval (Outer->getOperatorLoc ()));
9931027 }
994- if (flipDemorganOperator (Fixes, Inner))
1028+ if (flipDemorganOperator (Fixes, Inner-> getOpcode (), Inner-> getOperatorLoc () ))
9951029 return false ;
9961030 if (flipDemorganSide (Fixes, Context, Inner->getLHS (), NewOpcode) ||
9971031 flipDemorganSide (Fixes, Context, Inner->getRHS (), NewOpcode))
0 commit comments