update emoji autocorrect entries from po-files
[LibreOffice.git] / compilerplugins / clang / simplifybool.cxx
blob9f82660dd29f86864dc0affa46871215ad8efef4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "plugin.hxx"
12 namespace {
14 Expr const * ignoreParenImpCastAndComma(Expr const * expr) {
15 for (;;) {
16 expr = expr->IgnoreParenImpCasts();
17 auto e = dyn_cast<BinaryOperator>(expr);
18 if (e == nullptr || e->getOpcode() != BO_Comma) {
19 return expr;
21 expr = e->getRHS();
25 Expr const * getSubExprOfLogicalNegation(Expr const * expr) {
26 auto e = dyn_cast<UnaryOperator>(ignoreParenImpCastAndComma(expr));
27 return e == nullptr || e->getOpcode() != UO_LNot
28 ? nullptr : e->getSubExpr();
31 enum class Value { Unknown, False, True };
33 Value getValue(Expr const * expr) {
34 expr = ignoreParenImpCastAndComma(expr);
35 if (expr->getType()->isBooleanType()) {
36 // Instead going via Expr::isCXX11ConstantExpr would turn up excatly one
37 // additional place in svx/source/dialog/framelinkarray.cxx
39 // const bool DIAG_DBL_CLIP_DEFAULT = false;
40 // ...
41 // ... = mxImpl.get() ? mxImpl->mbDiagDblClip : DIAG_DBL_CLIP_DEFAULT;
43 // where it is unclear whether it is not actually better to consider
44 // DIAG_DBL_CLIP_DEFAULT a tunable parameter (and thus not to simplify):
45 auto lit = dyn_cast<CXXBoolLiteralExpr>(expr);
46 if (lit != nullptr) {
47 return lit->getValue() ? Value::True : Value::False;
50 return Value::Unknown;
53 class SimplifyBool:
54 public RecursiveASTVisitor<SimplifyBool>, public loplugin::Plugin
56 public:
57 explicit SimplifyBool(InstantiationData const & data): Plugin(data) {}
59 void run() override;
61 bool VisitUnaryLNot(UnaryOperator const * expr);
63 bool VisitBinLT(BinaryOperator const * expr);
65 bool VisitBinGT(BinaryOperator const * expr);
67 bool VisitBinLE(BinaryOperator const * expr);
69 bool VisitBinGE(BinaryOperator const * expr);
71 bool VisitBinEQ(BinaryOperator const * expr);
73 bool VisitBinNE(BinaryOperator const * expr);
75 bool VisitConditionalOperator(ConditionalOperator const * expr);
78 void SimplifyBool::run() {
79 if (compiler.getLangOpts().CPlusPlus) {
80 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
84 bool SimplifyBool::VisitUnaryLNot(UnaryOperator const * expr) {
85 if (ignoreLocation(expr)) {
86 return true;
88 auto e = getSubExprOfLogicalNegation(expr->getSubExpr());
89 if (e == nullptr) {
90 return true;
92 /* hits for OSL_ENSURE(!b, ...);
93 report(
94 DiagnosticsEngine::Warning,
95 ("double logical negation expression of the form '!!A' (with A of type"
96 " %0) can %select{logically|literally}1 be simplified as 'A'"),
97 expr->getLocStart())
98 << e->IgnoreImpCasts()->getType()
99 << e->IgnoreImpCasts()->getType()->isBooleanType()
100 << expr->getSourceRange();
102 return true;
105 bool SimplifyBool::VisitBinLT(BinaryOperator const * expr) {
106 if (ignoreLocation(expr)) {
107 return true;
109 if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
110 && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()))
112 return true;
114 auto v1 = getValue(expr->getLHS());
115 auto v2 = getValue(expr->getRHS());
116 switch (v1) {
117 case Value::Unknown:
118 switch (v2) {
119 case Value::Unknown:
120 break;
121 case Value::False:
122 report(
123 DiagnosticsEngine::Warning,
124 ("less-than expression of the form 'A < false' (with A of type"
125 " %0) can logically be simplified as 'false'"),
126 expr->getLocStart())
127 << expr->getLHS()->IgnoreImpCasts()->getType()
128 << expr->getSourceRange();
129 break;
130 case Value::True:
132 auto e = getSubExprOfLogicalNegation(expr->getLHS());
133 if (e == nullptr) {
134 report(
135 DiagnosticsEngine::Warning,
136 ("less-than expression of the form 'A < true' (with A"
137 " of type %0) can %select{logically|literally}1 be"
138 " simplified as '!A'"),
139 expr->getLocStart())
140 << expr->getLHS()->IgnoreImpCasts()->getType()
141 << (expr->getLHS()->IgnoreImpCasts()->getType()
142 ->isBooleanType())
143 << expr->getSourceRange();
144 } else {
145 report(
146 DiagnosticsEngine::Warning,
147 ("less-than expression of the form '!A < true' (with A"
148 " of type %0) can %select{logically|literally}1 be"
149 " simplified as 'A'"),
150 expr->getLocStart())
151 << e->IgnoreImpCasts()->getType()
152 << e->IgnoreImpCasts()->getType()->isBooleanType()
153 << expr->getSourceRange();
155 break;
158 break;
159 case Value::False:
160 switch (v2) {
161 case Value::Unknown:
162 report(
163 DiagnosticsEngine::Warning,
164 ("less-than expression of the form 'false < A' (with A of type"
165 " %0) can %select{logically|literally}1 be simplified as 'A'"),
166 expr->getLocStart())
167 << expr->getRHS()->IgnoreImpCasts()->getType()
168 << expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()
169 << expr->getSourceRange();
170 break;
171 case Value::False:
172 report(
173 DiagnosticsEngine::Warning,
174 ("less-than expression of the form 'false < false' can"
175 " literally be simplified as 'false'"),
176 expr->getLocStart())
177 << expr->getSourceRange();
178 break;
179 case Value::True:
180 report(
181 DiagnosticsEngine::Warning,
182 ("less-than expression of the form 'false < true' can"
183 " literally be simplified as 'true'"),
184 expr->getLocStart())
185 << expr->getSourceRange();
186 break;
188 break;
189 case Value::True:
190 switch (v2) {
191 case Value::Unknown:
192 report(
193 DiagnosticsEngine::Warning,
194 ("less-than expression of the form 'true < A' (with A of type"
195 " %0) can logically be simplified as 'false'"),
196 expr->getLocStart())
197 << expr->getRHS()->IgnoreImpCasts()->getType()
198 << expr->getSourceRange();
199 break;
200 case Value::False:
201 report(
202 DiagnosticsEngine::Warning,
203 ("less-than expression of the form 'true < false' can"
204 " literally be simplified as 'false'"),
205 expr->getLocStart())
206 << expr->getSourceRange();
207 break;
208 case Value::True:
209 report(
210 DiagnosticsEngine::Warning,
211 ("less-than expression of the form 'true < true' can"
212 " literally be simplified as 'false'"),
213 expr->getLocStart())
214 << expr->getSourceRange();
215 break;
217 break;
219 return true;
222 bool SimplifyBool::VisitBinGT(BinaryOperator const * expr) {
223 if (ignoreLocation(expr)) {
224 return true;
226 if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
227 && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()))
229 return true;
231 auto v1 = getValue(expr->getLHS());
232 auto v2 = getValue(expr->getRHS());
233 switch (v1) {
234 case Value::Unknown:
235 switch (v2) {
236 case Value::Unknown:
237 break;
238 case Value::False:
239 report(
240 DiagnosticsEngine::Warning,
241 ("greater-than expression of the form 'A > false' (with A of"
242 " type %0) can %select{logically|literally}1 be simplified as"
243 " 'A'"),
244 expr->getLocStart())
245 << expr->getLHS()->IgnoreImpCasts()->getType()
246 << expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
247 << expr->getSourceRange();
248 break;
249 case Value::True:
250 report(
251 DiagnosticsEngine::Warning,
252 ("greater-than expression of the form 'A > true' (with A of"
253 " type %0) can logically be simplified as 'false'"),
254 expr->getLocStart())
255 << expr->getLHS()->IgnoreImpCasts()->getType()
256 << expr->getSourceRange();
257 break;
259 break;
260 case Value::False:
261 switch (v2) {
262 case Value::Unknown:
263 report(
264 DiagnosticsEngine::Warning,
265 ("greater-than expression of the form 'false > A' (with A of"
266 " type %0) can logically be simplified as 'false'"),
267 expr->getLocStart())
268 << expr->getRHS()->IgnoreImpCasts()->getType()
269 << expr->getSourceRange();
270 break;
271 case Value::False:
272 report(
273 DiagnosticsEngine::Warning,
274 ("greater-than expression of the form 'false > false' can"
275 " literally be simplified as 'false'"),
276 expr->getLocStart())
277 << expr->getSourceRange();
278 break;
279 case Value::True:
280 report(
281 DiagnosticsEngine::Warning,
282 ("greater-than expression of the form 'false > true' can"
283 " literally be simplified as 'false'"),
284 expr->getLocStart())
285 << expr->getSourceRange();
286 break;
288 break;
289 case Value::True:
290 switch (v2) {
291 case Value::Unknown:
293 auto e = getSubExprOfLogicalNegation(expr->getRHS());
294 if (e == nullptr) {
295 report(
296 DiagnosticsEngine::Warning,
297 ("greater-than expression of the form 'true > A' (with"
298 " A of type %0) can %select{logically|literally}1 be"
299 " simplified as '!A'"),
300 expr->getLocStart())
301 << expr->getRHS()->IgnoreImpCasts()->getType()
302 << (expr->getRHS()->IgnoreImpCasts()->getType()
303 ->isBooleanType())
304 << expr->getSourceRange();
305 } else {
306 report(
307 DiagnosticsEngine::Warning,
308 ("greater-than expression of the form 'true > !A' (with"
309 " A of type %0) can %select{logically|literally}1 be"
310 " simplified as 'A'"),
311 expr->getLocStart())
312 << e->IgnoreImpCasts()->getType()
313 << e->IgnoreImpCasts()->getType()->isBooleanType()
314 << expr->getSourceRange();
316 break;
318 case Value::False:
319 report(
320 DiagnosticsEngine::Warning,
321 ("greater-than expression of the form 'true > false' can"
322 " literally be simplified as 'true'"),
323 expr->getLocStart())
324 << expr->getSourceRange();
325 break;
326 case Value::True:
327 report(
328 DiagnosticsEngine::Warning,
329 ("greater-than expression of the form 'true > true' can"
330 " literally be simplified as 'false'"),
331 expr->getLocStart())
332 << expr->getSourceRange();
333 break;
335 break;
337 return true;
340 bool SimplifyBool::VisitBinLE(BinaryOperator const * expr) {
341 if (ignoreLocation(expr)) {
342 return true;
344 if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
345 && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()))
347 return true;
349 auto v1 = getValue(expr->getLHS());
350 auto v2 = getValue(expr->getRHS());
351 switch (v1) {
352 case Value::Unknown:
353 switch (v2) {
354 case Value::Unknown:
355 break;
356 case Value::False:
358 auto e = getSubExprOfLogicalNegation(expr->getLHS());
359 if (e == nullptr) {
360 report(
361 DiagnosticsEngine::Warning,
362 ("less-than-or-equal-to expression of the form 'A <="
363 " false' (with A of type %0) can"
364 " %select{logically|literally}1 be simplified as"
365 " '!A'"),
366 expr->getLocStart())
367 << expr->getLHS()->IgnoreImpCasts()->getType()
368 << (expr->getLHS()->IgnoreImpCasts()->getType()
369 ->isBooleanType())
370 << expr->getSourceRange();
371 } else {
372 report(
373 DiagnosticsEngine::Warning,
374 ("less-than-or-equal-to expression of the form '!A <="
375 " false' (with A of type %0) can"
376 " %select{logically|literally}1 be simplified as 'A'"),
377 expr->getLocStart())
378 << e->IgnoreImpCasts()->getType()
379 << e->IgnoreImpCasts()->getType()->isBooleanType()
380 << expr->getSourceRange();
382 break;
384 case Value::True:
385 report(
386 DiagnosticsEngine::Warning,
387 ("less-than-or-equal-to expression of the form 'A <= true'"
388 " (with A of type %0) can logically be simplified as 'true'"),
389 expr->getLocStart())
390 << expr->getLHS()->IgnoreImpCasts()->getType()
391 << expr->getSourceRange();
392 break;
394 break;
395 case Value::False:
396 switch (v2) {
397 case Value::Unknown:
398 report(
399 DiagnosticsEngine::Warning,
400 ("less-than-or-equal-to expression of the form 'false <= A'"
401 " (with A of type %0) can logically be simplified as 'true'"),
402 expr->getLocStart())
403 << expr->getRHS()->IgnoreImpCasts()->getType()
404 << expr->getSourceRange();
405 break;
406 case Value::False:
407 report(
408 DiagnosticsEngine::Warning,
409 ("less-than-or-equal-to expression of the form 'false <= false'"
410 " can literally be simplified as 'true'"),
411 expr->getLocStart())
412 << expr->getSourceRange();
413 break;
414 case Value::True:
415 report(
416 DiagnosticsEngine::Warning,
417 ("less-than-or-equal-to expression of the form 'false <= true'"
418 " can literally be simplified as 'true'"),
419 expr->getLocStart())
420 << expr->getSourceRange();
421 break;
423 break;
424 case Value::True:
425 switch (v2) {
426 case Value::Unknown:
427 report(
428 DiagnosticsEngine::Warning,
429 ("less-than-or-equal-to expression of the form 'true <= A'"
430 " (with A of type %0) can %select{logically|literally}1 be"
431 " simplified as 'A'"),
432 expr->getLocStart())
433 << expr->getRHS()->IgnoreImpCasts()->getType()
434 << expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()
435 << expr->getSourceRange();
436 break;
437 case Value::False:
438 report(
439 DiagnosticsEngine::Warning,
440 ("less-than-or-equal-to expression of the form 'true <= false'"
441 " can literally be simplified as 'false'"),
442 expr->getLocStart())
443 << expr->getSourceRange();
444 break;
445 case Value::True:
446 report(
447 DiagnosticsEngine::Warning,
448 ("less-than-or-equal-to expression of the form 'true <= true'"
449 " can literally be simplified as 'true'"),
450 expr->getLocStart())
451 << expr->getSourceRange();
452 break;
454 break;
456 return true;
459 bool SimplifyBool::VisitBinGE(BinaryOperator const * expr) {
460 if (ignoreLocation(expr)) {
461 return true;
463 if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
464 && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()))
466 return true;
468 auto v1 = getValue(expr->getLHS());
469 auto v2 = getValue(expr->getRHS());
470 switch (v1) {
471 case Value::Unknown:
472 switch (v2) {
473 case Value::Unknown:
474 break;
475 case Value::False:
476 report(
477 DiagnosticsEngine::Warning,
478 ("greater-than-or-equal-to expression of the form 'A >= false'"
479 " (with A of type %0) can logically be simplified as 'true'"),
480 expr->getLocStart())
481 << expr->getLHS()->IgnoreImpCasts()->getType()
482 << expr->getSourceRange();
483 break;
484 case Value::True:
485 report(
486 DiagnosticsEngine::Warning,
487 ("greater-than-or-equal-to expression of the form 'A >= true'"
488 " (with A of type %0) can %select{logically|literally}1 be"
489 " simplified as 'A'"),
490 expr->getLocStart())
491 << expr->getLHS()->IgnoreImpCasts()->getType()
492 << expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
493 << expr->getSourceRange();
494 break;
496 break;
497 case Value::False:
498 switch (v2) {
499 case Value::Unknown:
501 auto e = getSubExprOfLogicalNegation(expr->getRHS());
502 if (e == nullptr) {
503 report(
504 DiagnosticsEngine::Warning,
505 ("greater-than-or-equal-to expression of the form"
506 " 'false >= A' (with A of type %0) can"
507 " %select{logically|literally}1 be simplified as"
508 " '!A'"),
509 expr->getLocStart())
510 << expr->getRHS()->IgnoreImpCasts()->getType()
511 << (expr->getRHS()->IgnoreImpCasts()->getType()
512 ->isBooleanType())
513 << expr->getSourceRange();
514 } else {
515 report(
516 DiagnosticsEngine::Warning,
517 ("greater-than-or-equal-to expression of the form"
518 " 'false >= !A' (with A of type %0) can"
519 " %select{logically|literally}1 be simplified as 'A'"),
520 expr->getLocStart())
521 << e->IgnoreImpCasts()->getType()
522 << e->IgnoreImpCasts()->getType()->isBooleanType()
523 << expr->getSourceRange();
525 break;
527 case Value::False:
528 report(
529 DiagnosticsEngine::Warning,
530 ("greater-than-or-equal-to expression of the form 'false >="
531 " false' can literally be simplified as 'true'"),
532 expr->getLocStart())
533 << expr->getSourceRange();
534 break;
535 case Value::True:
536 report(
537 DiagnosticsEngine::Warning,
538 ("greater-than-or-equal-to expression of the form 'false >="
539 " true' can literally be simplified as 'false'"),
540 expr->getLocStart())
541 << expr->getSourceRange();
542 break;
544 break;
545 case Value::True:
546 switch (v2) {
547 case Value::Unknown:
548 report(
549 DiagnosticsEngine::Warning,
550 ("greater-than-or-equal-to expression of the form 'true >= A'"
551 " (with A of type %0) can logically be simplified as 'true'"),
552 expr->getLocStart())
553 << expr->getRHS()->IgnoreImpCasts()->getType()
554 << expr->getSourceRange();
555 break;
556 case Value::False:
557 report(
558 DiagnosticsEngine::Warning,
559 ("greater-than-or-equal-to expression of the form 'true >="
560 " false' can literally be simplified as 'true'"),
561 expr->getLocStart())
562 << expr->getSourceRange();
563 break;
564 case Value::True:
565 report(
566 DiagnosticsEngine::Warning,
567 ("greater-than-or-equal-to expression of the form 'true >="
568 " true' can literally be simplified as 'true'"),
569 expr->getLocStart())
570 << expr->getSourceRange();
571 break;
573 break;
575 return true;
578 bool SimplifyBool::VisitBinEQ(BinaryOperator const * expr) {
579 if (ignoreLocation(expr)) {
580 return true;
582 if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
583 && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()))
585 return true;
587 auto v1 = getValue(expr->getLHS());
588 auto v2 = getValue(expr->getRHS());
589 switch (v1) {
590 case Value::Unknown:
591 switch (v2) {
592 case Value::Unknown:
593 break;
594 case Value::False:
596 auto e = getSubExprOfLogicalNegation(expr->getLHS());
597 if (e == nullptr) {
598 report(
599 DiagnosticsEngine::Warning,
600 ("equal-to expression of the form 'A == false' (with A"
601 " of type %0) can %select{logically|literally}1 be"
602 " simplified as '!A'"),
603 expr->getLocStart())
604 << expr->getLHS()->IgnoreImpCasts()->getType()
605 << (expr->getLHS()->IgnoreImpCasts()->getType()
606 ->isBooleanType())
607 << expr->getSourceRange();
608 } else {
609 report(
610 DiagnosticsEngine::Warning,
611 ("equal-to expression of the form '!A == false' (with A"
612 " of type %0) can %select{logically|literally}1 be"
613 " simplified as 'A'"),
614 expr->getLocStart())
615 << e->IgnoreImpCasts()->getType()
616 << e->IgnoreImpCasts()->getType()->isBooleanType()
617 << expr->getSourceRange();
619 break;
621 case Value::True:
622 report(
623 DiagnosticsEngine::Warning,
624 ("equal-to expression of the form 'A == true' (with A of type"
625 " %0) can %select{logically|literally}1 be simplified as 'A'"),
626 expr->getLocStart())
627 << expr->getLHS()->IgnoreImpCasts()->getType()
628 << expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
629 << expr->getSourceRange();
630 break;
632 break;
633 case Value::False:
634 switch (v2) {
635 case Value::Unknown:
637 auto e = getSubExprOfLogicalNegation(expr->getRHS());
638 if (e == nullptr) {
639 report(
640 DiagnosticsEngine::Warning,
641 ("equal-to expression of the form 'false == A' (with A"
642 " of type %0) can %select{logically|literally}1 be"
643 " simplified as '!A'"),
644 expr->getLocStart())
645 << expr->getRHS()->IgnoreImpCasts()->getType()
646 << (expr->getRHS()->IgnoreImpCasts()->getType()
647 ->isBooleanType())
648 << expr->getSourceRange();
649 } else {
650 report(
651 DiagnosticsEngine::Warning,
652 ("equal-to expression of the form 'false == !A' (with A"
653 " of type %0) can %select{logically|literally}1 be"
654 " simplified as 'A'"),
655 expr->getLocStart())
656 << e->IgnoreImpCasts()->getType()
657 << e->IgnoreImpCasts()->getType()->isBooleanType()
658 << expr->getSourceRange();
660 break;
662 case Value::False:
663 report(
664 DiagnosticsEngine::Warning,
665 ("equal-to expression of the form 'false == false' can"
666 " literally be simplified as 'true'"),
667 expr->getLocStart())
668 << expr->getSourceRange();
669 break;
670 case Value::True:
671 report(
672 DiagnosticsEngine::Warning,
673 ("equal-to expression of the form 'false == true' can"
674 " literally be simplified as 'false'"),
675 expr->getLocStart())
676 << expr->getSourceRange();
677 break;
679 break;
680 case Value::True:
681 switch (v2) {
682 case Value::Unknown:
683 report(
684 DiagnosticsEngine::Warning,
685 ("equal-to expression of the form 'true == A' (with A of type"
686 " %0) can %select{logically|literally}1 be simplified as 'A'"),
687 expr->getLocStart())
688 << expr->getRHS()->IgnoreImpCasts()->getType()
689 << expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()
690 << expr->getSourceRange();
691 break;
692 case Value::False:
693 report(
694 DiagnosticsEngine::Warning,
695 ("equal-to expression of the form 'true == false' can"
696 " literally be simplified as 'false'"),
697 expr->getLocStart())
698 << expr->getSourceRange();
699 break;
700 case Value::True:
701 report(
702 DiagnosticsEngine::Warning,
703 ("equal-to expression of the form 'true == true' can"
704 " literally be simplified as 'true'"),
705 expr->getLocStart())
706 << expr->getSourceRange();
707 break;
709 break;
711 return true;
714 bool SimplifyBool::VisitBinNE(BinaryOperator const * expr) {
715 if (ignoreLocation(expr)) {
716 return true;
718 if (!(expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
719 && expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()))
721 return true;
723 auto v1 = getValue(expr->getLHS());
724 auto v2 = getValue(expr->getRHS());
725 switch (v1) {
726 case Value::Unknown:
727 switch (v2) {
728 case Value::Unknown:
729 break;
730 case Value::False:
731 report(
732 DiagnosticsEngine::Warning,
733 ("not-equal-to expression of the form 'A != false' (with A of"
734 " type %0) can %select{logically|literally}1 be simplified as"
735 " 'A'"),
736 expr->getLocStart())
737 << expr->getLHS()->IgnoreImpCasts()->getType()
738 << expr->getLHS()->IgnoreImpCasts()->getType()->isBooleanType()
739 << expr->getSourceRange();
740 break;
741 case Value::True:
743 auto e = getSubExprOfLogicalNegation(expr->getLHS());
744 if (e == nullptr) {
745 report(
746 DiagnosticsEngine::Warning,
747 ("not-equal-to expression of the form 'A != true' (with"
748 " A of type %0) can %select{logically|literally}1 be"
749 " simplified as '!A'"),
750 expr->getLocStart())
751 << expr->getLHS()->IgnoreImpCasts()->getType()
752 << (expr->getLHS()->IgnoreImpCasts()->getType()
753 ->isBooleanType())
754 << expr->getSourceRange();
755 } else {
756 report(
757 DiagnosticsEngine::Warning,
758 ("not-equal-to expression of the form '!A != true'"
759 " (with A of type %0) can"
760 " %select{logically|literally}1 be simplified as 'A'"),
761 expr->getLocStart())
762 << e->IgnoreImpCasts()->getType()
763 << e->IgnoreImpCasts()->getType()->isBooleanType()
764 << expr->getSourceRange();
766 break;
769 break;
770 case Value::False:
771 switch (v2) {
772 case Value::Unknown:
773 report(
774 DiagnosticsEngine::Warning,
775 ("not-equal-to expression of the form 'false != A' (with A of"
776 " type %0) can %select{logically|literally}1 be simplified as"
777 " 'A'"),
778 expr->getLocStart())
779 << expr->getRHS()->IgnoreImpCasts()->getType()
780 << expr->getRHS()->IgnoreImpCasts()->getType()->isBooleanType()
781 << expr->getSourceRange();
782 break;
783 case Value::False:
784 report(
785 DiagnosticsEngine::Warning,
786 ("not-equal-to expression of the form 'false != false' can"
787 " literally be simplified as 'false'"),
788 expr->getLocStart())
789 << expr->getSourceRange();
790 break;
791 case Value::True:
792 report(
793 DiagnosticsEngine::Warning,
794 ("not-equal-to expression of the form 'false != true' can"
795 " literally be simplified as 'true'"),
796 expr->getLocStart())
797 << expr->getSourceRange();
798 break;
800 break;
801 case Value::True:
802 switch (v2) {
803 case Value::Unknown:
805 auto e = getSubExprOfLogicalNegation(expr->getRHS());
806 if (e == nullptr) {
807 report(
808 DiagnosticsEngine::Warning,
809 ("not-equal-to expression of the form 'true != A' (with"
810 " A of type %0) can %select{logically|literally}1 be"
811 " simplified as '!A'"),
812 expr->getLocStart())
813 << expr->getRHS()->IgnoreImpCasts()->getType()
814 << (expr->getRHS()->IgnoreImpCasts()->getType()
815 ->isBooleanType())
816 << expr->getSourceRange();
817 } else {
818 report(
819 DiagnosticsEngine::Warning,
820 ("not-equal-to expression of the form 'true != !A'"
821 " (with A of type %0) can"
822 " %select{logically|literally}1 be simplified as 'A'"),
823 expr->getLocStart())
824 << e->IgnoreImpCasts()->getType()
825 << e->IgnoreImpCasts()->getType()->isBooleanType()
826 << expr->getSourceRange();
828 break;
830 case Value::False:
831 report(
832 DiagnosticsEngine::Warning,
833 ("not-equal-to expression of the form 'true != false' can"
834 " literally be simplified as 'true'"),
835 expr->getLocStart())
836 << expr->getSourceRange();
837 break;
838 case Value::True:
839 report(
840 DiagnosticsEngine::Warning,
841 ("not-equal-to expression of the form 'true != true' can"
842 " literally be simplified as 'false'"),
843 expr->getLocStart())
844 << expr->getSourceRange();
845 break;
847 break;
849 return true;
852 bool SimplifyBool::VisitConditionalOperator(ConditionalOperator const * expr) {
853 if (ignoreLocation(expr)) {
854 return true;
856 auto v1 = getValue(expr->getTrueExpr());
857 auto v2 = getValue(expr->getFalseExpr());
858 switch (v1) {
859 case Value::Unknown:
860 switch (v2) {
861 case Value::Unknown:
862 break;
863 case Value::False:
864 report(
865 DiagnosticsEngine::Warning,
866 ("conditional expression of the form 'A ? B : false' (with A of"
867 " type %0 and B of type %1) can %select{logically|literally}2"
868 " be simplified as 'A && B'"),
869 expr->getLocStart())
870 << expr->getCond()->IgnoreImpCasts()->getType()
871 << expr->getTrueExpr()->IgnoreImpCasts()->getType()
872 << ((expr->getCond()->IgnoreImpCasts()->getType()
873 ->isBooleanType())
874 && (expr->getTrueExpr()->IgnoreImpCasts()->getType()
875 ->isBooleanType()))
876 << expr->getSourceRange();
877 break;
878 case Value::True:
880 auto e = getSubExprOfLogicalNegation(expr->getCond());
881 if (e == nullptr) {
882 report(
883 DiagnosticsEngine::Warning,
884 ("conditional expression of the form 'A ? B : true'"
885 " (with A of type %0 and B of type %1) can"
886 " %select{logically|literally}2 be simplified as '!A"
887 " || B'"),
888 expr->getLocStart())
889 << expr->getCond()->IgnoreImpCasts()->getType()
890 << expr->getTrueExpr()->IgnoreImpCasts()->getType()
891 << ((expr->getCond()->IgnoreImpCasts()->getType()
892 ->isBooleanType())
893 && (expr->getTrueExpr()->IgnoreImpCasts()->getType()
894 ->isBooleanType()))
895 << expr->getSourceRange();
896 } else {
897 report(
898 DiagnosticsEngine::Warning,
899 ("conditional expression of the form '!A ? B : true'"
900 " (with A of type %0 and B of type %1) can"
901 " %select{logically|literally}2 be simplified as 'A ||"
902 " B'"),
903 expr->getLocStart())
904 << e->IgnoreImpCasts()->getType()
905 << expr->getTrueExpr()->IgnoreImpCasts()->getType()
906 << (e->IgnoreImpCasts()->getType()->isBooleanType()
907 && (expr->getTrueExpr()->IgnoreImpCasts()
908 ->getType()->isBooleanType()))
909 << expr->getSourceRange();
911 break;
914 break;
915 case Value::False:
916 switch (v2) {
917 case Value::Unknown:
919 auto e = getSubExprOfLogicalNegation(expr->getCond());
920 if (e == nullptr) {
921 report(
922 DiagnosticsEngine::Warning,
923 ("conditional expression of the form 'A ? false : B'"
924 " (with A of type %0 and B of type %1) can"
925 " %select{logically|literally}2 be simplified as '!A"
926 " && B'"),
927 expr->getLocStart())
928 << expr->getCond()->IgnoreImpCasts()->getType()
929 << expr->getFalseExpr()->IgnoreImpCasts()->getType()
930 << ((expr->getCond()->IgnoreImpCasts()->getType()
931 ->isBooleanType())
932 && (expr->getFalseExpr()->IgnoreImpCasts()
933 ->getType()->isBooleanType()))
934 << expr->getSourceRange();
935 } else {
936 report(
937 DiagnosticsEngine::Warning,
938 ("conditional expression of the form '!A ? false : B'"
939 " (with A of type %0 and B of type %1) can"
940 " %select{logically|literally}2 be simplified as 'A &&"
941 " B'"),
942 expr->getLocStart())
943 << e->IgnoreImpCasts()->getType()
944 << expr->getFalseExpr()->IgnoreImpCasts()->getType()
945 << (e->IgnoreImpCasts()->getType()->isBooleanType()
946 && (expr->getFalseExpr()->IgnoreImpCasts()
947 ->getType()->isBooleanType()))
948 << expr->getSourceRange();
950 break;
952 case Value::False:
953 report(
954 DiagnosticsEngine::Warning,
955 ("conditional expression of the form 'A ? false : false' (with"
956 " A of type %0) can logically be simplified as 'false'"),
957 expr->getLocStart())
958 << expr->getCond()->IgnoreImpCasts()->getType()
959 << expr->getSourceRange();
960 break;
961 case Value::True:
963 auto e = getSubExprOfLogicalNegation(expr->getCond());
964 if (e == nullptr) {
965 report(
966 DiagnosticsEngine::Warning,
967 ("conditional expression of the form 'A ? false : true'"
968 " (with A of type %0) can"
969 " %select{logically|literally}1 be simplified as"
970 " '!A'"),
971 expr->getLocStart())
972 << expr->getCond()->IgnoreImpCasts()->getType()
973 << (expr->getCond()->IgnoreImpCasts()->getType()
974 ->isBooleanType())
975 << expr->getSourceRange();
976 } else {
977 report(
978 DiagnosticsEngine::Warning,
979 ("conditional expression of the form '!A ? false :"
980 " true' (with A of type %0) can"
981 " %select{logically|literally}1 be simplified as 'A'"),
982 expr->getLocStart())
983 << e->IgnoreImpCasts()->getType()
984 << e->IgnoreImpCasts()->getType()->isBooleanType()
985 << expr->getSourceRange();
987 break;
990 break;
991 case Value::True:
992 switch (v2) {
993 case Value::Unknown:
994 report(
995 DiagnosticsEngine::Warning,
996 ("conditional expression of the form 'A ? true : B' (with A of"
997 " type %0 and B of type %1) can %select{logically|literally}2"
998 " be simplified as 'A || B'"),
999 expr->getLocStart())
1000 << expr->getCond()->IgnoreImpCasts()->getType()
1001 << expr->getFalseExpr()->IgnoreImpCasts()->getType()
1002 << ((expr->getCond()->IgnoreImpCasts()->getType()
1003 ->isBooleanType())
1004 && (expr->getFalseExpr()->IgnoreImpCasts()->getType()
1005 ->isBooleanType()))
1006 << expr->getSourceRange();
1007 break;
1008 case Value::False:
1009 report(
1010 DiagnosticsEngine::Warning,
1011 ("conditional expression of the form 'A ? true : false' (with A"
1012 " of type %0) can %select{logically|literally}1 be simplified"
1013 " as 'A'"),
1014 expr->getLocStart())
1015 << expr->getCond()->IgnoreImpCasts()->getType()
1016 << expr->getCond()->IgnoreImpCasts()->getType()->isBooleanType()
1017 << expr->getSourceRange();
1018 break;
1019 case Value::True:
1020 report(
1021 DiagnosticsEngine::Warning,
1022 ("conditional expression of the form 'A ? true : true' (with A"
1023 " of type %0) can logically be simplified as 'true'"),
1024 expr->getLocStart())
1025 << expr->getCond()->IgnoreImpCasts()->getType()
1026 << expr->getSourceRange();
1027 break;
1029 break;
1031 return true;
1034 loplugin::Plugin::Registration<SimplifyBool> X("simplifybool");
1038 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */