#include "clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Stmt.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/Formula.h"
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <memory>
#include <optional>
#include <utility>
namespace clang {
namespace dataflow {
template <class... NameTypes>
static bool isFullyQualifiedNamespaceEqualTo(const NamespaceDecl &NS,
llvm::StringRef Name,
NameTypes... Names) { … }
static bool hasOptionalClassName(const CXXRecordDecl &RD) { … }
static const CXXRecordDecl *getOptionalBaseClass(const CXXRecordDecl *RD) { … }
namespace {
usingnamespace::clang::ast_matchers;
LatticeTransferState;
AST_MATCHER(CXXRecordDecl, optionalClass) { … }
AST_MATCHER(CXXRecordDecl, optionalOrDerivedClass) { … }
auto desugarsToOptionalType() { … }
auto desugarsToOptionalOrDerivedType() { … }
auto hasOptionalType() { … }
auto hasOptionalOrDerivedType() { … }
QualType getPublicType(const Expr *E) { … }
QualType getPublicReceiverType(const CXXMemberCallExpr &MCE) { … }
AST_MATCHER_P(CXXMemberCallExpr, publicReceiverType,
ast_matchers::internal::Matcher<QualType>, InnerMatcher) { … }
auto isOptionalMemberCallWithNameMatcher(
ast_matchers::internal::Matcher<NamedDecl> matcher,
const std::optional<StatementMatcher> &Ignorable = std::nullopt) { … }
auto isOptionalOperatorCallWithName(
llvm::StringRef operator_name,
const std::optional<StatementMatcher> &Ignorable = std::nullopt) { … }
auto isMakeOptionalCall() { … }
auto nulloptTypeDecl() { … }
auto hasNulloptType() { … }
auto inPlaceClass() { … }
auto isOptionalNulloptConstructor() { … }
auto isOptionalInPlaceConstructor() { … }
auto isOptionalValueOrConversionConstructor() { … }
auto isOptionalValueOrConversionAssignment() { … }
auto isOptionalNulloptAssignment() { … }
auto isStdSwapCall() { … }
auto isStdForwardCall() { … }
constexpr llvm::StringLiteral ValueOrCallID = …;
auto isValueOrStringEmptyCall() { … }
auto isValueOrNotEqX() { … }
auto isCallReturningOptional() { … }
template <typename L, typename R>
auto isComparisonOperatorCall(L lhs_arg_matcher, R rhs_arg_matcher) { … }
const Formula &forceBoolValue(Environment &Env, const Expr &Expr) { … }
StorageLocation &locForHasValue(const RecordStorageLocation &OptionalLoc) { … }
StorageLocation &locForValue(const RecordStorageLocation &OptionalLoc) { … }
void setHasValue(RecordStorageLocation &OptionalLoc, BoolValue &HasValueVal,
Environment &Env) { … }
BoolValue *getHasValue(Environment &Env, RecordStorageLocation *OptionalLoc) { … }
QualType valueTypeFromOptionalDecl(const CXXRecordDecl &RD) { … }
int countOptionalWrappers(const ASTContext &ASTCtx, QualType Type) { … }
StorageLocation *getLocBehindPossiblePointer(const Expr &E,
const Environment &Env) { … }
void transferUnwrapCall(const Expr *UnwrapExpr, const Expr *ObjectExpr,
LatticeTransferState &State) { … }
void transferArrowOpCall(const Expr *UnwrapExpr, const Expr *ObjectExpr,
LatticeTransferState &State) { … }
void transferMakeOptionalCall(const CallExpr *E,
const MatchFinder::MatchResult &,
LatticeTransferState &State) { … }
void transferOptionalHasValueCall(const CXXMemberCallExpr *CallExpr,
const MatchFinder::MatchResult &,
LatticeTransferState &State) { … }
void transferOptionalIsNullCall(const CXXMemberCallExpr *CallExpr,
const MatchFinder::MatchResult &,
LatticeTransferState &State) { … }
void transferValueOrImpl(
const clang::Expr *ValueOrPredExpr, const MatchFinder::MatchResult &Result,
LatticeTransferState &State,
const Formula &(*ModelPred)(Environment &Env, const Formula &ExprVal,
const Formula &HasValueVal)) { … }
void transferValueOrStringEmptyCall(const clang::Expr *ComparisonExpr,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) { … }
void transferValueOrNotEqX(const Expr *ComparisonExpr,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) { … }
void transferCallReturningOptional(const CallExpr *E,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) { … }
void constructOptionalValue(const Expr &E, Environment &Env,
BoolValue &HasValueVal) { … }
BoolValue &valueOrConversionHasValue(QualType DestType, const Expr &E,
const MatchFinder::MatchResult &MatchRes,
LatticeTransferState &State) { … }
void transferValueOrConversionConstructor(
const CXXConstructExpr *E, const MatchFinder::MatchResult &MatchRes,
LatticeTransferState &State) { … }
void transferAssignment(const CXXOperatorCallExpr *E, BoolValue &HasValueVal,
LatticeTransferState &State) { … }
void transferValueOrConversionAssignment(
const CXXOperatorCallExpr *E, const MatchFinder::MatchResult &MatchRes,
LatticeTransferState &State) { … }
void transferNulloptAssignment(const CXXOperatorCallExpr *E,
const MatchFinder::MatchResult &,
LatticeTransferState &State) { … }
void transferSwap(RecordStorageLocation *Loc1, RecordStorageLocation *Loc2,
Environment &Env) { … }
void transferSwapCall(const CXXMemberCallExpr *E,
const MatchFinder::MatchResult &,
LatticeTransferState &State) { … }
void transferStdSwapCall(const CallExpr *E, const MatchFinder::MatchResult &,
LatticeTransferState &State) { … }
void transferStdForwardCall(const CallExpr *E, const MatchFinder::MatchResult &,
LatticeTransferState &State) { … }
const Formula &evaluateEquality(Arena &A, const Formula &EqVal,
const Formula &LHS, const Formula &RHS) { … }
void transferOptionalAndOptionalCmp(const clang::CXXOperatorCallExpr *CmpExpr,
const MatchFinder::MatchResult &,
LatticeTransferState &State) { … }
void transferOptionalAndValueCmp(const clang::CXXOperatorCallExpr *CmpExpr,
const clang::Expr *E, Environment &Env) { … }
void transferOptionalAndNulloptCmp(const clang::CXXOperatorCallExpr *CmpExpr,
const clang::Expr *E, Environment &Env) { … }
std::optional<StatementMatcher>
ignorableOptional(const UncheckedOptionalAccessModelOptions &Options) { … }
StatementMatcher
valueCall(const std::optional<StatementMatcher> &IgnorableOptional) { … }
StatementMatcher
valueOperatorCall(const std::optional<StatementMatcher> &IgnorableOptional) { … }
auto buildTransferMatchSwitch() { … }
llvm::SmallVector<SourceLocation> diagnoseUnwrapCall(const Expr *ObjectExpr,
const Environment &Env) { … }
auto buildDiagnoseMatchSwitch(
const UncheckedOptionalAccessModelOptions &Options) { … }
}
ast_matchers::DeclarationMatcher
UncheckedOptionalAccessModel::optionalClassDecl() { … }
UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(ASTContext &Ctx,
Environment &Env)
: … { … }
void UncheckedOptionalAccessModel::transfer(const CFGElement &Elt,
NoopLattice &L, Environment &Env) { … }
UncheckedOptionalAccessDiagnoser::UncheckedOptionalAccessDiagnoser(
UncheckedOptionalAccessModelOptions Options)
: … { … }
}
}