ProgramPoint.h revision 1ab69c513239596946286373e081b89fa3358612
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-//
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//
307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//                     The LLVM Compiler Infrastructure
407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//
507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// This file is distributed under the University of Illinois Open Source
607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// License. See LICENSE.TXT for details.
7ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark//
8dac1d17027dcaa5596885a9f333979418b35001ccaryclark//===----------------------------------------------------------------------===//
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com//  This file defines the interface ProgramPoint, which identifies a
11ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark//  distinct location in a function.
12ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark//
13ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark//===----------------------------------------------------------------------===//
14ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
15ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
16ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
17ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
18ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#include "clang/Analysis/AnalysisContext.h"
19ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#include "clang/Analysis/CFG.h"
20ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark#include "llvm/Support/DataTypes.h"
2107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "llvm/ADT/DenseMap.h"
2207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "llvm/ADT/FoldingSet.h"
2307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "llvm/Support/Casting.h"
2407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "llvm/ADT/StringRef.h"
2507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include <cassert>
2607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include <utility>
2707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include <string>
2807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comnamespace clang {
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass AnalysisContext;
3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass FunctionDecl;
334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgclass LocationContext;
344431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgclass ProgramPointTag;
3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass ProgramPoint {
3707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
3807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  enum Kind { BlockEdgeKind,
3907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              BlockEntranceKind,
4007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              BlockExitKind,
4107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              PreStmtKind,
4207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              PostStmtKind,
4307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              PreLoadKind,
4407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              PostLoadKind,
45ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark              PreStoreKind,
46ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark              PostStoreKind,
47ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark              PostPurgeDeadSymbolsKind,
484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org              PostStmtCustomKind,
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              PostConditionKind,
50ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark              PostLValueKind,
51ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark              PostInitializerKind,
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              CallEnterKind,
534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org              CallExitKind,
5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              MinPostStmtKind = PostStmtKind,
5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com              MaxPostStmtKind = CallExitKind };
56ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
57ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkprivate:
58ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  std::pair<const void *, const void *> Data;
59ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  Kind K;
60ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
61ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  // The LocationContext could be NULL to allow ProgramPoint to be used in
62ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  // context insensitive analysis.
63ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const LocationContext *L;
64ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const ProgramPointTag *Tag;
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
66ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  ProgramPoint();
67ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
68ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkprotected:
694431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  ProgramPoint(const void* P, Kind k, const LocationContext *l,
704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org               const ProgramPointTag *tag = 0)
714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    : Data(P, static_cast<const void*>(NULL)), K(k), L(l), Tag(tag) {}
724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
73ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  ProgramPoint(const void* P1, const void* P2, Kind k, const LocationContext *l,
7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com               const ProgramPointTag *tag = 0)
7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : Data(P1, P2), K(k), L(l), Tag(tag) {}
76ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comprotected:
78ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const void* getData1() const { return Data.first; }
79ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const void* getData2() const { return Data.second; }
80ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
81ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkpublic:
82ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  Kind getKind() const { return K; }
83ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
84ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const ProgramPointTag *getTag() const { return Tag; }
85ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
86ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const LocationContext *getLocationContext() const { return L; }
874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  // For use with DenseMap.  This hash is probably slow.
8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  unsigned getHashValue() const {
904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    llvm::FoldingSetNodeID ID;
91ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    Profile(ID);
9207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return ID.ComputeHash();
9307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  static bool classof(const ProgramPoint*) { return true; }
964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
97ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  bool operator==(const ProgramPoint & RHS) const {
98ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag;
99ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
100ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
101ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  bool operator!=(const ProgramPoint& RHS) const {
102ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return K != RHS.K || Data != RHS.Data || L != RHS.L || Tag != RHS.Tag;
10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
10407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
105ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  void Profile(llvm::FoldingSetNodeID& ID) const {
10607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    ID.AddInteger((unsigned) K);
10707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    ID.AddPointer(Data.first);
10807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    ID.AddPointer(Data.second);
10907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    ID.AddPointer(L);
11007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    ID.AddPointer(Tag);
111ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
112ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
113ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass BlockEntrance : public ProgramPoint {
11507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
11607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  BlockEntrance(const CFGBlock* B, const LocationContext *L,
117ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                const ProgramPointTag *tag = 0)
11807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : ProgramPoint(B, BlockEntranceKind, L, tag) {}
11907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
120ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const CFGBlock* getBlock() const {
121ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return reinterpret_cast<const CFGBlock*>(getData1());
12207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
12307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
12407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  const CFGElement getFirstElement() const {
125ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    const CFGBlock* B = getBlock();
126ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return B->empty() ? CFGElement() : B->front();
12707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
12907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  /// Create a new BlockEntrance object that is the same as the original
130ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  /// except for using the specified tag value.
131ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  BlockEntrance withTag(const ProgramPointTag *tag) {
13207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return BlockEntrance(getBlock(), getLocationContext(), tag);
13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
13407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
135ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint* Location) {
13607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return Location->getKind() == BlockEntranceKind;
13707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
138ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
139ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
140ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass BlockExit : public ProgramPoint {
141ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkpublic:
142ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  BlockExit(const CFGBlock* B, const LocationContext *L)
14307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : ProgramPoint(B, BlockExitKind, L) {}
14407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
14507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  const CFGBlock* getBlock() const {
146ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return reinterpret_cast<const CFGBlock*>(getData1());
147ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
148ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
149ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const Stmt* getTerminator() const {
15065f553182ab7069378ef863d30094d0327f178d0caryclark    return getBlock()->getTerminator();
15165f553182ab7069378ef863d30094d0327f178d0caryclark  }
15265f553182ab7069378ef863d30094d0327f178d0caryclark
15365f553182ab7069378ef863d30094d0327f178d0caryclark  static bool classof(const ProgramPoint* Location) {
154ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return Location->getKind() == BlockExitKind;
15507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
15607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
157ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass StmtPoint : public ProgramPoint {
15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
160ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
161ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            const ProgramPointTag *tag)
1624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    : ProgramPoint(S, p2, k, L, tag) {}
163ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
1644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
16507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
16607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  template <typename T>
16707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
16807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
16907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  static bool classof(const ProgramPoint* Location) {
1704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    unsigned k = Location->getKind();
1714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    return k >= PreStmtKind && k <= MaxPostStmtKind;
1724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  }
1734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org};
17407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
1764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgclass PreStmt : public StmtPoint {
1774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgpublic:
1784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
17907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com          const Stmt *SubStmt = 0)
18007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
18107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
182dac1d17027dcaa5596885a9f333979418b35001ccaryclark  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
183ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
184570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com  static bool classof(const ProgramPoint* Location) {
18507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return Location->getKind() == PreStmtKind;
18607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
18707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
18807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
189ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass PostStmt : public StmtPoint {
190ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkprotected:
191ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L,
19207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com           const ProgramPointTag *tag =0)
19307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : StmtPoint(S, data, k, L, tag) {}
194ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
1954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgpublic:
196ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  explicit PostStmt(const Stmt* S, Kind k,
1974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                    const LocationContext *L, const ProgramPointTag *tag = 0)
19807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : StmtPoint(S, NULL, k, L, tag) {}
19907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
20007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  explicit PostStmt(const Stmt* S, const LocationContext *L,
20107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                    const ProgramPointTag *tag = 0)
20207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
203ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
204ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint* Location) {
20507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    unsigned k = Location->getKind();
20607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
207ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
20807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
20907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
21007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass PostStmtCustom : public PostStmt {
21107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
21207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  PostStmtCustom(const Stmt* S,
21307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                 const std::pair<const void*, const void*>* TaggedData,\
21407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                 const LocationContext *L)
215ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    : PostStmt(S, TaggedData, PostStmtCustomKind, L) {}
21607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
217277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com  const std::pair<const void*, const void*>& getTaggedPair() const {
21807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return
21907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com      *reinterpret_cast<const std::pair<const void*, const void*>*>(getData2());
22007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
22107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
22207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  const void* getTag() const { return getTaggedPair().first; }
22307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
22407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  const void* getTaggedData() const { return getTaggedPair().second; }
22507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
22607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  static bool classof(const ProgramPoint* Location) {
22707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return Location->getKind() == PostStmtCustomKind;
22807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
22907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
23007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
23107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// PostCondition represents the post program point of a branch condition.
23207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass PostCondition : public PostStmt {
23307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
23407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  PostCondition(const Stmt* S, const LocationContext *L,
23507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                const ProgramPointTag *tag = 0)
23607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : PostStmt(S, PostConditionKind, L, tag) {}
23707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
23807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  static bool classof(const ProgramPoint* Location) {
23907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return Location->getKind() == PostConditionKind;
24007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  }
24107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
24207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
24307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass LocationCheck : public StmtPoint {
24407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comprotected:
24507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  LocationCheck(const Stmt *S, const LocationContext *L,
24607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                ProgramPoint::Kind K, const ProgramPointTag *tag)
24707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : StmtPoint(S, NULL, K, L, tag) {}
24807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
24907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  static bool classof(const ProgramPoint *location) {
250ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    unsigned k = location->getKind();
251ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return k == PreLoadKind || k == PreStoreKind;
252ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
253ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
2544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
255ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass PreLoad : public LocationCheck {
256ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkpublic:
257ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  PreLoad(const Stmt *S, const LocationContext *L,
258ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark          const ProgramPointTag *tag = 0)
259ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    : LocationCheck(S, L, PreLoadKind, tag) {}
260ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
261ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint *location) {
262ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return location->getKind() == PreLoadKind;
263ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
264ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
265ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
266ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass PreStore : public LocationCheck {
26707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
268ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  PreStore(const Stmt *S, const LocationContext *L,
269ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark           const ProgramPointTag *tag = 0)
27007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  : LocationCheck(S, L, PreStoreKind, tag) {}
27107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
272ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint *location) {
273ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return location->getKind() == PreStoreKind;
274ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
275ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
276ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
277ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass PostLoad : public PostStmt {
278ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkpublic:
279ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  PostLoad(const Stmt* S, const LocationContext *L,
280ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark           const ProgramPointTag *tag = 0)
281ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    : PostStmt(S, PostLoadKind, L, tag) {}
282ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
283ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint* Location) {
284ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return Location->getKind() == PostLoadKind;
285ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
286ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
287ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
288ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass PostStore : public PostStmt {
2894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgpublic:
2904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  PostStore(const Stmt* S, const LocationContext *L,
291ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            const ProgramPointTag *tag = 0)
292ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    : PostStmt(S, PostStoreKind, L, tag) {}
293ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
2944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  static bool classof(const ProgramPoint* Location) {
2954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    return Location->getKind() == PostStoreKind;
296ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
297ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
298ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
299ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass PostLValue : public PostStmt {
3004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgpublic:
301ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  PostLValue(const Stmt* S, const LocationContext *L,
3024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org             const ProgramPointTag *tag = 0)
3034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    : PostStmt(S, PostLValueKind, L, tag) {}
304ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
3054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  static bool classof(const ProgramPoint* Location) {
306dac1d17027dcaa5596885a9f333979418b35001ccaryclark    return Location->getKind() == PostLValueKind;
3074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  }
308ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
3094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
310ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass PostPurgeDeadSymbols : public PostStmt {
3114431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgpublic:
312dac1d17027dcaa5596885a9f333979418b35001ccaryclark  PostPurgeDeadSymbols(const Stmt* S, const LocationContext *L,
313dac1d17027dcaa5596885a9f333979418b35001ccaryclark                       const ProgramPointTag *tag = 0)
3144431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {}
3154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
316ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint* Location) {
317ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return Location->getKind() == PostPurgeDeadSymbolsKind;
318ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
319ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
320ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
321ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass BlockEdge : public ProgramPoint {
322ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkpublic:
323ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L)
324ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    : ProgramPoint(B1, B2, BlockEdgeKind, L) {}
325ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
326ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const CFGBlock* getSrc() const {
327ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return static_cast<const CFGBlock*>(getData1());
328ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
329ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
330ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const CFGBlock* getDst() const {
331ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return static_cast<const CFGBlock*>(getData2());
332ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
333ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
334ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint* Location) {
335ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return Location->getKind() == BlockEdgeKind;
336ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
337ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
338ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
339ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass PostInitializer : public ProgramPoint {
340ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkpublic:
341ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  PostInitializer(const CXXCtorInitializer *I,
342ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                  const LocationContext *L)
343ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    : ProgramPoint(I, PostInitializerKind, L) {}
344ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
345ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint *Location) {
3464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    return Location->getKind() == PostInitializerKind;
3474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  }
348ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
349ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
350ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass CallEnter : public StmtPoint {
351ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkpublic:
3524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
353ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark            const LocationContext *callerCtx)
354ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
355ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
356ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const Stmt *getCallExpr() const {
357ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return static_cast<const Stmt *>(getData1());
358ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
359ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
360ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const StackFrameContext *getCalleeContext() const {
361ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return static_cast<const StackFrameContext *>(getData2());
362ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
363ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
364ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint *Location) {
365ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return Location->getKind() == CallEnterKind;
366ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
367ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
368ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
369ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass CallExit : public StmtPoint {
370ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkpublic:
371ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  // CallExit uses the callee's location context.
372ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  CallExit(const Stmt *S, const LocationContext *L)
373ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    : StmtPoint(S, 0, CallExitKind, L, 0) {}
374ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
375ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  static bool classof(const ProgramPoint *Location) {
376ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark    return Location->getKind() == CallExitKind;
377ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  }
378ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
379ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
380ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark/// ProgramPoints can be "tagged" as representing points specific to a given
381ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark/// analysis entity.  Tags are abstract annotations, with an associated
382ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark/// description and potentially other information.
383ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass ProgramPointTag {
384ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkpublic:
385ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
386ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  virtual ~ProgramPointTag();
387ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  virtual StringRef getTagDescription() const = 0;
388ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
389ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkprotected:
390ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  /// Used to implement 'classof' in subclasses.
391ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const void *getTagKind() { return TagKind; }
392ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
393ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkprivate:
394ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  const void *TagKind;
395ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
396ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
397ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkclass SimpleProgramPointTag : public ProgramPointTag {
3984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org  std::string desc;
3994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.orgpublic:
400ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  SimpleProgramPointTag(StringRef description);
401ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  StringRef getTagDescription() const;
402ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
403ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
404ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} // end namespace clang
405ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
406ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
407ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarknamespace llvm { // Traits specialization for DenseMap
408ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
40907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comtemplate <> struct DenseMapInfo<clang::ProgramPoint> {
41007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
411ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkstatic inline clang::ProgramPoint getEmptyKey() {
41207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com  uintptr_t x =
413ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
414ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
41507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
416ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
417ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkstatic inline clang::ProgramPoint getTombstoneKey() {
418ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  uintptr_t x =
419ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
420ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
421ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
422ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
423dac1d17027dcaa5596885a9f333979418b35001ccaryclarkstatic unsigned getHashValue(const clang::ProgramPoint& Loc) {
424ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  return Loc.getHashValue();
42565f553182ab7069378ef863d30094d0327f178d0caryclark}
42665f553182ab7069378ef863d30094d0327f178d0caryclark
427ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkstatic bool isEqual(const clang::ProgramPoint& L,
428ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark                    const clang::ProgramPoint& R) {
429ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark  return L == R;
430ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark}
43107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
432ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark};
433ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
434ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarktemplate <>
435ccec0f958ffc71a9986d236bc2eb335cb2111119caryclarkstruct isPodLike<clang::ProgramPoint> { static const bool value = true; };
436ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
437ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark} // end namespace llvm
438ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark
43907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
440ccec0f958ffc71a9986d236bc2eb335cb2111119caryclark