1 //===- DynamicTypeMap.cpp - Dynamic Type Info related APIs ----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines APIs that track and query dynamic type information. This 11 // information can be used to devirtualize calls during the symbolic execution 12 // or do type checking. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h" 17 #include "clang/Basic/LLVM.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 20 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <cassert> 24 25 namespace clang { 26 namespace ento { 27 28 DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, 29 const MemRegion *Reg) { 30 Reg = Reg->StripCasts(); 31 32 // Look up the dynamic type in the GDM. 33 const DynamicTypeInfo *GDMType = State->get<DynamicTypeMap>(Reg); 34 if (GDMType) 35 return *GDMType; 36 37 // Otherwise, fall back to what we know about the region. 38 if (const auto *TR = dyn_cast<TypedRegion>(Reg)) 39 return DynamicTypeInfo(TR->getLocationType(), /*CanBeSubclass=*/false); 40 41 if (const auto *SR = dyn_cast<SymbolicRegion>(Reg)) { 42 SymbolRef Sym = SR->getSymbol(); 43 return DynamicTypeInfo(Sym->getType()); 44 } 45 46 return {}; 47 } 48 49 ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg, 50 DynamicTypeInfo NewTy) { 51 Reg = Reg->StripCasts(); 52 ProgramStateRef NewState = State->set<DynamicTypeMap>(Reg, NewTy); 53 assert(NewState); 54 return NewState; 55 } 56 57 void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out, 58 const char *NL, const char *Sep) { 59 bool First = true; 60 for (const auto &I : State->get<DynamicTypeMap>()) { 61 if (First) { 62 Out << NL << "Dynamic types of regions:" << NL; 63 First = false; 64 } 65 const MemRegion *MR = I.first; 66 const DynamicTypeInfo &DTI = I.second; 67 Out << MR << " : "; 68 if (DTI.isValid()) { 69 Out << DTI.getType()->getPointeeType().getAsString(); 70 if (DTI.canBeASubClass()) { 71 Out << " (or its subclass)"; 72 } 73 } else { 74 Out << "Invalid type info"; 75 } 76 Out << NL; 77 } 78 } 79 80 void *ProgramStateTrait<DynamicTypeMap>::GDMIndex() { 81 static int index = 0; 82 return &index; 83 } 84 85 } // namespace ento 86 } // namespace clang 87