]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
Unbreak DRM KMS build by adding the needed compatibility field in the LinuxKPI.
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / lib / StaticAnalyzer / Core / DynamicTypeMap.cpp
1 //===- DynamicTypeMap.cpp - Dynamic Type Info related APIs ----------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
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.
12 //
13 //===----------------------------------------------------------------------===//
14
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"
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(), /*CanBeSub=*/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 printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State,
58                               const char *NL, unsigned int Space, bool IsDot) {
59   Indent(Out, Space, IsDot) << "\"dynamic_types\": ";
60
61   const DynamicTypeMapTy &DTM = State->get<DynamicTypeMap>();
62   if (DTM.isEmpty()) {
63     Out << "null," << NL;
64     return;
65   }
66
67   ++Space;
68   Out << '[' << NL;
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\": ";
73     if (DTI.isValid()) {
74       Out << '\"' << DTI.getType()->getPointeeType().getAsString()
75           << "\", \"sub_classable\": "
76           << (DTI.canBeASubClass() ? "true" : "false");
77     } else {
78       Out << "null"; // Invalid type info
79     }
80     Out << "}";
81
82     if (std::next(I) != DTM.end())
83       Out << ',';
84     Out << NL;
85   }
86
87   --Space;
88   Indent(Out, Space, IsDot) << "]," << NL;
89 }
90
91 void *ProgramStateTrait<DynamicTypeMap>::GDMIndex() {
92   static int index = 0;
93   return &index;
94 }
95
96 } // namespace ento
97 } // namespace clang