Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit ca80453

Browse files
committed
[analyzer] change "tag" in ProgramPoint from "void*" to a ProgramPointTag*.
Having a notion of an actual ProgramPointTag will aid in introspection of the analyzer's behavior. For example, the GraphViz output of the analyzer will pretty-print the tags in a useful manner. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137529 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 79c9c75 commit ca80453

16 files changed

+228
-99
lines changed

Diff for: include/clang/Analysis/ProgramPoint.h

+55-21
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,18 @@
2121
#include "llvm/ADT/DenseMap.h"
2222
#include "llvm/ADT/FoldingSet.h"
2323
#include "llvm/Support/Casting.h"
24+
#include "llvm/ADT/StringRef.h"
2425
#include <cassert>
2526
#include <utility>
27+
#include <string>
2628

2729
namespace clang {
2830

29-
class LocationContext;
3031
class AnalysisContext;
3132
class FunctionDecl;
32-
33+
class LocationContext;
34+
class ProgramPointTag;
35+
3336
class ProgramPoint {
3437
public:
3538
enum Kind { BlockEdgeKind,
@@ -58,15 +61,17 @@ class ProgramPoint {
5861
// The LocationContext could be NULL to allow ProgramPoint to be used in
5962
// context insensitive analysis.
6063
const LocationContext *L;
61-
const void *Tag;
64+
const ProgramPointTag *Tag;
6265

66+
ProgramPoint();
67+
6368
protected:
6469
ProgramPoint(const void* P, Kind k, const LocationContext *l,
65-
const void *tag = 0)
70+
const ProgramPointTag *tag = 0)
6671
: Data(P, static_cast<const void*>(NULL)), K(k), L(l), Tag(tag) {}
6772

6873
ProgramPoint(const void* P1, const void* P2, Kind k, const LocationContext *l,
69-
const void *tag = 0)
74+
const ProgramPointTag *tag = 0)
7075
: Data(P1, P2), K(k), L(l), Tag(tag) {}
7176

7277
protected:
@@ -76,7 +81,7 @@ class ProgramPoint {
7681
public:
7782
Kind getKind() const { return K; }
7883

79-
const void *getTag() const { return Tag; }
84+
const ProgramPointTag *getTag() const { return Tag; }
8085

8186
const LocationContext *getLocationContext() const { return L; }
8287

@@ -109,7 +114,7 @@ class ProgramPoint {
109114
class BlockEntrance : public ProgramPoint {
110115
public:
111116
BlockEntrance(const CFGBlock* B, const LocationContext *L,
112-
const void *tag = 0)
117+
const ProgramPointTag *tag = 0)
113118
: ProgramPoint(B, BlockEntranceKind, L, tag) {}
114119

115120
const CFGBlock* getBlock() const {
@@ -123,7 +128,7 @@ class BlockEntrance : public ProgramPoint {
123128

124129
/// Create a new BlockEntrance object that is the same as the original
125130
/// except for using the specified tag value.
126-
BlockEntrance withTag(const void *tag) {
131+
BlockEntrance withTag(const ProgramPointTag *tag) {
127132
return BlockEntrance(getBlock(), getLocationContext(), tag);
128133
}
129134

@@ -153,7 +158,7 @@ class BlockExit : public ProgramPoint {
153158
class StmtPoint : public ProgramPoint {
154159
public:
155160
StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
156-
const void *tag)
161+
const ProgramPointTag *tag)
157162
: ProgramPoint(S, p2, k, L, tag) {}
158163

159164
const Stmt *getStmt() const { return (const Stmt*) getData1(); }
@@ -170,7 +175,7 @@ class StmtPoint : public ProgramPoint {
170175

171176
class PreStmt : public StmtPoint {
172177
public:
173-
PreStmt(const Stmt *S, const LocationContext *L, const void *tag,
178+
PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
174179
const Stmt *SubStmt = 0)
175180
: StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
176181

@@ -184,15 +189,16 @@ class PreStmt : public StmtPoint {
184189
class PostStmt : public StmtPoint {
185190
protected:
186191
PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L,
187-
const void *tag =0)
192+
const ProgramPointTag *tag =0)
188193
: StmtPoint(S, data, k, L, tag) {}
189194

190195
public:
191196
explicit PostStmt(const Stmt* S, Kind k,
192-
const LocationContext *L, const void *tag = 0)
197+
const LocationContext *L, const ProgramPointTag *tag = 0)
193198
: StmtPoint(S, NULL, k, L, tag) {}
194199

195-
explicit PostStmt(const Stmt* S, const LocationContext *L,const void *tag = 0)
200+
explicit PostStmt(const Stmt* S, const LocationContext *L,
201+
const ProgramPointTag *tag = 0)
196202
: StmtPoint(S, NULL, PostStmtKind, L, tag) {}
197203

198204
static bool classof(const ProgramPoint* Location) {
@@ -225,7 +231,8 @@ class PostStmtCustom : public PostStmt {
225231
// PostCondition represents the post program point of a branch condition.
226232
class PostCondition : public PostStmt {
227233
public:
228-
PostCondition(const Stmt* S, const LocationContext *L, const void *tag = 0)
234+
PostCondition(const Stmt* S, const LocationContext *L,
235+
const ProgramPointTag *tag = 0)
229236
: PostStmt(S, PostConditionKind, L, tag) {}
230237

231238
static bool classof(const ProgramPoint* Location) {
@@ -236,7 +243,7 @@ class PostCondition : public PostStmt {
236243
class LocationCheck : public StmtPoint {
237244
protected:
238245
LocationCheck(const Stmt *S, const LocationContext *L,
239-
ProgramPoint::Kind K, const void *tag)
246+
ProgramPoint::Kind K, const ProgramPointTag *tag)
240247
: StmtPoint(S, NULL, K, L, tag) {}
241248

242249
static bool classof(const ProgramPoint *location) {
@@ -247,7 +254,8 @@ class LocationCheck : public StmtPoint {
247254

248255
class PreLoad : public LocationCheck {
249256
public:
250-
PreLoad(const Stmt *S, const LocationContext *L, const void *tag = 0)
257+
PreLoad(const Stmt *S, const LocationContext *L,
258+
const ProgramPointTag *tag = 0)
251259
: LocationCheck(S, L, PreLoadKind, tag) {}
252260

253261
static bool classof(const ProgramPoint *location) {
@@ -257,7 +265,8 @@ class PreLoad : public LocationCheck {
257265

258266
class PreStore : public LocationCheck {
259267
public:
260-
PreStore(const Stmt *S, const LocationContext *L, const void *tag = 0)
268+
PreStore(const Stmt *S, const LocationContext *L,
269+
const ProgramPointTag *tag = 0)
261270
: LocationCheck(S, L, PreStoreKind, tag) {}
262271

263272
static bool classof(const ProgramPoint *location) {
@@ -267,7 +276,8 @@ class PreStore : public LocationCheck {
267276

268277
class PostLoad : public PostStmt {
269278
public:
270-
PostLoad(const Stmt* S, const LocationContext *L, const void *tag = 0)
279+
PostLoad(const Stmt* S, const LocationContext *L,
280+
const ProgramPointTag *tag = 0)
271281
: PostStmt(S, PostLoadKind, L, tag) {}
272282

273283
static bool classof(const ProgramPoint* Location) {
@@ -277,7 +287,8 @@ class PostLoad : public PostStmt {
277287

278288
class PostStore : public PostStmt {
279289
public:
280-
PostStore(const Stmt* S, const LocationContext *L, const void *tag = 0)
290+
PostStore(const Stmt* S, const LocationContext *L,
291+
const ProgramPointTag *tag = 0)
281292
: PostStmt(S, PostStoreKind, L, tag) {}
282293

283294
static bool classof(const ProgramPoint* Location) {
@@ -287,7 +298,8 @@ class PostStore : public PostStmt {
287298

288299
class PostLValue : public PostStmt {
289300
public:
290-
PostLValue(const Stmt* S, const LocationContext *L, const void *tag = 0)
301+
PostLValue(const Stmt* S, const LocationContext *L,
302+
const ProgramPointTag *tag = 0)
291303
: PostStmt(S, PostLValueKind, L, tag) {}
292304

293305
static bool classof(const ProgramPoint* Location) {
@@ -298,7 +310,7 @@ class PostLValue : public PostStmt {
298310
class PostPurgeDeadSymbols : public PostStmt {
299311
public:
300312
PostPurgeDeadSymbols(const Stmt* S, const LocationContext *L,
301-
const void *tag = 0)
313+
const ProgramPointTag *tag = 0)
302314
: PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {}
303315

304316
static bool classof(const ProgramPoint* Location) {
@@ -365,6 +377,28 @@ class CallExit : public StmtPoint {
365377
}
366378
};
367379

380+
/// ProgramPoints can be "tagged" as representing points specific to a given
381+
/// analysis entity. Tags are abstract annotations, with an associated
382+
/// description and potentially other information.
383+
class ProgramPointTag {
384+
public:
385+
ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
386+
virtual ~ProgramPointTag();
387+
virtual StringRef getTagDescription() const = 0;
388+
389+
protected:
390+
const void *getTagKind() { return TagKind; }
391+
392+
private:
393+
const void *TagKind;
394+
};
395+
396+
class SimpleProgramPointTag : public ProgramPointTag {
397+
std::string desc;
398+
public:
399+
SimpleProgramPointTag(StringRef description);
400+
StringRef getTagDescription() const;
401+
};
368402

369403
} // end namespace clang
370404

Diff for: include/clang/StaticAnalyzer/Core/Checker.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_CLANG_SA_CORE_CHECKER
1515
#define LLVM_CLANG_SA_CORE_CHECKER
1616

17+
#include "clang/Analysis/ProgramPoint.h"
1718
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
1819
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
1920
#include "llvm/Support/Casting.h"
@@ -329,6 +330,11 @@ class Call {
329330

330331
} // end eval namespace
331332

333+
class CheckerBase : public ProgramPointTag {
334+
public:
335+
StringRef getTagDescription() const;
336+
};
337+
332338
template <typename CHECK1, typename CHECK2=check::_VoidCheck,
333339
typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
334340
typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
@@ -341,7 +347,9 @@ template <>
341347
class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
342348
check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
343349
check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
344-
check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> {
350+
check::_VoidCheck, check::_VoidCheck, check::_VoidCheck>
351+
: public CheckerBase
352+
{
345353
public:
346354
static void _register(void *checker, CheckerManager &mgr) { }
347355
};

Diff for: include/clang/StaticAnalyzer/Core/CheckerManager.h

+13-12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace clang {
2727
class CallExpr;
2828

2929
namespace ento {
30+
class CheckerBase;
3031
class ExprEngine;
3132
class AnalysisManager;
3233
class BugReporter;
@@ -55,8 +56,8 @@ class CheckerFn<RET(P1, P2, P3, P4)> {
5556
typedef RET (*Func)(void *, P1, P2, P3, P4);
5657
Func Fn;
5758
public:
58-
void *Checker;
59-
CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
59+
CheckerBase *Checker;
60+
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
6061
RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const {
6162
return Fn(Checker, p1, p2, p3, p4);
6263
}
@@ -67,8 +68,8 @@ class CheckerFn<RET(P1, P2, P3)> {
6768
typedef RET (*Func)(void *, P1, P2, P3);
6869
Func Fn;
6970
public:
70-
void *Checker;
71-
CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
71+
CheckerBase *Checker;
72+
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
7273
RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); }
7374
};
7475

@@ -77,8 +78,8 @@ class CheckerFn<RET(P1, P2)> {
7778
typedef RET (*Func)(void *, P1, P2);
7879
Func Fn;
7980
public:
80-
void *Checker;
81-
CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
81+
CheckerBase *Checker;
82+
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
8283
RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); }
8384
};
8485

@@ -87,8 +88,8 @@ class CheckerFn<RET(P1)> {
8788
typedef RET (*Func)(void *, P1);
8889
Func Fn;
8990
public:
90-
void *Checker;
91-
CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
91+
CheckerBase *Checker;
92+
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
9293
RET operator()(P1 p1) const { return Fn(Checker, p1); }
9394
};
9495

@@ -97,8 +98,8 @@ class CheckerFn<RET()> {
9798
typedef RET (*Func)(void *);
9899
Func Fn;
99100
public:
100-
void *Checker;
101-
CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
101+
CheckerBase *Checker;
102+
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
102103
RET operator()() const { return Fn(Checker); }
103104
};
104105

@@ -115,8 +116,8 @@ class CheckerManager {
115116

116117
const LangOptions &getLangOptions() const { return LangOpts; }
117118

118-
typedef void *CheckerRef;
119-
typedef void *CheckerTag;
119+
typedef CheckerBase *CheckerRef;
120+
typedef const void *CheckerTag;
120121
typedef CheckerFn<void ()> CheckerDtor;
121122

122123
//===----------------------------------------------------------------------===//

Diff for: include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class CheckerContext {
2828
ExprEngine &Eng;
2929
ExplodedNode *Pred;
3030
SaveAndRestore<bool> OldSink;
31-
const void *checkerTag;
31+
const ProgramPointTag *checkerTag;
3232
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
3333
SaveOr OldHasGen;
3434
const GRState *ST;
@@ -39,7 +39,7 @@ class CheckerContext {
3939
public:
4040
CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
4141
ExprEngine &eng, ExplodedNode *pred,
42-
const void *tag, ProgramPoint::Kind K,
42+
const ProgramPointTag *tag, ProgramPoint::Kind K,
4343
bool *respondsToCB = 0,
4444
const Stmt *stmt = 0, const GRState *st = 0)
4545
: Dst(dst), B(builder), Eng(eng), Pred(pred),
@@ -104,7 +104,7 @@ class CheckerContext {
104104
}
105105

106106
ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
107-
bool autoTransition = true, const void *tag = 0) {
107+
bool autoTransition = true, const ProgramPointTag *tag = 0) {
108108
assert(state);
109109
ExplodedNode *N = generateNodeImpl(stmt, state, false,
110110
tag ? tag : checkerTag);
@@ -123,7 +123,7 @@ class CheckerContext {
123123
}
124124

125125
ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
126-
const void *tag = 0) {
126+
const ProgramPointTag *tag = 0) {
127127
assert(statement && "Only transitions with statements currently supported");
128128
ExplodedNode *N = generateNodeImpl(statement, state, false,
129129
tag ? tag : checkerTag);
@@ -147,7 +147,7 @@ class CheckerContext {
147147
Dst.Add(node);
148148
}
149149

150-
void addTransition(const GRState *state, const void *tag = 0) {
150+
void addTransition(const GRState *state, const ProgramPointTag *tag = 0) {
151151
assert(state);
152152
// If the 'state' is not new, we need to check if the cached state 'ST'
153153
// is new.
@@ -168,7 +168,7 @@ class CheckerContext {
168168

169169
private:
170170
ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
171-
bool markAsSink, const void *tag) {
171+
bool markAsSink, const ProgramPointTag *tag) {
172172
ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
173173
if (markAsSink && node)
174174
node->markAsSink();

0 commit comments

Comments
 (0)