aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/BugReporterVisitors.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp96
1 files changed, 74 insertions, 22 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index cf1e0a6a656c..0e505463bb5e 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -14,6 +14,7 @@
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -323,6 +324,9 @@ public:
}
PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame);
+ if (!L.isValid() || !L.asLocation().isValid())
+ return nullptr;
+
return new PathDiagnosticEventPiece(L, Out.str());
}
@@ -828,8 +832,53 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
// Check if this is inlined defensive checks.
const LocationContext *CurLC =Succ->getLocationContext();
const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
- if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC))
+ if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) {
BR.markInvalid("Suppress IDC", CurLC);
+ return nullptr;
+ }
+
+ // Treat defensive checks in function-like macros as if they were an inlined
+ // defensive check. If the bug location is not in a macro and the
+ // terminator for the current location is in a macro then suppress the
+ // warning.
+ auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
+
+ if (!BugPoint)
+ return nullptr;
+
+ SourceLocation BugLoc = BugPoint->getStmt()->getLocStart();
+ if (BugLoc.isMacroID())
+ return nullptr;
+
+ ProgramPoint CurPoint = Succ->getLocation();
+ const Stmt *CurTerminatorStmt = nullptr;
+ if (auto BE = CurPoint.getAs<BlockEdge>()) {
+ CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
+ } else if (auto SP = CurPoint.getAs<StmtPoint>()) {
+ const Stmt *CurStmt = SP->getStmt();
+ if (!CurStmt->getLocStart().isMacroID())
+ return nullptr;
+
+ CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
+ CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminator();
+ } else {
+ return nullptr;
+ }
+
+ if (!CurTerminatorStmt)
+ return nullptr;
+
+ SourceLocation TerminatorLoc = CurTerminatorStmt->getLocStart();
+ if (TerminatorLoc.isMacroID()) {
+ const SourceManager &SMgr = BRC.getSourceManager();
+ std::pair<FileID, unsigned> TLInfo = SMgr.getDecomposedLoc(TerminatorLoc);
+ SrcMgr::SLocEntry SE = SMgr.getSLocEntry(TLInfo.first);
+ const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion();
+ if (EInfo.isFunctionMacroExpansion()) {
+ BR.markInvalid("Suppress Macro IDC", CurLC);
+ return nullptr;
+ }
+ }
}
return nullptr;
}
@@ -862,6 +911,15 @@ static const Expr *peelOffOuterExpr(const Expr *Ex,
return peelOffOuterExpr(EWC->getSubExpr(), N);
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
return peelOffOuterExpr(OVE->getSourceExpr(), N);
+ if (auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
+ auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
+ if (PropRef && PropRef->isMessagingGetter()) {
+ const Expr *GetterMessageSend =
+ POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
+ assert(isa<ObjCMessageExpr>(GetterMessageSend));
+ return peelOffOuterExpr(GetterMessageSend, N);
+ }
+ }
// Peel off the ternary operator.
if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
@@ -1494,20 +1552,6 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
return event;
}
-
-// FIXME: Copied from ExprEngineCallAndReturn.cpp.
-static bool isInStdNamespace(const Decl *D) {
- const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
- const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
- if (!ND)
- return false;
-
- while (const NamespaceDecl *Parent = dyn_cast<NamespaceDecl>(ND->getParent()))
- ND = Parent;
-
- return ND->isStdNamespace();
-}
-
std::unique_ptr<PathDiagnosticPiece>
LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
const ExplodedNode *N,
@@ -1518,7 +1562,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
AnalyzerOptions &Options = Eng.getAnalysisManager().options;
const Decl *D = N->getLocationContext()->getDecl();
- if (isInStdNamespace(D)) {
+ if (AnalysisDeclContext::isInStdNamespace(D)) {
// Skip reports within the 'std' namespace. Although these can sometimes be
// the user's fault, we currently don't report them very well, and
// Note that this will not help for any other data structure libraries, like
@@ -1552,12 +1596,6 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
}
}
- // The analyzer issues a false positive on
- // std::basic_string<uint8_t> v; v.push_back(1);
- // and
- // std::u16string s; s += u'a';
- // because we cannot reason about the internal invariants of the
- // datastructure.
for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
LCtx = LCtx->getParent()) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
@@ -1565,10 +1603,24 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
continue;
const CXXRecordDecl *CD = MD->getParent();
+ // The analyzer issues a false positive on
+ // std::basic_string<uint8_t> v; v.push_back(1);
+ // and
+ // std::u16string s; s += u'a';
+ // because we cannot reason about the internal invariants of the
+ // datastructure.
if (CD->getName() == "basic_string") {
BR.markInvalid(getTag(), nullptr);
return nullptr;
}
+
+ // The analyzer issues a false positive on
+ // std::shared_ptr<int> p(new int(1)); p = nullptr;
+ // because it does not reason properly about temporary destructors.
+ if (CD->getName() == "shared_ptr") {
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
+ }
}
}
}