From: Zhongxing Xu Date: Fri, 10 Apr 2009 08:45:10 +0000 (+0000) Subject: Add prototype for CodeTextRegion. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ec13d9206645af07ef7c571405893b8d901de151;p=clang Add prototype for CodeTextRegion. A CodeTextRegion wraps two kinds of data: FunctionDecl* or SymbolRef. The latter comes from the symbolic function pointer that are generated from function calls or input data. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68777 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 766c0918d1..1c97f1737c 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -39,6 +39,7 @@ class MemRegionManager; class MemRegion : public llvm::FoldingSetNode { public: enum Kind { MemSpaceRegionKind, + CodeTextRegionKind, SymbolicRegionKind, AllocaRegionKind, // Typed regions. @@ -113,7 +114,7 @@ public: return R->getKind() > MemSpaceRegionKind; } }; - + /// AllocaRegion - A region that represents an untyped blob of bytes created /// by a call to 'alloca'. class AllocaRegion : public SubRegion { @@ -174,6 +175,58 @@ public: } }; +/// CodeTextRegion - A region that represents code texts of a function. It wraps +/// two kinds of code texts: real function and symbolic function. Real function +/// is a function declared in the program. Symbolic function is a function +/// pointer that we don't know which function it points to. +class CodeTextRegion : public TypedRegion { +public: + enum CodeKind { Declared, Symbolic }; + +private: + // The function pointer kind that this CodeTextRegion represents. + CodeKind codekind; + + // Data may be a SymbolRef or FunctionDecl*. + const void* Data; + + // Cached function pointer type. + QualType LocationType; + +public: + + CodeTextRegion(const FunctionDecl* fd, QualType t, const MemRegion* sreg) + : TypedRegion(sreg, CodeTextRegionKind), + codekind(Declared), + Data(fd), + LocationType(t) {} + + CodeTextRegion(SymbolRef sym, QualType t, const MemRegion* sreg) + : TypedRegion(sreg, CodeTextRegionKind), + codekind(Symbolic), + Data(sym), + LocationType(t) {} + + QualType getRValueType(ASTContext &C) const { + // Do not get the object type of a CodeTextRegion. + assert(0); + return QualType(); + } + + QualType getLValueType(ASTContext &C) const { + return LocationType; + } + + void Profile(llvm::FoldingSetNodeID& ID) const; + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, + const void* data, QualType t); + + static bool classof(const MemRegion* R) { + return R->getKind() == CodeTextRegionKind; + } +}; + /// SymbolicRegion - A special, "non-concrete" region. Unlike other region /// clases, SymbolicRegion represents a region that serves as an alias for /// either a real region, a NULL pointer, etc. It essentially is used to @@ -492,6 +545,7 @@ class MemRegionManager { MemSpaceRegion* stack; MemSpaceRegion* heap; MemSpaceRegion* unknown; + MemSpaceRegion* code; public: MemRegionManager(llvm::BumpPtrAllocator& a) @@ -515,6 +569,8 @@ public: /// memory space. MemSpaceRegion* getUnknownRegion(); + MemSpaceRegion* getCodeRegion(); + bool isGlobalsRegion(const MemRegion* R) { assert(R); return R == globals; @@ -567,6 +623,9 @@ public: TypedViewRegion* getTypedViewRegion(QualType LValueType, const MemRegion* superRegion); + CodeTextRegion* getCodeTextRegion(SymbolRef sym, QualType t); + CodeTextRegion* getCodeTextRegion(const FunctionDecl* fd, QualType t); + bool hasStackStorage(const MemRegion* R); private: diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h index f83b02c227..415969b54d 100644 --- a/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/include/clang/Analysis/PathSensitive/ValueManager.h @@ -82,6 +82,8 @@ public: SVal getConjuredSymbolVal(const Expr *E, unsigned Count); SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count); + + SVal getFunctionPointer(const FunctionDecl* FD); }; } // end clang namespace #endif diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp index 7c13f0701e..c8a43a556d 100644 --- a/lib/Analysis/MemRegion.cpp +++ b/lib/Analysis/MemRegion.cpp @@ -107,6 +107,17 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { ElementRegion::ProfileRegion(ID, Index, superRegion); } +void CodeTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const void* data, + QualType t) { + ID.AddInteger(MemRegion::CodeTextRegionKind); + ID.AddPointer(data); + ID.Add(t); +} + +void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { + CodeTextRegion::ProfileRegion(ID, Data, LocationType); +} + //===----------------------------------------------------------------------===// // getLValueType() and getRValueType() //===----------------------------------------------------------------------===// @@ -209,6 +220,10 @@ MemSpaceRegion* MemRegionManager::getUnknownRegion() { return LazyAllocate(unknown); } +MemSpaceRegion* MemRegionManager::getCodeRegion() { + return LazyAllocate(code); +} + bool MemRegionManager::onStack(const MemRegion* R) { while (const SubRegion* SR = dyn_cast(R)) R = SR->getSuperRegion(); @@ -306,6 +321,39 @@ MemRegionManager::getElementRegion(SVal Idx, const TypedRegion* superRegion){ return R; } +CodeTextRegion* MemRegionManager::getCodeTextRegion(const FunctionDecl* fd, + QualType t) { + llvm::FoldingSetNodeID ID; + CodeTextRegion::ProfileRegion(ID, fd, t); + void* InsertPos; + MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); + CodeTextRegion* R = cast_or_null(data); + + if (!R) { + R = (CodeTextRegion*) A.Allocate(); + new (R) CodeTextRegion(fd, t, getCodeRegion()); + Regions.InsertNode(R, InsertPos); + } + + return R; +} + +CodeTextRegion* MemRegionManager::getCodeTextRegion(SymbolRef sym, QualType t) { + llvm::FoldingSetNodeID ID; + CodeTextRegion::ProfileRegion(ID, sym, t); + void* InsertPos; + MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); + CodeTextRegion* R = cast_or_null(data); + + if (!R) { + R = (CodeTextRegion*) A.Allocate(); + new (R) CodeTextRegion(sym, t, getCodeRegion()); + Regions.InsertNode(R, InsertPos); + } + + return R; +} + /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) { llvm::FoldingSetNodeID ID; diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp index 3e958ba801..572d5ec555 100644 --- a/lib/Analysis/SVals.cpp +++ b/lib/Analysis/SVals.cpp @@ -282,6 +282,12 @@ SVal ValueManager::getRValueSymbolVal(const MemRegion* R) { if (const TypedRegion* TR = dyn_cast(R)) { QualType T = TR->getRValueType(SymMgr.getContext()); + + // If T is of function pointer type, create a CodeTextRegion wrapping a + // symbol. + if (T->isFunctionPointerType()) { + return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T)); + } if (Loc::IsLocType(T)) return Loc::MakeVal(MemMgr.getSymbolicRegion(sym)); @@ -298,6 +304,12 @@ SVal ValueManager::getConjuredSymbolVal(const Expr* E, unsigned Count) { QualType T = E->getType(); SymbolRef sym = SymMgr.getConjuredSymbol(E, Count); + // If T is of function pointer type, create a CodeTextRegion wrapping a + // symbol. + if (T->isFunctionPointerType()) { + return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T)); + } + if (Loc::IsLocType(T)) return Loc::MakeVal(MemMgr.getSymbolicRegion(sym)); @@ -312,6 +324,12 @@ SVal ValueManager::getConjuredSymbolVal(const Expr* E, QualType T, SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count); + // If T is of function pointer type, create a CodeTextRegion wrapping a + // symbol. + if (T->isFunctionPointerType()) { + return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T)); + } + if (Loc::IsLocType(T)) return Loc::MakeVal(MemMgr.getSymbolicRegion(sym)); @@ -321,6 +339,12 @@ SVal ValueManager::getConjuredSymbolVal(const Expr* E, QualType T, return UnknownVal(); } +SVal ValueManager::getFunctionPointer(const FunctionDecl* FD) { + CodeTextRegion* R + = MemMgr.getCodeTextRegion(FD, Context.getPointerType(FD->getType())); + return Loc::MakeVal(R); +} + nonloc::LocAsInteger nonloc::LocAsInteger::Make(BasicValueFactory& Vals, Loc V, unsigned Bits) { return LocAsInteger(Vals.getPersistentSValWithData(V, Bits));