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