22#include "llvm/Support/raw_ostream.h"
93class GTestChecker :
public Checker<check::PostCall> {
95 mutable IdentifierInfo *AssertionResultII =
nullptr;
96 mutable IdentifierInfo *SuccessII =
nullptr;
99 GTestChecker() =
default;
101 void checkPostCall(
const CallEvent &
Call, CheckerContext &
C)
const;
104 void modelAssertionResultBoolConstructor(
const CXXConstructorCall *
Call,
105 bool IsRef, CheckerContext &
C)
const;
107 void modelAssertionResultCopyConstructor(
const CXXConstructorCall *
Call,
108 CheckerContext &
C)
const;
110 void initIdentifierInfo(ASTContext &Ctx)
const;
113 getAssertionResultSuccessFieldValue(
const CXXRecordDecl *AssertionResultDecl,
129void GTestChecker::modelAssertionResultBoolConstructor(
131 assert(
Call->getNumArgs() >= 1 &&
Call->getNumArgs() <= 2);
134 SVal BooleanArgVal =
Call->getArgSVal(0);
139 BooleanArgVal =
C.getState()->getSVal(BooleanArgVal.
castAs<Loc>());
142 SVal ThisVal =
Call->getCXXThisVal();
144 SVal ThisSuccess = getAssertionResultSuccessFieldValue(
145 Call->getDecl()->getParent(), ThisVal, State);
147 State = assumeValuesEqual(ThisSuccess, BooleanArgVal, State,
C);
148 C.addTransition(State);
158void GTestChecker::modelAssertionResultCopyConstructor(
159 const CXXConstructorCall *
Call, CheckerContext &
C)
const {
160 assert(
Call->getNumArgs() == 1);
164 SVal OtherVal =
Call->getArgSVal(0);
165 SVal ThisVal =
Call->getCXXThisVal();
167 const CXXRecordDecl *AssertResultClassDecl =
Call->getDecl()->getParent();
170 SVal ThisSuccess = getAssertionResultSuccessFieldValue(AssertResultClassDecl,
172 SVal OtherSuccess = getAssertionResultSuccessFieldValue(AssertResultClassDecl,
175 State = assumeValuesEqual(ThisSuccess, OtherSuccess, State,
C);
176 C.addTransition(State);
180void GTestChecker::checkPostCall(
const CallEvent &
Call,
181 CheckerContext &
C)
const {
186 initIdentifierInfo(
C.getASTContext());
188 auto *CtorCall = dyn_cast<CXXConstructorCall>(&
Call);
192 const CXXConstructorDecl *CtorDecl = CtorCall->getDecl();
193 const CXXRecordDecl *CtorParent = CtorDecl->
getParent();
204 modelAssertionResultCopyConstructor(CtorCall,
C);
224 modelAssertionResultBoolConstructor(CtorCall,
false,
C);
227 if (ParamCount == 2){
230 RefTy->getPointeeType()->getCanonicalTypeUnqualified() == BoolTy) {
232 modelAssertionResultBoolConstructor(CtorCall,
true,
C);
238void GTestChecker::initIdentifierInfo(ASTContext &Ctx)
const {
239 if (AssertionResultII)
242 AssertionResultII = &Ctx.
Idents.
get(
"AssertionResult");
248SVal GTestChecker::getAssertionResultSuccessFieldValue(
249 const CXXRecordDecl *AssertionResultDecl, SVal Instance,
256 auto *SuccessField = dyn_cast<FieldDecl>(
Result.front());
260 std::optional<Loc> FieldLoc =
261 State->getLValue(SuccessField, Instance).getAs<Loc>();
265 return State->getSVal(*FieldLoc);
272 auto DVal1 = Val1.
getAs<DefinedOrUnknownSVal>();
273 auto DVal2 = Val2.
getAs<DefinedOrUnknownSVal>();
274 if (!DVal1 || !DVal2)
278 C.getSValBuilder().evalEQ(State, *DVal1, *DVal2).getAs<DefinedSVal>();
282 State =
C.getConstraintManager().assume(State, *ValuesEqual,
true);
286void ento::registerGTestChecker(CheckerManager &Mgr) {
290bool ento::shouldRegisterGTestChecker(
const CheckerManager &mgr) {
Defines the clang::LangOptions interface.
bool isCopyConstructor(unsigned &TypeQuals) const
Whether this constructor is a copy constructor (C++ [class.copy]p2, which can be used to copy the cla...
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
DeclContextLookupResult lookup_result
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
const ParmVarDecl * getParamDecl(unsigned i) const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
const T * getAs() const
Member-template getAs<specific type>'.
Represents a call to a C++ constructor.
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
const LangOptions & getLangOpts() const
Simple checker classes that implement one frontend (i.e.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
@ Result
The result type of a method or function.