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