1 //===- DynamicTypeMap.cpp - Dynamic Type Info related APIs ----------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines APIs that track and query dynamic type information. This
10 // information can be used to devirtualize calls during the symbolic execution
11 // or do type checking.
13 //===----------------------------------------------------------------------===//
15 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
16 #include "clang/Basic/JsonSupport.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"
28 DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
29 const MemRegion *Reg) {
30 Reg = Reg->StripCasts();
32 // Look up the dynamic type in the GDM.
33 const DynamicTypeInfo *GDMType = State->get<DynamicTypeMap>(Reg);
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(), /*CanBeSub=*/false);
41 if (const auto *SR = dyn_cast<SymbolicRegion>(Reg)) {
42 SymbolRef Sym = SR->getSymbol();
43 return DynamicTypeInfo(Sym->getType());
49 ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
50 DynamicTypeInfo NewTy) {
51 Reg = Reg->StripCasts();
52 ProgramStateRef NewState = State->set<DynamicTypeMap>(Reg, NewTy);
57 void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State,
58 const char *NL, unsigned int Space, bool IsDot) {
59 Indent(Out, Space, IsDot) << "\"dynamic_types\": ";
61 const DynamicTypeMapTy &DTM = State->get<DynamicTypeMap>();
69 for (DynamicTypeMapTy::iterator I = DTM.begin(); I != DTM.end(); ++I) {
70 const MemRegion *MR = I->first;
71 const DynamicTypeInfo &DTI = I->second;
72 Out << "{ \"region\": \"" << MR << "\", \"dyn_type\": ";
74 Out << '\"' << DTI.getType()->getPointeeType().getAsString()
75 << "\", \"sub_classable\": "
76 << (DTI.canBeASubClass() ? "true" : "false");
78 Out << "null"; // Invalid type info
82 if (std::next(I) != DTM.end())
88 Indent(Out, Space, IsDot) << "]," << NL;
91 void *ProgramStateTrait<DynamicTypeMap>::GDMIndex() {