Skip to content

Commit f051379

Browse files
committedSep 14, 2018
[analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger
Differential Revision: https://reviews.llvm.org/D49437 llvm-svn: 342221
1 parent d6145d9 commit f051379

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed
 

‎clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,15 @@ bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R,
274274
continue;
275275
}
276276

277-
if (isDereferencableType(T)) {
277+
SVal V = State->getSVal(FieldVal);
278+
279+
if (isDereferencableType(T) || V.getAs<nonloc::LocAsInteger>()) {
278280
if (isDereferencableUninit(FR, LocalChain))
279281
ContainsUninitField = true;
280282
continue;
281283
}
282284

283285
if (isPrimitiveType(T)) {
284-
SVal V = State->getSVal(FieldVal);
285-
286286
if (isPrimitiveUninit(V)) {
287287
if (addFieldToUninits(LocalChain.add(RegularField(FR))))
288288
ContainsUninitField = true;

‎clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp

+20-11
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ class LocField final : public FieldNode {
5757
}
5858
};
5959

60-
/// Represents a void* field that needs to be casted back to its dynamic type
61-
/// for a correct note message.
62-
class NeedsCastLocField final : public FieldNode {
60+
/// Represents a nonloc::LocAsInteger or void* field, that point to objects, but
61+
/// needs to be casted back to its dynamic type for a correct note message.
62+
class NeedsCastLocField : public FieldNode {
6363
QualType CastBackType;
6464

6565
public:
@@ -71,7 +71,13 @@ class NeedsCastLocField final : public FieldNode {
7171
}
7272

7373
virtual void printPrefix(llvm::raw_ostream &Out) const override {
74-
Out << "static_cast" << '<' << CastBackType.getAsString() << ">(";
74+
// If this object is a nonloc::LocAsInteger.
75+
if (getDecl()->getType()->isIntegerType())
76+
Out << "reinterpret_cast";
77+
// If this pointer's dynamic type is different then it's static type.
78+
else
79+
Out << "static_cast";
80+
Out << '<' << CastBackType.getAsString() << ">(";
7581
}
7682

7783
virtual void printNode(llvm::raw_ostream &Out) const override {
@@ -106,11 +112,12 @@ static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State,
106112
bool FindUninitializedFields::isDereferencableUninit(
107113
const FieldRegion *FR, FieldChainInfo LocalChain) {
108114

109-
assert(isDereferencableType(FR->getDecl()->getType()) &&
110-
"This method only checks dereferencable objects!");
111-
112115
SVal V = State->getSVal(FR);
113116

117+
assert((isDereferencableType(FR->getDecl()->getType()) ||
118+
V.getAs<nonloc::LocAsInteger>()) &&
119+
"This method only checks dereferencable objects!");
120+
114121
if (V.isUnknown() || V.getAs<loc::ConcreteInt>()) {
115122
IsAnyFieldInitialized = true;
116123
return false;
@@ -196,13 +203,15 @@ static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State,
196203

197204
llvm::SmallSet<const TypedValueRegion *, 5> VisitedRegions;
198205

199-
// If the static type of the field is a void pointer, we need to cast it back
200-
// to the dynamic type before dereferencing.
201-
bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType());
202-
203206
SVal V = State->getSVal(FR);
204207
assert(V.getAsRegion() && "V must have an underlying region!");
205208

209+
// If the static type of the field is a void pointer, or it is a
210+
// nonloc::LocAsInteger, we need to cast it back to the dynamic type before
211+
// dereferencing.
212+
bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()) ||
213+
V.getAs<nonloc::LocAsInteger>();
214+
206215
// The region we'd like to acquire.
207216
const auto *R = V.getAsRegion()->getAs<TypedValueRegion>();
208217
if (!R)

‎clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ void fConcreteIntLocTest() {
2121
ConcreteIntLocTest();
2222
}
2323

24+
//===----------------------------------------------------------------------===//
25+
// nonloc::LocAsInteger tests.
26+
//===----------------------------------------------------------------------===//
27+
28+
using intptr_t = long;
29+
30+
struct LocAsIntegerTest {
31+
intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast<char *>(this->ptr)'}}
32+
int dontGetFilteredByNonPedanticMode = 0;
33+
34+
LocAsIntegerTest(void *ptr) : ptr(reinterpret_cast<intptr_t>(ptr)) {} // expected-warning{{1 uninitialized field}}
35+
};
36+
37+
void fLocAsIntegerTest() {
38+
char c;
39+
LocAsIntegerTest t(&c);
40+
}
41+
2442
//===----------------------------------------------------------------------===//
2543
// Null pointer tests.
2644
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)
Please sign in to comment.