|
15 | 15 | #include "clang/AST/Expr.h"
|
16 | 16 | #include "clang/AST/ExprObjC.h"
|
17 | 17 | #include "clang/Analysis/CFGStmtMap.h"
|
| 18 | +#include "clang/Lex/Lexer.h" |
18 | 19 | #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
|
19 | 20 | #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
|
20 | 21 | #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
|
@@ -1372,14 +1373,57 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
|
1372 | 1373 | return Event;
|
1373 | 1374 | }
|
1374 | 1375 |
|
1375 |
| -bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out, |
| 1376 | +bool ConditionBRVisitor::patternMatch(const Expr *Ex, |
| 1377 | + const Expr *ParentEx, |
| 1378 | + raw_ostream &Out, |
1376 | 1379 | BugReporterContext &BRC,
|
1377 | 1380 | BugReport &report,
|
1378 | 1381 | const ExplodedNode *N,
|
1379 | 1382 | Optional<bool> &prunable) {
|
1380 | 1383 | const Expr *OriginalExpr = Ex;
|
1381 | 1384 | Ex = Ex->IgnoreParenCasts();
|
1382 | 1385 |
|
| 1386 | + // Use heuristics to determine if Ex is a macro expending to a literal and |
| 1387 | + // if so, use the macro's name. |
| 1388 | + SourceLocation LocStart = Ex->getLocStart(); |
| 1389 | + SourceLocation LocEnd = Ex->getLocEnd(); |
| 1390 | + if (LocStart.isMacroID() && LocEnd.isMacroID() && |
| 1391 | + (isa<GNUNullExpr>(Ex) || |
| 1392 | + isa<ObjCBoolLiteralExpr>(Ex) || |
| 1393 | + isa<CXXBoolLiteralExpr>(Ex) || |
| 1394 | + isa<IntegerLiteral>(Ex) || |
| 1395 | + isa<FloatingLiteral>(Ex))) { |
| 1396 | + |
| 1397 | + StringRef StartName = Lexer::getImmediateMacroNameForDiagnostics(LocStart, |
| 1398 | + BRC.getSourceManager(), BRC.getASTContext().getLangOpts()); |
| 1399 | + StringRef EndName = Lexer::getImmediateMacroNameForDiagnostics(LocEnd, |
| 1400 | + BRC.getSourceManager(), BRC.getASTContext().getLangOpts()); |
| 1401 | + bool beginAndEndAreTheSameMacro = StartName.equals(EndName); |
| 1402 | + |
| 1403 | + bool partOfParentMacro = false; |
| 1404 | + if (ParentEx->getLocStart().isMacroID()) { |
| 1405 | + StringRef PName = Lexer::getImmediateMacroNameForDiagnostics( |
| 1406 | + ParentEx->getLocStart(), BRC.getSourceManager(), |
| 1407 | + BRC.getASTContext().getLangOpts()); |
| 1408 | + partOfParentMacro = PName.equals(StartName); |
| 1409 | + } |
| 1410 | + |
| 1411 | + if (beginAndEndAreTheSameMacro && !partOfParentMacro ) { |
| 1412 | + // Get the location of the macro name as written by the caller. |
| 1413 | + SourceLocation Loc = LocStart; |
| 1414 | + while (LocStart.isMacroID()) { |
| 1415 | + Loc = LocStart; |
| 1416 | + LocStart = BRC.getSourceManager().getImmediateMacroCallerLoc(LocStart); |
| 1417 | + } |
| 1418 | + StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics( |
| 1419 | + Loc, BRC.getSourceManager(), BRC.getASTContext().getLangOpts()); |
| 1420 | + |
| 1421 | + // Return the macro name. |
| 1422 | + Out << MacroName; |
| 1423 | + return false; |
| 1424 | + } |
| 1425 | + } |
| 1426 | + |
1383 | 1427 | if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
|
1384 | 1428 | const bool quotes = isa<VarDecl>(DR->getDecl());
|
1385 | 1429 | if (quotes) {
|
@@ -1440,10 +1484,10 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
|
1440 | 1484 | SmallString<128> LhsString, RhsString;
|
1441 | 1485 | {
|
1442 | 1486 | llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
|
1443 |
| - const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N, |
1444 |
| - shouldPrune); |
1445 |
| - const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N, |
1446 |
| - shouldPrune); |
| 1487 | + const bool isVarLHS = patternMatch(BExpr->getLHS(), BExpr, OutLHS, |
| 1488 | + BRC, R, N, shouldPrune); |
| 1489 | + const bool isVarRHS = patternMatch(BExpr->getRHS(), BExpr, OutRHS, |
| 1490 | + BRC, R, N, shouldPrune); |
1447 | 1491 |
|
1448 | 1492 | shouldInvert = !isVarLHS && isVarRHS;
|
1449 | 1493 | }
|
|
0 commit comments