NoQ updated this revision to Diff 195810.
NoQ added a comment.
This revision is now accepted and ready to land.
Don't canonicalize the decl in the body farm. The decl supplied by the
AnalysisDeclContext is already the correct one (and not necessarily the
canonical one).
Keep the defensive behavior for NoStoreFuncVisitor because it's generally the
right thing to do for future-proofness.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D60808/new/
https://reviews.llvm.org/D60808
Files:
clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
clang/lib/Analysis/BodyFarm.cpp
clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
clang/test/Analysis/OSAtomic_mac.c
Index: clang/test/Analysis/OSAtomic_mac.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/OSAtomic_mac.c
@@ -0,0 +1,27 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,debug.ExprInspection\
+// RUN: -analyzer-output=text -verify %s
+
+int OSAtomicCompareAndSwapPtrBarrier(*, *, **);
+int OSAtomicCompareAndSwapPtrBarrier() {
+ // There is some body in the actual header,
+ // but we should trust our BodyFarm instead.
+}
+
+int *invalidSLocOnRedecl() {
+ // Was crashing when trying to throw a report about returning an uninitialized
+ // value to the caller. FIXME: We should probably still throw that report,
+ // something like "The "compare" part of CompareAndSwap depends on an
+ // undefined value".
+ int *b;
+ OSAtomicCompareAndSwapPtrBarrier(0, 0, &b); // no-crash
+ return b;
+}
+
+void testThatItActuallyWorks() {
+ void *x = 0;
+ int res = OSAtomicCompareAndSwapPtrBarrier(0, &x, &x);
+ clang_analyzer_eval(res); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
+ clang_analyzer_eval(x == &x); // expected-warning{{TRUE}}
+ // expected-note@-1{{TRUE}}
+}
Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -335,7 +335,7 @@
if (RegionOfInterest->isSubRegionOf(SelfRegion) &&
potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(),
IvarR->getDecl()))
- return maybeEmitNode(R, *Call, N, {}, SelfRegion, "self",
+ return maybeEmitNote(R, *Call, N, {}, SelfRegion, "self",
/*FirstIsReferenceType=*/false, 1);
}
}
@@ -344,7 +344,7 @@
const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion();
if (RegionOfInterest->isSubRegionOf(ThisR)
&& !CCall->getDecl()->isImplicit())
- return maybeEmitNode(R, *Call, N, {}, ThisR, "this",
+ return maybeEmitNote(R, *Call, N, {}, ThisR, "this",
/*FirstIsReferenceType=*/false, 1);
// Do not generate diagnostics for not modified parameters in
@@ -363,7 +363,7 @@
QualType T = PVD->getType();
while (const MemRegion *MR = V.getAsRegion()) {
if (RegionOfInterest->isSubRegionOf(MR) && !isPointerToConst(T))
- return maybeEmitNode(R, *Call, N, {}, MR, ParamName,
+ return maybeEmitNote(R, *Call, N, {}, MR, ParamName,
ParamIsReferenceType, IndirectionLevel);
QualType PT = T->getPointeeType();
@@ -371,7 +371,7 @@
if (const RecordDecl *RD = PT->getAsRecordDecl())
if (auto P = findRegionOfInterestInRecord(RD, State, MR))
- return maybeEmitNode(R, *Call, N, *P, RegionOfInterest, ParamName,
+ return maybeEmitNote(R, *Call, N, *P, RegionOfInterest, ParamName,
ParamIsReferenceType, IndirectionLevel);
V = State->getSVal(MR, PT);
@@ -549,7 +549,7 @@
/// \return Diagnostics piece for region not modified in the current function,
/// if it decides to emit one.
std::shared_ptr<PathDiagnosticPiece>
- maybeEmitNode(BugReport &R, const CallEvent &Call, const ExplodedNode *N,
+ maybeEmitNote(BugReport &R, const CallEvent &Call, const ExplodedNode *N,
const RegionVector &FieldChain, const MemRegion *MatchedRegion,
StringRef FirstElement, bool FirstIsReferenceType,
unsigned IndirectionLevel) {
@@ -579,6 +579,11 @@
PathDiagnosticLocation L =
PathDiagnosticLocation::create(N->getLocation(), SM);
+ // For now this shouldn't trigger, but once it does, we'll need to decide
+ // if these reports are worth suppressing as well.
+ if (!L.hasValidLocation())
+ return nullptr;
+
SmallString<256> sbuf;
llvm::raw_svector_ostream os(sbuf);
os << "Returning without writing to '";
Index: clang/lib/Analysis/BodyFarm.cpp
===================================================================
--- clang/lib/Analysis/BodyFarm.cpp
+++ clang/lib/Analysis/BodyFarm.cpp
@@ -665,8 +665,6 @@
}
Stmt *BodyFarm::getBody(const FunctionDecl *D) {
- D = D->getCanonicalDecl();
-
Optional<Stmt *> &Val = Bodies[D];
if (Val.hasValue())
return Val.getValue();
Index: clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -313,6 +313,8 @@
bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
+ bool hasValidLocation() const { return asLocation().isValid(); }
+
void invalidate() {
*this = PathDiagnosticLocation();
}
@@ -468,7 +470,7 @@
PathDiagnosticPiece::Kind k,
bool addPosRange = true)
: PathDiagnosticPiece(s, k), Pos(pos) {
- assert(Pos.isValid() && Pos.asLocation().isValid() &&
+ assert(Pos.isValid() && Pos.hasValidLocation() &&
"PathDiagnosticSpotPiece's must have a valid location.");
if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits