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
getDynamicTypeInfo(ProgramStateRef State,const MemRegion * Reg)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
setDynamicTypeInfo(ProgramStateRef State,const MemRegion * Reg,DynamicTypeInfo NewTy)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
printDynamicTypeInfo(ProgramStateRef State,raw_ostream & Out,const char * NL,const char * Sep)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
GDMIndex()80 void *ProgramStateTrait<DynamicTypeMap>::GDMIndex() {
81 static int index = 0;
82 return &index;
83 }
84
85 } // namespace ento
86 } // namespace clang
87