xref: /freebsd/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/TaggedUnionModeling.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- TaggedUnionModeling.h -------------------------------------*- C++ -*-==//
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 #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_TAGGEDUNIONMODELING_H
10 #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_TAGGEDUNIONMODELING_H
11 
12 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
13 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
14 #include "clang/StaticAnalyzer/Core/Checker.h"
15 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
18 #include "llvm/ADT/FoldingSet.h"
19 #include <numeric>
20 
21 namespace clang::ento::tagged_union_modeling {
22 
23 // The implementation of all these functions can be found in the file
24 // StdVariantChecker.cpp under the same directory as this file.
25 
26 bool isCopyConstructorCall(const CallEvent &Call);
27 bool isCopyAssignmentCall(const CallEvent &Call);
28 bool isMoveAssignmentCall(const CallEvent &Call);
29 bool isMoveConstructorCall(const CallEvent &Call);
30 bool isStdType(const Type *Type, const std::string &TypeName);
31 bool isStdVariant(const Type *Type);
32 
33 // When invalidating regions, we also have to follow that by invalidating the
34 // corresponding custom data in the program state.
35 template <class TypeMap>
36 ProgramStateRef
removeInformationStoredForDeadInstances(const CallEvent & Call,ProgramStateRef State,ArrayRef<const MemRegion * > Regions)37 removeInformationStoredForDeadInstances(const CallEvent &Call,
38                                         ProgramStateRef State,
39                                         ArrayRef<const MemRegion *> Regions) {
40   // If we do not know anything about the call we shall not continue.
41   // If the call is happens within a system header it is implementation detail.
42   // We should not take it into consideration.
43   if (Call.isInSystemHeader())
44     return State;
45 
46   for (const MemRegion *Region : Regions)
47     State = State->remove<TypeMap>(Region);
48 
49   return State;
50 }
51 
52 template <class TypeMap>
handleConstructorAndAssignment(const CallEvent & Call,CheckerContext & C,SVal ThisSVal)53 void handleConstructorAndAssignment(const CallEvent &Call, CheckerContext &C,
54                                     SVal ThisSVal) {
55   ProgramStateRef State = Call.getState();
56 
57   if (!State)
58     return;
59 
60   auto ArgSVal = Call.getArgSVal(0);
61   const auto *ThisRegion = ThisSVal.getAsRegion();
62   const auto *ArgMemRegion = ArgSVal.getAsRegion();
63 
64   // Make changes to the state according to type of constructor/assignment
65   bool IsCopy = isCopyConstructorCall(Call) || isCopyAssignmentCall(Call);
66   bool IsMove = isMoveConstructorCall(Call) || isMoveAssignmentCall(Call);
67   // First we handle copy and move operations
68   if (IsCopy || IsMove) {
69     const QualType *OtherQType = State->get<TypeMap>(ArgMemRegion);
70 
71     // If the argument of a copy constructor or assignment is unknown then
72     // we will not know the argument of the copied to object.
73     if (!OtherQType) {
74       State = State->remove<TypeMap>(ThisRegion);
75     } else {
76       // When move semantics is used we can only know that the moved from
77       // object must be in a destructible state. Other usage of the object
78       // than destruction is undefined.
79       if (IsMove)
80         State = State->remove<TypeMap>(ArgMemRegion);
81 
82       State = State->set<TypeMap>(ThisRegion, *OtherQType);
83     }
84   } else {
85     // Value constructor
86     auto ArgQType = ArgSVal.getType(C.getASTContext());
87     const Type *ArgTypePtr = ArgQType.getTypePtr();
88 
89     QualType WoPointer = ArgTypePtr->getPointeeType();
90     State = State->set<TypeMap>(ThisRegion, WoPointer);
91   }
92 
93   C.addTransition(State);
94 }
95 
96 } // namespace clang::ento::tagged_union_modeling
97 
98 #endif // LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_TAGGEDUNIONMODELING_H
99