32#include "llvm/ADT/StringMap.h"
37using ::clang::ast_matchers::MatchFinder;
44 while (!NamespaceNames.empty() && NS) {
45 if (NS->
getName() != NamespaceNames.consume_back())
47 NS = dyn_cast_or_null<NamespaceDecl>(NS->
getParent());
49 return NamespaceNames.empty() && !NS;
58 if (RD->getName() == Name)
59 if (
const auto *N = dyn_cast_or_null<NamespaceDecl>(RD->getDeclContext()))
65 return isTypeNamed(
Type, {
"absl",
"internal_statusor"},
"OperatorBase");
74 return OkVal !=
nullptr && Env.
proves(OkVal->formula());
87 if (!RD->hasDefinition())
89 for (
const auto &
Base : RD->bases())
101 return ofClass(
hasName(
"::absl::Status"));
161 "::absl::AbortedError",
"::absl::AlreadyExistsError",
162 "::absl::CancelledError",
"::absl::DataLossError",
163 "::absl::DeadlineExceededError",
"::absl::FailedPreconditionError",
164 "::absl::InternalError",
"::absl::InvalidArgumentError",
165 "::absl::NotFoundError",
"::absl::OutOfRangeError",
166 "::absl::PermissionDeniedError",
"::absl::ResourceExhaustedError",
167 "::absl::UnauthenticatedError",
"::absl::UnavailableError",
168 "::absl::UnimplementedError",
"::absl::UnknownError"))));
189 hasArgument(1,
anyOf(hasType(hasUnqualifiedDesugaredType(
190 type(equalsBoundNode(
"T")))),
191 nullPointerConstant())));
199 anyOf(hasType(hasCanonicalType(
type(equalsBoundNode(
"T")))),
200 nullPointerConstant(),
202 "std::in_place_t"))))));
220 .CaseOfCFGStmt<CXXMemberCallExpr>(
231 .CaseOfCFGStmt<CXXOperatorCallExpr>(
253 return DiagnoseMatchSwitch(Elt, Ctx, State.Env);
272 hasTemplateArgument(0, refersToType(
type().bind(
"T"))));
283 hasName(
"absl::internal_statusor::OperatorBase"));
328 if (StatusOrLoc ==
nullptr)
332 State.Env.setValue(*
Expr, OkVal);
340 if (StatusOrLoc ==
nullptr)
345 if (State.Env.getValue(
locForOk(StatusLoc)) ==
nullptr)
349 copyRecord(StatusLoc, State.Env.getResultObjectLocation(*
Expr), State.Env);
351 State.Env.setStorageLocation(*
Expr, StatusLoc);
359 if (StatusLoc ==
nullptr)
363 State.Env.setValue(*
Expr, *Val);
371 assert(
Expr->getNumArgs() == 1);
372 auto *Arg =
Expr->getArg(0);
374 Arg->isPRValue() ? &State.Env.getResultObjectLocation(*Arg)
377 if (ThisLoc ==
nullptr || ArgRecord ==
nullptr)
380 auto &ThisOkVal =
valForOk(*ThisLoc, State.Env);
381 auto &ArgOkVal =
valForOk(*ArgRecord, State.Env);
382 auto &A = State.Env.arena();
383 auto &NewVal = State.Env.makeAtomicBoolValue();
384 State.Env.assume(A.makeImplies(A.makeNot(ThisOkVal.formula()),
385 A.makeNot(NewVal.formula())));
386 State.Env.assume(A.makeImplies(NewVal.formula(), ArgOkVal.formula()));
387 State.Env.setValue(
locForOk(*ThisLoc), NewVal);
393 auto &A = Env.
arena();
403 auto &LhsOkVal =
valForOk(LhsStatusLoc, Env);
404 auto &RhsOkVal =
valForOk(RhsStatusLoc, Env);
409 Env.
assume(A.makeImplies(A.makeAnd(LhsOkVal.formula(), RhsOkVal.formula()),
413 Res.formula(), A.makeEquals(LhsOkVal.formula(), RhsOkVal.formula())));
422 auto &A = Env.
arena();
438 res.formula(), A.makeEquals(LhsOkVal.formula(), RhsOkVal.formula())));
449 if (LhsStatusOrLoc ==
nullptr)
452 if (RhsStatusOrLoc ==
nullptr)
459 if (LhsStatusLoc ==
nullptr)
463 if (RhsStatusLoc ==
nullptr)
476 if (LhsAndRhsVal ==
nullptr)
480 State.Env.setValue(*
Expr, State.Env.makeNot(*LhsAndRhsVal));
482 State.Env.setValue(*
Expr, *LhsAndRhsVal);
488 return dyn_cast<RecordStorageLocation>(&PointerVal->getPointeeLoc());
503 if (LhsStatusOrLoc ==
nullptr || RhsStatusOrLoc ==
nullptr)
512 if (LhsStatusLoc ==
nullptr || RhsStatusLoc ==
nullptr)
514 auto &LhsOkVal =
valForOk(*LhsStatusLoc, Env);
515 auto &RhsOkVal =
valForOk(*RhsStatusLoc, Env);
517 auto &A = Env.
arena();
519 Res.formula(), A.makeEquals(LhsOkVal.formula(), RhsOkVal.formula())));
528 if (LhsAndRhsVal ==
nullptr)
532 State.Env.setValue(*
Expr, State.Env.makeNot(*LhsAndRhsVal));
534 State.Env.setValue(*
Expr, *LhsAndRhsVal);
542 State.Env.assume(OkVal.formula());
550 auto &A = State.Env.arena();
551 State.Env.assume(A.makeNot(OkVal.formula()));
559 if (StatusOrLoc ==
nullptr)
563 State.Env.assume(OkVal.formula());
569 assert(
Expr->getNumArgs() > 1);
572 if (StatusOrLoc ==
nullptr)
576 State.Env.assume(OkVal.formula());
584 State.Env.assume(OkVal.formula());
593 if (State.Env.getValue(
locForOk(StatusLoc)) ==
nullptr)
602 if (State.Env.getValue(
locForOk(StatusLoc)) ==
nullptr)
610 return std::move(Builder)
626 .CaseOfCFGStmt<CXXOperatorCallExpr>(
633 .CaseOfCFGStmt<BinaryOperator>(
640 .CaseOfCFGStmt<BinaryOperator>(
682 Env.getDataflowAnalysisContext().setSyntheticFieldCallback(
683 [StatusType](
QualType Ty) -> llvm::StringMap<QualType> {
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::SourceLocation class and associated facilities.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const SmallVectorImpl< Type * > & getTypes() const
A builtin binary operation expression such as "x + y" or "x <= y".
Represents a top-level expression in a basic block.
Represents a call to a C++ constructor.
Represents a call to a member function that may be written either with member call syntax (e....
SourceLocation getExprLoc() const LLVM_READONLY
A call to an overloaded operator written using operator syntax.
Represents a C++ struct/union/class.
bool hasDefinition() const
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Represents a class template specialization, which refers to a class template with a given set of temp...
const TemplateArgumentList & getTemplateArgs() const
Retrieve the template arguments of the class template specialization.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
ASTContext & getASTContext() const LLVM_READONLY
This represents one expression.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represent a C++ namespace.
A (possibly-)qualified type.
const TemplateArgument & get(unsigned Idx) const
Retrieve the template argument at a given index.
QualType getAsType() const
Retrieve the type for a type template argument.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Collects cases of a "match switch": a collection of matchers paired with callbacks,...
ASTContext & getASTContext() final
DataflowAnalysis(ASTContext &Context)
Holds the state of the program (store and heap) at a given program point.
BoolValue & makeAtomicBoolValue() const
Returns an atomic boolean value.
bool proves(const Formula &) const
Returns true if the formula is always true when this point is reached.
void assume(const Formula &)
Record a fact that must be true if this point in the program is reached.
void setValue(const StorageLocation &Loc, Value &Val)
Assigns Val as the value of Loc in the environment.
std::enable_if_t< std::is_base_of_v< StorageLocation, T >, T * > get(const ValueDecl &D) const
Returns the result of casting getStorageLocation(...) to a subclass of StorageLocation (using cast_or...
Models a symbolic pointer. Specifically, any value of type T*.
A storage location for a record (struct, class, or union).
StorageLocation & getSyntheticField(llvm::StringRef Name) const
Returns the storage location for the synthetic field Name.
Base class for elements of the local variable store and of the heap.
Base class for all values computed by abstract interpretation.
UncheckedStatusOrAccessDiagnoser(UncheckedStatusOrAccessModelOptions Options={})
llvm::SmallVector< SourceLocation > operator()(const CFGElement &Elt, ASTContext &Ctx, const TransferStateForDiagnostics< UncheckedStatusOrAccessModel::Lattice > &State)
UncheckedStatusOrAccessModel(ASTContext &Ctx, Environment &Env)
void transfer(const CFGElement &Elt, Lattice &L, Environment &Env)
internal::Matcher< QualType > TypeMatcher
const internal::VariadicOperatorMatcherFunc< 1, 1 > unless
Matches if the provided matcher does not match.
internal::Matcher< Decl > DeclarationMatcher
Types of matchers for the top-level classes in the AST class hierarchy.
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
const internal::VariadicDynCastAllOfMatcher< Decl, NamedDecl > namedDecl
Matches a declaration of anything that could have a name.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicFunction< internal::Matcher< NamedDecl >, StringRef, internal::hasAnyNameFunc > hasAnyName
Matches NamedDecl nodes that have any of the specified names.
internal::Matcher< Stmt > StatementMatcher
const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator > binaryOperator
Matches binary operator expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXConstructExpr > cxxConstructExpr
Matches constructor call expressions (including implicit ones).
const internal::VariadicDynCastAllOfMatcher< Decl, ClassTemplateSpecializationDecl > classTemplateSpecializationDecl
Matches C++ class template specializations.
const internal::VariadicDynCastAllOfMatcher< Decl, FunctionDecl > functionDecl
Matches function declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
internal::PolymorphicMatcher< internal::HasDeclarationMatcher, void(internal::HasDeclarationSupportedTypes), internal::Matcher< Decl > > hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> anyOf
Matches if any of the given matchers matches.
const internal::VariadicAllOfMatcher< QualType > qualType
Matches QualTypes in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXThisExpr > cxxThisExpr
Matches implicit and explicit this expressions.
static void transferValueAssignmentCall(const CXXOperatorCallExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
TransferState< UncheckedStatusOrAccessModel::Lattice > LatticeTransferState
static ClassTemplateSpecializationDecl * getStatusOrBaseClass(const QualType &Ty)
static bool isStatusOrOperatorBaseType(QualType Type)
static auto isStatusMemberCallWithName(llvm::StringRef member_name)
static auto buildDiagnoseMatchSwitch(const UncheckedStatusOrAccessModelOptions &Options)
static auto isStatusOrValueConstructor()
static auto isComparisonOperatorCall(llvm::StringRef operator_name)
RecordStorageLocation & locForStatus(RecordStorageLocation &StatusOrLoc)
static void transferNotOkStatusCall(const CallExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
static BoolValue * evaluateStatusEquality(RecordStorageLocation &LhsStatusLoc, RecordStorageLocation &RhsStatusLoc, Environment &Env)
static void transferStatusConstructor(const CXXConstructExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
static BoolValue * evaluateStatusOrEquality(RecordStorageLocation &LhsStatusOrLoc, RecordStorageLocation &RhsStatusOrLoc, Environment &Env)
static auto isStatusOrOperatorCallWithName(llvm::StringRef operator_name)
static void transferValueConstructor(const CXXConstructExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
static auto isOkStatusCall()
static void transferComparisonOperator(const CXXOperatorCallExpr *Expr, LatticeTransferState &State, bool IsNegative)
clang::ast_matchers::DeclarationMatcher statusOrClass()
static void transferOkStatusCall(const CallExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
static auto isPointerComparisonOperatorCall(std::string operator_name)
clang::ast_matchers::TypeMatcher statusOrType()
static auto isStatusConstructor()
static bool isSafeUnwrap(RecordStorageLocation *StatusOrLoc, const Environment &Env)
static void transferPointerComparisonOperator(const BinaryOperator *Expr, LatticeTransferState &State, bool IsNegative)
static void transferStatusOrOkCall(const CXXMemberCallExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
static bool namespaceEquals(const NamespaceDecl *NS, clang::ArrayRef< clang::StringRef > NamespaceNames)
static bool isTypeNamed(QualType Type, clang::ArrayRef< clang::StringRef > NS, StringRef Name)
static void transferStatusOrConstructor(const CXXConstructExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
static auto valueOperatorCall()
clang::ast_matchers::DeclarationMatcher statusClass()
static auto ofClassStatus()
BoolValue & initializeStatusOr(RecordStorageLocation &StatusOrLoc, Environment &Env)
QualType findStatusType(const ASTContext &Ctx)
BoolValue & initializeStatus(RecordStorageLocation &StatusLoc, Environment &Env)
llvm::StringMap< QualType > getSyntheticFields(QualType Ty, QualType StatusType, const CXXRecordDecl &RD)
StorageLocation & locForOk(RecordStorageLocation &StatusLoc)
static auto isStatusOrMemberCallWithName(llvm::StringRef member_name)
static BoolValue * evaluateEquality(const Expr *LhsExpr, const Expr *RhsExpr, Environment &Env)
static void transferStatusCall(const CXXMemberCallExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
static clang::ast_matchers::TypeMatcher statusType()
static void transferStatusOkCall(const CXXMemberCallExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
static void transferEmplaceCall(const CXXMemberCallExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
static auto isStatusOrValueAssignmentCall()
static auto isStatusOrConstructor()
static BoolValue * evaluatePointerEquality(const Expr *LhsExpr, const Expr *RhsExpr, Environment &Env)
static QualType getStatusOrValueType(ClassTemplateSpecializationDecl *TRD)
static RecordStorageLocation * getPointeeLocation(const Expr &Expr, Environment &Env)
BoolValue & valForOk(RecordStorageLocation &StatusLoc, Environment &Env)
bool isStatusOrType(QualType Type)
static auto isNotOkStatusCall()
static void transferStatusUpdateCall(const CXXMemberCallExpr *Expr, const MatchFinder::MatchResult &, LatticeTransferState &State)
CFGMatchSwitch< LatticeTransferState > buildTransferMatchSwitch(ASTContext &Ctx, CFGMatchSwitchBuilder< LatticeTransferState > Builder)
bool isStatusType(QualType Type)
clang::ast_matchers::DeclarationMatcher statusOrOperatorBaseClass()
void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst, Environment &Env, QualType TypeToCopy=QualType())
Copies a record (struct, class, or union) from Src to Dst.
internal::Matcher< NamedDecl > hasName(StringRef Name)
Matches NamedDecl nodes that have the specified name.
std::function< Result(const CFGElement &, ASTContext &, State &)> CFGMatchSwitch
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXMemberCallExpr > cxxMemberCallExpr
Matches member call expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXOperatorCallExpr > cxxOperatorCallExpr
Matches overloaded operator calls.
const AstTypeMatcher< PointerType > pointerType
internal::PolymorphicMatcher< internal::HasOverloadedOperatorNameMatcher, AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl), std::vector< std::string > > hasOverloadedOperatorName(StringRef Name)
Matches overloaded operator names.
RecordStorageLocation * getImplicitObjectLocation(const CXXMemberCallExpr &MCE, const Environment &Env)
Returns the storage location for the implicit object of a CXXMemberCallExpr, or null if none is defin...
const internal::VariadicDynCastAllOfMatcher< Decl, CXXMethodDecl > cxxMethodDecl
Matches method declarations.
U cast(CodeGen::Address addr)
Contains all information for a given match.
A read-only version of TransferState.
Contains all information for a given match.