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 22namespace 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 27bool isCopyConstructorCall(const CallEvent &Call); 28bool isCopyAssignmentCall(const CallEvent &Call); 29bool isMoveAssignmentCall(const CallEvent &Call); 30bool isMoveConstructorCall(const CallEvent &Call); 31bool isStdType(const Type *Type, const std::string &TypeName); 32bool 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. 36template <class TypeMap> 37ProgramStateRef 38removeInformationStoredForDeadInstances(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 53template <class TypeMap> 54void handleConstructorAndAssignment(const CallEvent &Call, CheckerContext &C, 55 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