;
28using namespacetagged_union_modeling;
32namespace
clang::ento::tagged_union_modeling {
36 const auto*ConstructorCall = dyn_cast<CXXConstructorCall>(&
Call);
40 returnConstructorCall->getDecl();
46 returnConstructorDecl->isCopyConstructor();
51 const Decl*CopyAssignmentDecl =
Call.getDecl();
53 if(
const auto*AsMethodDecl =
54dyn_cast_or_null<CXXMethodDecl>(CopyAssignmentDecl))
55 returnAsMethodDecl->isCopyAssignmentOperator();
69 const Decl*CopyAssignmentDecl =
Call.getDecl();
71 const auto*AsMethodDecl =
72dyn_cast_or_null<CXXMethodDecl>(CopyAssignmentDecl);
76 returnAsMethodDecl->isMoveAssignmentOperator();
92staticstd::optional<ArrayRef<TemplateArgument>>
101staticstd::optional<QualType>
103std::optional<ArrayRef<TemplateArgument>> VariantTemplates =
105 if(!VariantTemplates)
108 return(*VariantTemplates)[i].getAsType();
133{
"std",
"variant",
"variant"}};
135{
"std",
"variant",
"operator="}};
138 BugTypeBadVariantType{
this,
"BadVariantType",
"BadVariantType"};
150 returnremoveInformationStoredForDeadInstances<VariantHeldTypeMap>(
151*
Call, State, Regions);
157 if(
Call.isCalledFromSystemHeader())
161 returnhandleStdGetCall(
Call,
C);
165 boolIsVariantConstructor =
166isa<CXXConstructorCall>(
Call) && VariantConstructor.
matches(
Call);
167 boolIsVariantAssignmentOperatorCall =
168isa<CXXMemberOperatorCall>(
Call) &&
171 if(IsVariantConstructor || IsVariantAssignmentOperatorCall) {
172 if(
Call.getNumArgs() == 0 && IsVariantConstructor) {
173handleDefaultConstructor(cast<CXXConstructorCall>(&
Call),
C);
179 if(
Call.getNumArgs() != 1)
183 if(IsVariantConstructor) {
184 const auto&AsConstructorCall = cast<CXXConstructorCall>(
Call);
185ThisSVal = AsConstructorCall.getCXXThisVal();
186}
else if(IsVariantAssignmentOperatorCall) {
187 const auto&AsMemberOpCall = cast<CXXMemberOperatorCall>(
Call);
188ThisSVal = AsMemberOpCall.getCXXThisVal();
193handleConstructorAndAssignment<VariantHeldTypeMap>(
Call,
C, ThisSVal);
207 const auto*
constThisMemRegion = ThisSVal.
getAsRegion();
217State = State->set<VariantHeldTypeMap>(ThisMemRegion, *DefaultType);
218 C.addTransition(State);
224 const auto&ArgType =
Call.getArgSVal(0)
225.getType(
C.getASTContext())
235 const MemRegion*ArgMemRegion =
Call.getArgSVal(0).getAsRegion();
236 const QualType*StoredType = State->get<VariantHeldTypeMap>(ArgMemRegion);
240 const CallExpr*CE = cast<CallExpr>(
Call.getOriginExpr());
251 switch(TypeOut.getKind()) {
252 caseTemplateArgument::ArgKind::Type:
253RetrievedType = TypeOut.getAsType();
255 caseTemplateArgument::ArgKind::Integral:
258 if(std::optional<QualType> NthTemplate =
260ArgType, TypeOut.getAsIntegral().getSExtValue())) {
261RetrievedType = *NthTemplate;
270 QualTypeStoredCanonicalType = StoredType->getCanonicalType();
271 if(RetrievedCanonicalType == StoredCanonicalType)
278llvm::raw_svector_ostream OS(Str);
279std::string StoredTypeName = StoredType->getAsString();
280std::string RetrievedTypeName = RetrievedType.
getAsString();
283<< StoredTypeName <<
"\', not " 285<< RetrievedTypeName <<
"\'";
286 autoR = std::make_unique<PathSensitiveBugReport>(BadVariantType, OS.str(),
288 C.emitReport(std::move(R));
293boolclang::ento::shouldRegisterStdVariantChecker(
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
static std::optional< ArrayRef< TemplateArgument > > getTemplateArgsFromVariant(const Type *VariantType)
static std::optional< QualType > getNthTemplateTypeArgFromVariant(const Type *varType, unsigned i)
static llvm::StringRef indefiniteArticleBasedOnVowel(char a)
static bool isVowel(char a)
C Language Family Type Representation.
ProgramStateRef checkRegionChanges(ProgramStateRef State, const InvalidatedSymbols *, ArrayRef< const MemRegion * >, ArrayRef< const MemRegion * > Regions, const LocationContext *, const CallEvent *Call) const
bool evalCall(const CallEvent &Call, CheckerContext &C) const
Represents a C++ constructor within a class.
bool isMoveConstructor(unsigned &TypeQuals) const
Determine whether this constructor is a move constructor (C++11 [class.copy]p3), which can be used to...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
Represents a function declaration or definition.
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
QualType getCanonicalType() const
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
unsigned size() const
Retrieve the number of template arguments in this template argument list.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
Represents a type template specialization; the template must be a class template, a type alias templa...
ArrayRef< TemplateArgument > template_arguments() const
The base class of the type hierarchy.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const T * getAs() const
Member-template getAs<specific type>'.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
SVal getCXXThisVal() const
Returns the value of the implicit 'this' object.
Represents a call to a C++ constructor.
A CallDescription is a pattern that can be used to match calls based on the qualified name and the ar...
bool matches(const CallEvent &Call) const
Returns true if the CallEvent is a call to a function that matches the CallDescription.
Represents an abstract call to a function or method along a particular path.
const ProgramStateRef & getState() const
The state in which the call is being evaluated.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
MemRegion - The root abstract class for all memory regions.
std::string getDescriptiveName(bool UseQuotes=true) const
Get descriptive name for memory region.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
QualType getType(const ASTContext &) const
Try to get a reasonable type for the given value.
const MemRegion * getAsRegion() const
bool isCopyAssignmentCall(const CallEvent &Call)
static const CXXConstructorDecl * getConstructorDeclarationForCall(const CallEvent &Call)
static bool isStdType(const Type *Type, llvm::StringRef TypeName)
bool isMoveAssignmentCall(const CallEvent &Call)
bool isCopyConstructorCall(const CallEvent &Call)
bool isStdVariant(const Type *Type)
bool isMoveConstructorCall(const CallEvent &Call)
llvm::DenseSet< SymbolRef > InvalidatedSymbols
The JSON file list parser is used to communicate input to InstallAPI.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4