Store.h revision 09270cc1b9cdd4c50012cb7984df8745e05833e5
14323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek//== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==// 24323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek// 34323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek// The LLVM Compiler Infrastructure 44323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek// 54323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek// This file is distributed under the University of Illinois Open Source 64323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek// License. See LICENSE.TXT for details. 74323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek// 84323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek//===----------------------------------------------------------------------===// 94323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek// 104323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek// This file defined the types Store and StoreManager. 114323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek// 124323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek//===----------------------------------------------------------------------===// 134323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek 144323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek#ifndef LLVM_CLANG_ANALYSIS_STORE_H 154323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek#define LLVM_CLANG_ANALYSIS_STORE_H 164323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek 17993f1c72913417be7c534ec7a634363cdfc84fa5Ted Kremenek#include "clang/Analysis/PathSensitive/MemRegion.h" 1867f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek#include "clang/Analysis/PathSensitive/SVals.h" 198d7f5481a0eeb4c0508202a4bd2b754cfa93c4feTed Kremenek#include "clang/Analysis/PathSensitive/ValueManager.h" 2067f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek#include "llvm/ADT/DenseSet.h" 21f59bf48ee79ed218e6dcaf1b82fa730efd0e9999Ted Kremenek#include "llvm/ADT/SmallPtrSet.h" 22f59bf48ee79ed218e6dcaf1b82fa730efd0e9999Ted Kremenek#include "llvm/ADT/SmallSet.h" 232bc39c61077e6a49728f309bb80a949fb0b2aaffTed Kremenek#include "llvm/ADT/SmallVector.h" 244323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek 254323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremeneknamespace clang { 261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 274323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenektypedef const void* Store; 286d69b5d82281992e981caa9bc038e3f6cac6594aZhongxing Xu 291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpclass GRState; 30caa3724b1d525a888982f94a6ae2b527eb3bca7dTed Kremenekclass GRStateManager; 31f59bf48ee79ed218e6dcaf1b82fa730efd0e9999Ted Kremenekclass Stmt; 326d69b5d82281992e981caa9bc038e3f6cac6594aZhongxing Xuclass Expr; 3397ed4f68f5dba3e21e7a490ef0f9ffd3bfead7f8Ted Kremenekclass ObjCIvarDecl; 3459e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenekclass SubRegionMap; 354e3c1f7c2a2053cf770f744846a87087415eb340Zhongxing Xuclass StackFrameContext; 361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 374323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenekclass StoreManager { 38d6cfbe4bd5103cd020d987d09438744eb17226a3Ted Kremenekprotected: 398d7f5481a0eeb4c0508202a4bd2b754cfa93c4feTed Kremenek ValueManager &ValMgr; 40c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek GRStateManager &StateMgr; 418d7f5481a0eeb4c0508202a4bd2b754cfa93c4feTed Kremenek 42d6cfbe4bd5103cd020d987d09438744eb17226a3Ted Kremenek /// MRMgr - Manages region objects associated with this StoreManager. 438d7f5481a0eeb4c0508202a4bd2b754cfa93c4feTed Kremenek MemRegionManager &MRMgr; 44d6cfbe4bd5103cd020d987d09438744eb17226a3Ted Kremenek 45f7a0cf426eddae76e1a71dd2295631a2cf0560afTed Kremenek StoreManager(GRStateManager &stateMgr); 46d6cfbe4bd5103cd020d987d09438744eb17226a3Ted Kremenek 471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 484323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek virtual ~StoreManager() {} 491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 50c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// Return the value bound to specified location in a given state. 51c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// \param[in] state The analysis state. 52c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// \param[in] loc The symbolic memory location. 531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// \param[in] T An optional type that provides a hint indicating the 54c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// expected type of the returned value. This is used if the value is 55c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// lazily computed. 56c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// \return The value bound to the location \c loc. 5732c3fa4195762ba93f0b7114ab36c0941bc34432Ted Kremenek virtual SValuator::CastResult Retrieve(const GRState *state, Loc loc, 5832c3fa4195762ba93f0b7114ab36c0941bc34432Ted Kremenek QualType T = QualType()) = 0; 594193eca10ce0cc8b2dae887e935a43b26f492b5bZhongxing Xu 60c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// Return a state with the specified value bound to the given location. 61c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// \param[in] state The analysis state. 62c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// \param[in] loc The symbolic memory location. 63c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// \param[in] val The value to bind to location \c loc. 641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// \return A pointer to a GRState object that contains the same bindings as 65c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// \c state with the addition of having the value specified by \c val bound 66c6ed3840d685bd40bd921dd1f76cfb5a9b4fc599Ted Kremenek /// to the location given for \c loc. 6767f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek virtual const GRState *Bind(const GRState *state, Loc loc, SVal val) = 0; 684193eca10ce0cc8b2dae887e935a43b26f492b5bZhongxing Xu 694193eca10ce0cc8b2dae887e935a43b26f492b5bZhongxing Xu virtual Store Remove(Store St, Loc L) = 0; 701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 714f09027385466f1f4c382c80ca77157e2aef97d9Ted Kremenek /// BindCompoundLiteral - Return the store that has the bindings currently 724f09027385466f1f4c382c80ca77157e2aef97d9Ted Kremenek /// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region 734f09027385466f1f4c382c80ca77157e2aef97d9Ted Kremenek /// for the compound literal and 'BegInit' and 'EndInit' represent an 744f09027385466f1f4c382c80ca77157e2aef97d9Ted Kremenek /// array of initializer values. 7567f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek virtual const GRState *BindCompoundLiteral(const GRState *state, 7667f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek const CompoundLiteralExpr* cl, 7767f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek SVal v) = 0; 781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7959e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek /// getInitialStore - Returns the initial "empty" store representing the 8059e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek /// value bindings upon entry to an analyzed function. 8117fd8632dcda97022a51effc24060eacdad9dbe0Zhongxing Xu virtual Store getInitialStore(const LocationContext *InitLoc) = 0; 821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8359e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek /// getRegionManager - Returns the internal RegionManager object that is 8459e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek /// used to query and manipulate MemRegion objects. 85d6cfbe4bd5103cd020d987d09438744eb17226a3Ted Kremenek MemRegionManager& getRegionManager() { return MRMgr; } 861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8759e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek /// getSubRegionMap - Returns an opaque map object that clients can query 8814453bf723c025034823e4d4005a98ee176753a0Ted Kremenek /// to get the subregions of a given MemRegion object. It is the 8914453bf723c025034823e4d4005a98ee176753a0Ted Kremenek // caller's responsibility to 'delete' the returned map. 9067f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek virtual SubRegionMap *getSubRegionMap(const GRState *state) = 0; 916d69b5d82281992e981caa9bc038e3f6cac6594aZhongxing Xu 92d0f8bb1f6b51b93bf07b27b4a8f9d1823063cba8Zhongxing Xu virtual SVal getLValueVar(const VarDecl *VD, const LocationContext *LC) = 0; 93143bf82ac5afba0757e6817a2c2bb970c20b32d3Zhongxing Xu 94d0f8bb1f6b51b93bf07b27b4a8f9d1823063cba8Zhongxing Xu virtual SVal getLValueString(const StringLiteral* sl) = 0; 95f22679e3e5d5f5754931952e58112b4c863a4137Zhongxing Xu 96d0f8bb1f6b51b93bf07b27b4a8f9d1823063cba8Zhongxing Xu virtual SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl) = 0; 971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98d0f8bb1f6b51b93bf07b27b4a8f9d1823063cba8Zhongxing Xu virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) = 0; 991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100d0f8bb1f6b51b93bf07b27b4a8f9d1823063cba8Zhongxing Xu virtual SVal getLValueField(const FieldDecl* D, SVal Base) = 0; 1011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102d0f8bb1f6b51b93bf07b27b4a8f9d1823063cba8Zhongxing Xu virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0; 10360156f0596a7ab9a39ddec74942b60a3da847174Zhongxing Xu 10467f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek // FIXME: Make out-of-line. 10567f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek virtual SVal getSizeInElements(const GRState *state, const MemRegion *region){ 10660156f0596a7ab9a39ddec74942b60a3da847174Zhongxing Xu return UnknownVal(); 10760156f0596a7ab9a39ddec74942b60a3da847174Zhongxing Xu } 10860156f0596a7ab9a39ddec74942b60a3da847174Zhongxing Xu 1099deb0e35dea0f82691fadb60b61f45887ba67abaTed Kremenek /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit 1109deb0e35dea0f82691fadb60b61f45887ba67abaTed Kremenek /// conversions between arrays and pointers. 111f1d537f460c529906c73de56d891046b45434fb3Zhongxing Xu virtual SVal ArrayToPointer(Loc Array) = 0; 1121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1136eddeb153415049c7b62de4b45385a759a6906c6Ted Kremenek class CastResult { 11467f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek const GRState *state; 11567f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek const MemRegion *region; 1166eddeb153415049c7b62de4b45385a759a6906c6Ted Kremenek public: 11767f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek const GRState *getState() const { return state; } 11867f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek const MemRegion* getRegion() const { return region; } 11967f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek CastResult(const GRState *s, const MemRegion* r = 0) : state(s), region(r){} 1206eddeb153415049c7b62de4b45385a759a6906c6Ted Kremenek }; 1211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1226eddeb153415049c7b62de4b45385a759a6906c6Ted Kremenek /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from 1236eddeb153415049c7b62de4b45385a759a6906c6Ted Kremenek /// a MemRegion* to a specific location type. 'R' is the region being 1246eddeb153415049c7b62de4b45385a759a6906c6Ted Kremenek /// casted and 'CastToTy' the result type of the cast. 12509270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu const MemRegion *CastRegion(const MemRegion *region, QualType CastToTy); 1268203725f37fbb45ded343e4378247fee3389c0daZhongxing Xu 12794aa6c16e7404b2ff83a6f0ae7db8a758d389fc4Zhongxing Xu /// EvalBinOp - Perform pointer arithmetic. 12867f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek virtual SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op, 1296c07bdba93b095b66e2c8c82dd5ed458fa8285eaTed Kremenek Loc lhs, NonLoc rhs, QualType resultTy) { 13094aa6c16e7404b2ff83a6f0ae7db8a758d389fc4Zhongxing Xu return UnknownVal(); 13194aa6c16e7404b2ff83a6f0ae7db8a758d389fc4Zhongxing Xu } 1321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1332f26bc39f3b7bc93b9fdfbb79751b25704e5fdc6Ted Kremenek virtual void RemoveDeadBindings(GRState &state, Stmt* Loc, 1342f26bc39f3b7bc93b9fdfbb79751b25704e5fdc6Ted Kremenek SymbolReaper& SymReaper, 13567f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0; 136bbe8ff48be1728ef145c874d6d99879fac78892fZhongxing Xu 137d17da2b99f323fa91b01e1dd119cc32e0ee8197dTed Kremenek virtual const GRState *BindDecl(const GRState *ST, const VarDecl *VD, 138d17da2b99f323fa91b01e1dd119cc32e0ee8197dTed Kremenek const LocationContext *LC, SVal initVal) = 0; 1394193eca10ce0cc8b2dae887e935a43b26f492b5bZhongxing Xu 140d17da2b99f323fa91b01e1dd119cc32e0ee8197dTed Kremenek virtual const GRState *BindDeclWithNoInit(const GRState *ST, 141d17da2b99f323fa91b01e1dd119cc32e0ee8197dTed Kremenek const VarDecl *VD, 142d17da2b99f323fa91b01e1dd119cc32e0ee8197dTed Kremenek const LocationContext *LC) = 0; 143bbe8ff48be1728ef145c874d6d99879fac78892fZhongxing Xu 1441004a9f2b9eaf885e55ad8656194ef2a341db0f5Ted Kremenek virtual const GRState *InvalidateRegion(const GRState *state, 1451004a9f2b9eaf885e55ad8656194ef2a341db0f5Ted Kremenek const MemRegion *R, 1461004a9f2b9eaf885e55ad8656194ef2a341db0f5Ted Kremenek const Expr *E, unsigned Count) = 0; 1471004a9f2b9eaf885e55ad8656194ef2a341db0f5Ted Kremenek 14867f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek // FIXME: Make out-of-line. 14967f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek virtual const GRState *setExtent(const GRState *state, 15067f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek const MemRegion *region, SVal extent) { 15167f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek return state; 152baf03a7c0a846632396f9f5a19f6cd45bbe2b926Zhongxing Xu } 153baf03a7c0a846632396f9f5a19f6cd45bbe2b926Zhongxing Xu 1544e3c1f7c2a2053cf770f744846a87087415eb340Zhongxing Xu /// EnterStackFrame - Let the StoreManager to do something when execution 1554e3c1f7c2a2053cf770f744846a87087415eb340Zhongxing Xu /// engine is about to execute into a callee. 1564e3c1f7c2a2053cf770f744846a87087415eb340Zhongxing Xu virtual const GRState *EnterStackFrame(const GRState *state, 1574e3c1f7c2a2053cf770f744846a87087415eb340Zhongxing Xu const StackFrameContext *frame) { 158d6116cc4730245f09d458167aa94f2ea6e2b2b53Zhongxing Xu return state; 1594e3c1f7c2a2053cf770f744846a87087415eb340Zhongxing Xu } 1604e3c1f7c2a2053cf770f744846a87087415eb340Zhongxing Xu 16153ba0b636194dbeaa65a6f85316c9397a0c5298bTed Kremenek virtual void print(Store store, llvm::raw_ostream& Out, 162a622d8c2719e927b47f48dbebcece770e752dfb8Ted Kremenek const char* nl, const char *sep) = 0; 1631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16460dbad831a35ba0f58256b9bcd2a085af98ff2ecTed Kremenek class BindingsHandler { 1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump public: 16660dbad831a35ba0f58256b9bcd2a085af98ff2ecTed Kremenek virtual ~BindingsHandler(); 16760dbad831a35ba0f58256b9bcd2a085af98ff2ecTed Kremenek virtual bool HandleBinding(StoreManager& SMgr, Store store, 16867f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek const MemRegion *region, SVal val) = 0; 16960dbad831a35ba0f58256b9bcd2a085af98ff2ecTed Kremenek }; 1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17160dbad831a35ba0f58256b9bcd2a085af98ff2ecTed Kremenek /// iterBindings - Iterate over the bindings in the Store. 1720307cd59e0a48adeb9b69e3270dfe3625e7e2954Ted Kremenek virtual void iterBindings(Store store, BindingsHandler& f) = 0; 1730307cd59e0a48adeb9b69e3270dfe3625e7e2954Ted Kremenek 1741894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenekprotected: 17509270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu const MemRegion *MakeElementRegion(const MemRegion *Base, 17609270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu QualType pointeeTy, uint64_t index = 0); 1771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1781894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek /// CastRetrievedVal - Used by subclasses of StoreManager to implement 1791894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek /// implicit casts that arise from loads from regions that are reinterpreted 1801894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek /// as another region. 1811894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek SValuator::CastResult CastRetrievedVal(SVal val, const GRState *state, 1821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const TypedRegion *R, QualType castTy); 1834323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek}; 18459e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek 18567f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek// FIXME: Do we still need this? 18659e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek/// SubRegionMap - An abstract interface that represents a queryable map 18759e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek/// between MemRegion objects and their subregions. 18859e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenekclass SubRegionMap { 18959e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenekpublic: 19059e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek virtual ~SubRegionMap() {} 1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19259e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek class Visitor { 19359e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek public: 1945dc2746b6c759d2fdab050d3d41ba60ad141a0a3Ted Kremenek virtual ~Visitor() {}; 1955dc2746b6c759d2fdab050d3d41ba60ad141a0a3Ted Kremenek virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0; 19659e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek }; 1971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0; 19959e8f1128019aef95f45c6fa09cc0f8bfea99f13Ted Kremenek}; 20067f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek 20167f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek// FIXME: Do we need to pass GRStateManager anymore? 2029af46f59242cfaec74fa491a66724970478263ebTed KremenekStoreManager *CreateBasicStoreManager(GRStateManager& StMgr); 2039af46f59242cfaec74fa491a66724970478263ebTed KremenekStoreManager *CreateRegionStoreManager(GRStateManager& StMgr); 2049af46f59242cfaec74fa491a66724970478263ebTed KremenekStoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr); 20567f28534c090650ffa123afa84ff4a96f56de14eTed Kremenek 2064323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek} // end clang namespace 2074323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek 2084323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek#endif 209