ArrayRef<ParmVarDecl *> parameters = getCallParameters(Call);
for (unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) {
- Optional<unsigned> AdjustedIdx = Call->getAdjustedParameterIndex(I);
- if (!AdjustedIdx)
- continue;
- const ParmVarDecl *PVD = parameters[*AdjustedIdx];
+ const ParmVarDecl *PVD = parameters[I];
SVal S = Call->getArgSVal(I);
bool ParamIsReferenceType = PVD->getType()->isReferenceType();
std::string ParamName = PVD->getNameAsString();
SmallString<256> sbuf;
llvm::raw_svector_ostream os(sbuf);
os << "Returning without writing to '";
- prettyPrintRegionName(FirstElement, FirstIsReferenceType, MatchedRegion,
- FieldChain, IndirectionLevel, os);
+
+ // Do not generate the note if failed to pretty-print.
+ if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType,
+ MatchedRegion, FieldChain, IndirectionLevel, os))
+ return nullptr;
os << "'";
return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
}
/// Pretty-print region \p MatchedRegion to \p os.
- void prettyPrintRegionName(StringRef FirstElement, bool FirstIsReferenceType,
+ /// \return Whether printing succeeded.
+ bool prettyPrintRegionName(StringRef FirstElement, bool FirstIsReferenceType,
const MemRegion *MatchedRegion,
const RegionVector &FieldChain,
int IndirectionLevel,
for (const MemRegion *R : RegionSequence) {
// Just keep going up to the base region.
+ // Element regions may appear due to casts.
if (isa<CXXBaseObjectRegion>(R) || isa<CXXTempObjectRegion>(R))
continue;
os << Sep;
+ // Can only reasonably pretty-print DeclRegions.
+ if (!isa<DeclRegion>(R))
+ return false;
+
const auto *DR = cast<DeclRegion>(R);
Sep = DR->getValueType()->isAnyPointerType() ? "->" : ".";
DR->getDecl()->getDeclName().print(os, PP);
prettyPrintFirstElement(FirstElement,
/*MoreItemsExpected=*/false, IndirectionLevel,
os);
+ return true;
}
/// Print first item in the chain, return new separator.
return z; // expected-warning{{Undefined or garbage value returned to caller}}
// expected-note@-1{{Undefined or garbage value returned to caller}}
}
+
+////////
+
+struct HasFieldA {
+ int x;
+};
+
+struct HasFieldB {
+ int x;
+};
+
+void maybeInitializeHasField(HasFieldA *b) {
+ if (coin()) // expected-note{{Assuming the condition is false}}
+ // expected-note@-1{{Taking false branch}}
+ ((HasFieldB*)b)->x = 120;
+}
+
+int forceElementRegionApperence() {
+ HasFieldA a;
+ maybeInitializeHasField(&a); // expected-note{{Calling 'maybeInitializeHasField'}}
+ // expected-note@-1{{Returning from 'maybeInitializeHasField'}}
+ return ((HasFieldB*)&a)->x; // expected-warning{{Undefined or garbage value returned to caller}}
+ // expected-note@-1{{Undefined or garbage value returned to caller}}
+}