A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://clang.llvm.org/doxygen/UncheckedOptionalAccessModel_8cpp_source.html below:

clang: lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp Source File

33#include "llvm/ADT/StringRef.h" 34#include "llvm/Support/Casting.h" 35#include "llvm/Support/ErrorHandling.h" 46template

<

class

... NameTypes>

54 if constexpr

(

sizeof

...(NameTypes) > 0) {

57 if

(

const auto

*NextNS = dyn_cast_or_null<NamespaceDecl>(NS.

getParent

()))

69 if

(RD.

getName

() ==

"optional"

) {

70 if

(

const auto

*N = dyn_cast_or_null<NamespaceDecl>(RD.

getDeclContext

()))

71 return

N->isStdNamespace() ||

77 if

(RD.

getName

() ==

"Optional"

) {

79 const auto

*N = dyn_cast_or_null<NamespaceDecl>(RD.

getDeclContext

());

84 if

(RD.

getName

() ==

"NullableValue"

) {

85 const auto

*N = dyn_cast_or_null<NamespaceDecl>(RD.

getDeclContext

());

86 return

N !=

nullptr

&&

120using

LatticeTransferState = TransferState<UncheckedOptionalAccessLattice>;

124AST_MATCHER

(CXXRecordDecl, optionalOrDerivedClass) {

128auto

desugarsToOptionalType() {

129 return

hasUnqualifiedDesugaredType(

133auto

desugarsToOptionalOrDerivedType() {

134 return

hasUnqualifiedDesugaredType(

138auto

hasOptionalType() {

return

hasType(desugarsToOptionalType()); }

142auto

hasOptionalOrDerivedType() {

143 return

hasType(desugarsToOptionalOrDerivedType());

146

QualType getPublicType(

const

Expr *

E

) {

147 auto

*

Cast

= dyn_cast<ImplicitCastExpr>(

E

->IgnoreParens());

148 if

(Cast ==

nullptr

||

Cast

->getCastKind() != CK_UncheckedDerivedToBase) {

149

QualType Ty =

E

->getType();

150 if

(Ty->isPointerType())

151 return

Ty->getPointeeType();

158 bool

CastingFromThis = isa<CXXThisExpr>(

Cast

->getSubExpr());

162 const

CXXBaseSpecifier *PublicBase =

nullptr

;

163 for

(

const

CXXBaseSpecifier *

Base

:

Cast

->path()) {

164 if

(

Base

->getAccessSpecifier() !=

AS_public

&& !CastingFromThis)

167

CastingFromThis =

false

;

170 if

(PublicBase !=

nullptr

)

171 return

PublicBase->getType();

176 return

getPublicType(

Cast

->getSubExpr());

203

QualType getPublicReceiverType(

const

CXXMemberCallExpr &MCE) {

204 return

getPublicType(MCE.getImplicitObjectArgument());

208

ast_matchers::internal::Matcher<QualType>, InnerMatcher) {

209 return

InnerMatcher.matches(getPublicReceiverType(

Node

), Finder, Builder);

212auto

isOptionalMemberCallWithNameMatcher(

213

ast_matchers::internal::Matcher<NamedDecl> matcher,

214 const

std::optional<StatementMatcher> &Ignorable = std::nullopt) {

217

publicReceiverType(desugarsToOptionalType()),

221auto

isOptionalOperatorCallWithName(

222

llvm::StringRef operator_name,

223 const

std::optional<StatementMatcher> &Ignorable = std::nullopt) {

230auto

isMakeOptionalCall() {

233 "std::make_optional"

,

"base::make_optional"

,

"absl::make_optional"

,

234 "folly::make_optional"

,

"bsl::make_optional"

))),

238auto

nulloptTypeDecl() {

240 "base::nullopt_t"

,

"folly::None"

,

244auto

hasNulloptType() {

return

hasType(nulloptTypeDecl()); }

248 "base::in_place_t"

,

"folly::in_place_t"

,

249 "bsl::in_place_t"

));

252auto

isOptionalNulloptConstructor() {

255

hasParameter(0, hasNulloptType()))),

256

hasOptionalOrDerivedType());

259auto

isOptionalInPlaceConstructor() {

261

hasOptionalOrDerivedType());

264auto

isOptionalValueOrConversionConstructor() {

268

argumentCountIs(1), hasArgument(0,

unless

(hasNulloptType())),

269

hasOptionalOrDerivedType());

272auto

isOptionalValueOrConversionAssignment() {

277 anyOf

(isCopyAssignmentOperator(), isMoveAssignmentOperator())))),

278

argumentCountIs(2), hasArgument(1,

unless

(hasNulloptType())));

281auto

isOptionalNulloptAssignment() {

285

argumentCountIs(2), hasArgument(1, hasNulloptType()));

288auto

isStdSwapCall() {

291

hasArgument(0, hasOptionalOrDerivedType()),

292

hasArgument(1, hasOptionalOrDerivedType()));

295auto

isStdForwardCall() {

298

hasArgument(0, hasOptionalOrDerivedType()));

301constexpr

llvm::StringLiteral ValueOrCallID =

"ValueOrCall"

;

303auto

isValueOrStringEmptyCall() {

307

onImplicitObjectArgument(ignoringImplicit(

310

ofClass(optionalClass()))),

312

.bind(ValueOrCallID))));

315auto

isValueOrNotEqX() {

316 auto

ComparesToSame = [](ast_matchers::internal::Matcher<Stmt> Arg) {

321

ofClass(optionalClass()))),

323

.bind(ValueOrCallID)),

324

ignoringImplicit(Arg));

338auto

isZeroParamConstMemberCall() {

343auto

isZeroParamConstMemberOperatorCall() {

348auto

isNonConstMemberCall() {

352auto

isNonConstMemberOperatorCall() {

356auto

isCallReturningOptional() {

358 anyOf

(desugarsToOptionalOrDerivedType(),

359 referenceType

(pointee(desugarsToOptionalOrDerivedType()))))));

362template

<

typename

L,

typename

R>

363auto

isComparisonOperatorCall(L lhs_arg_matcher, R rhs_arg_matcher) {

366

argumentCountIs(2), hasArgument(0, lhs_arg_matcher),

367

hasArgument(1, rhs_arg_matcher));

371const

Formula &forceBoolValue(Environment &

Env

,

const

Expr &Expr) {

373 if

(

Value

!=

nullptr

)

374 return Value

->formula();

378 return Value

->formula();

381

StorageLocation &locForHasValue(

const

RecordStorageLocation &OptionalLoc) {

382 return

OptionalLoc.getSyntheticField(

"has_value"

);

385

StorageLocation &locForValue(

const

RecordStorageLocation &OptionalLoc) {

386 return

OptionalLoc.getSyntheticField(

"value"

);

391void

setHasValue(RecordStorageLocation &OptionalLoc, BoolValue &HasValueVal,

392

Environment &

Env

) {

393 Env

.

setValue

(locForHasValue(OptionalLoc), HasValueVal);

398

BoolValue *getHasValue(Environment &

Env

, RecordStorageLocation *OptionalLoc) {

399 if

(OptionalLoc ==

nullptr

)

401

StorageLocation &HasValueLoc = locForHasValue(*OptionalLoc);

402 auto

*HasValueVal =

Env

.

get

<BoolValue>(HasValueLoc);

403 if

(HasValueVal ==

nullptr

) {

410

QualType valueTypeFromOptionalDecl(

const

CXXRecordDecl &RD) {

411 auto

&CTSD = cast<ClassTemplateSpecializationDecl>(RD);

412 return

CTSD.getTemplateArgs()[0].getAsType();

419int

countOptionalWrappers(

const

ASTContext &ASTCtx, QualType Type) {

424 return

1 + countOptionalWrappers(

426

valueTypeFromOptionalDecl(*Optional).getDesugaredType(ASTCtx));

429

StorageLocation *getLocBehindPossiblePointer(

const

Expr &

E

,

430 const

Environment &

Env

) {

431 if

(

E

.isPRValue()) {

432 if

(

auto

*PointerVal = dyn_cast_or_null<PointerValue>(

Env

.

getValue

(

E

)))

433 return

&PointerVal->getPointeeLoc();

439void

transferUnwrapCall(

const

Expr *UnwrapExpr,

const

Expr *ObjectExpr,

440

LatticeTransferState &State) {

441 if

(

auto

*OptionalLoc = cast_or_null<RecordStorageLocation>(

442

getLocBehindPossiblePointer(*ObjectExpr, State.Env))) {

443 if

(State.Env.getStorageLocation(*UnwrapExpr) ==

nullptr

)

444

State.Env.setStorageLocation(*UnwrapExpr, locForValue(*OptionalLoc));

448void

transferArrowOpCall(

const

Expr *UnwrapExpr,

const

Expr *ObjectExpr,

449

LatticeTransferState &State) {

450 if

(

auto

*OptionalLoc = cast_or_null<RecordStorageLocation>(

451

getLocBehindPossiblePointer(*ObjectExpr, State.Env)))

453

*UnwrapExpr, State.Env.create<PointerValue>(locForValue(*OptionalLoc)));

456void

transferMakeOptionalCall(

const

CallExpr *

E

,

457 const

MatchFinder::MatchResult &,

458

LatticeTransferState &State) {

459

setHasValue(State.Env.getResultObjectLocation(*

E

),

460

State.Env.getBoolLiteralValue(

true

), State.Env);

463void

transferOptionalHasValueCall(

const

CXXMemberCallExpr *CallExpr,

464 const

MatchFinder::MatchResult &,

465

LatticeTransferState &State) {

466 if

(

auto

*HasValueVal = getHasValue(

468

State.Env.setValue(*CallExpr, *HasValueVal);

472void

transferOptionalIsNullCall(

const

CXXMemberCallExpr *CallExpr,

473 const

MatchFinder::MatchResult &,

474

LatticeTransferState &State) {

475 if

(

auto

*HasValueVal = getHasValue(

477

State.Env.setValue(*CallExpr, State.Env.makeNot(*HasValueVal));

483void

transferValueOrImpl(

485

LatticeTransferState &State,

486 const

Formula &(*ModelPred)(Environment &

Env

,

const

Formula &ExprVal,

487 const

Formula &HasValueVal)) {

488 auto

&

Env

= State.Env;

495 if

(HasValueVal ==

nullptr

)

498 Env

.

assume

(ModelPred(

Env

, forceBoolValue(

Env

, *ValueOrPredExpr),

499

HasValueVal->formula()));

502void

transferValueOrStringEmptyCall(

const clang::Expr

*ComparisonExpr,

503 const

MatchFinder::MatchResult &

Result

,

504

LatticeTransferState &State) {

505 return

transferValueOrImpl(ComparisonExpr,

Result

, State,

506

[](Environment &

Env

,

const

Formula &ExprVal,

507 const

Formula &HasValueVal) ->

const

Formula & {

520void

transferValueOrNotEqX(

const

Expr *ComparisonExpr,

521 const

MatchFinder::MatchResult &

Result

,

522

LatticeTransferState &State) {

523

transferValueOrImpl(ComparisonExpr,

Result

, State,

524

[](Environment &

Env

,

const

Formula &ExprVal,

525 const

Formula &HasValueVal) ->

const

Formula & {

534void

transferCallReturningOptional(

const

CallExpr *

E

,

535 const

MatchFinder::MatchResult &

Result

,

536

LatticeTransferState &State) {

537

RecordStorageLocation *

Loc

=

nullptr

;

538 if

(

E

->isPRValue()) {

539 Loc

= &State.Env.getResultObjectLocation(*

E

);

541 Loc

= State.Env.get<RecordStorageLocation>(*E);

542 if

(

Loc

==

nullptr

) {

543 Loc

= &cast<RecordStorageLocation>(State.Env.createStorageLocation(*

E

));

544

State.Env.setStorageLocation(*

E

, *

Loc

);

548 if

(State.Env.getValue(locForHasValue(*

Loc

)) !=

nullptr

)

551

setHasValue(*

Loc

, State.Env.makeAtomicBoolValue(), State.Env);

554void

handleConstMemberCall(

const

CallExpr *CE,

555

dataflow::RecordStorageLocation *

RecordLoc

,

556 const

MatchFinder::MatchResult &

Result

,

557

LatticeTransferState &State) {

560 const

FunctionDecl *DirectCallee = CE->getDirectCallee();

561 if

(DirectCallee ==

nullptr

)

563

StorageLocation &

Loc

=

564

State.Lattice.getOrCreateConstMethodReturnStorageLocation(

565

*

RecordLoc

, DirectCallee, State.Env, [&](StorageLocation &

Loc

) {

566

setHasValue(cast<RecordStorageLocation>(Loc),

567

State.Env.makeAtomicBoolValue(), State.Env);

569 if

(CE->isGLValue()) {

572

State.Env.setStorageLocation(*CE,

Loc

);

577 auto

&ResultLoc = State.Env.getResultObjectLocation(*CE);

578 copyRecord

(cast<RecordStorageLocation>(

Loc

), ResultLoc, State.Env);

586

(CE->getType()->isBooleanType() || CE->getType()->isPointerType())) {

587 Value

*Val = State.Lattice.getOrCreateConstMethodReturnValue(*

RecordLoc

, CE,

591

State.Env.setValue(*CE, *Val);

598

transferCallReturningOptional(CE,

Result

, State);

602void

transferValue_ConstMemberCall(

const

CXXMemberCallExpr *MCE,

603 const

MatchFinder::MatchResult &

Result

,

604

LatticeTransferState &State) {

605

handleConstMemberCall(

609void

transferValue_ConstMemberOperatorCall(

610 const

CXXOperatorCallExpr *OCE,

const

MatchFinder::MatchResult &

Result

,

611

LatticeTransferState &State) {

612 auto

*

RecordLoc

= cast_or_null<dataflow::RecordStorageLocation>(

613

State.Env.getStorageLocation(*OCE->getArg(0)));

617void

handleNonConstMemberCall(

const

CallExpr *CE,

618

dataflow::RecordStorageLocation *

RecordLoc

,

619 const

MatchFinder::MatchResult &

Result

,

620

LatticeTransferState &State) {

625 for

(

const auto

&[Field, FieldLoc] :

RecordLoc

->children()) {

626

QualType FieldType =

Field

->getType();

627 if

(!FieldType.isConstQualified() &&

629 auto

*FieldRecordLoc = cast_or_null<RecordStorageLocation>(FieldLoc);

630 if

(FieldRecordLoc) {

631

setHasValue(*FieldRecordLoc, State.Env.makeAtomicBoolValue(),

636

State.Lattice.clearConstMethodReturnValues(*

RecordLoc

);

637

State.Lattice.clearConstMethodReturnStorageLocations(*

RecordLoc

);

642

transferCallReturningOptional(CE,

Result

, State);

646void

transferValue_NonConstMemberCall(

const

CXXMemberCallExpr *MCE,

647 const

MatchFinder::MatchResult &

Result

,

648

LatticeTransferState &State) {

649

handleNonConstMemberCall(

653void

transferValue_NonConstMemberOperatorCall(

654 const

CXXOperatorCallExpr *OCE,

const

MatchFinder::MatchResult &

Result

,

655

LatticeTransferState &State) {

656 auto

*

RecordLoc

= cast_or_null<dataflow::RecordStorageLocation>(

657

State.Env.getStorageLocation(*OCE->getArg(0)));

661void

constructOptionalValue(

const

Expr &

E

, Environment &

Env

,

662

BoolValue &HasValueVal) {

664

setHasValue(

Loc

, HasValueVal,

Env

);

670

BoolValue &valueOrConversionHasValue(QualType DestType,

const

Expr &

E

,

671 const

MatchFinder::MatchResult &MatchRes,

672

LatticeTransferState &State) {

673 const int

DestTypeOptionalWrappersCount =

674

countOptionalWrappers(*MatchRes.Context, DestType);

675 const int

ArgTypeOptionalWrappersCount = countOptionalWrappers(

676

*MatchRes.Context,

E

.getType().getNonReferenceType());

683 if

(DestTypeOptionalWrappersCount != ArgTypeOptionalWrappersCount)

684 return

State.Env.getBoolLiteralValue(

true

);

690 auto

*

Loc

= State.Env.get<RecordStorageLocation>(

E

);

691 if

(

auto

*HasValueVal = getHasValue(State.Env,

Loc

))

693 return

State.Env.makeAtomicBoolValue();

696void

transferValueOrConversionConstructor(

697 const

CXXConstructExpr *

E

,

const

MatchFinder::MatchResult &MatchRes,

698

LatticeTransferState &State) {

699

assert(

E

->getNumArgs() > 0);

701

constructOptionalValue(

703

valueOrConversionHasValue(

704 E

->getConstructor()->getThisType()->getPointeeType(), *

E

->getArg(0),

708void

transferAssignment(

const

CXXOperatorCallExpr *

E

, BoolValue &HasValueVal,

709

LatticeTransferState &State) {

710

assert(

E

->getNumArgs() > 0);

712 if

(

auto

*

Loc

= State.Env.get<RecordStorageLocation>(*

E

->getArg(0))) {

713

setHasValue(*

Loc

, HasValueVal, State.Env);

716

State.Env.setStorageLocation(*

E

, *

Loc

);

720void

transferValueOrConversionAssignment(

721 const

CXXOperatorCallExpr *

E

,

const

MatchFinder::MatchResult &MatchRes,

722

LatticeTransferState &State) {

723

assert(

E

->getNumArgs() > 1);

726

valueOrConversionHasValue(

E

->getArg(0)->getType().getNonReferenceType(),

727

*

E

->getArg(1), MatchRes, State),

731void

transferNulloptAssignment(

const

CXXOperatorCallExpr *

E

,

732 const

MatchFinder::MatchResult &,

733

LatticeTransferState &State) {

734

transferAssignment(

E

, State.Env.getBoolLiteralValue(

false

), State);

737void

transferSwap(RecordStorageLocation *Loc1, RecordStorageLocation *Loc2,

738

Environment &

Env

) {

743 if

(Loc1 ==

nullptr

) {

744 if

(Loc2 !=

nullptr

)

748 if

(Loc2 ==

nullptr

) {

759

BoolValue *BoolVal1 = getHasValue(

Env

, Loc1);

760 if

(BoolVal1 ==

nullptr

)

763

BoolValue *BoolVal2 = getHasValue(

Env

, Loc2);

764 if

(BoolVal2 ==

nullptr

)

767

setHasValue(*Loc1, *BoolVal2,

Env

);

768

setHasValue(*Loc2, *BoolVal1,

Env

);

771void

transferSwapCall(

const

CXXMemberCallExpr *

E

,

772 const

MatchFinder::MatchResult &,

773

LatticeTransferState &State) {

774

assert(

E

->getNumArgs() == 1);

775 auto

*OtherLoc = State.Env.get<RecordStorageLocation>(*

E

->getArg(0));

779void

transferStdSwapCall(

const

CallExpr *

E

,

const

MatchFinder::MatchResult &,

780

LatticeTransferState &State) {

781

assert(

E

->getNumArgs() == 2);

782 auto

*Arg0Loc = State.Env.get<RecordStorageLocation>(*

E

->getArg(0));

783 auto

*Arg1Loc = State.Env.get<RecordStorageLocation>(*

E

->getArg(1));

784

transferSwap(Arg0Loc, Arg1Loc, State.Env);

787void

transferStdForwardCall(

const

CallExpr *

E

,

const

MatchFinder::MatchResult &,

788

LatticeTransferState &State) {

789

assert(

E

->getNumArgs() == 1);

791 if

(

auto

*

Loc

= State.Env.getStorageLocation(*

E

->getArg(0)))

792

State.Env.setStorageLocation(*

E

, *

Loc

);

795const

Formula &evaluateEquality(Arena &A,

const

Formula &EqVal,

796 const

Formula &LHS,

const

Formula &RHS) {

812

A.makeImplies(EqVal, A.makeOr(A.makeAnd(LHS, RHS),

813

A.makeAnd(A.makeNot(LHS), A.makeNot(RHS)))),

814

A.makeImplies(A.makeNot(EqVal), A.makeOr(LHS, RHS)));

818 const

MatchFinder::MatchResult &,

819

LatticeTransferState &State) {

820

Environment &

Env

= State.Env;

822 auto

*CmpValue = &forceBoolValue(

Env

, *CmpExpr);

823 auto

*Arg0Loc =

Env

.

get

<RecordStorageLocation>(*CmpExpr->

getArg

(0));

824 if

(

auto

*LHasVal = getHasValue(

Env

, Arg0Loc)) {

825 auto

*Arg1Loc =

Env

.

get

<RecordStorageLocation>(*CmpExpr->

getArg

(1));

826 if

(

auto

*RHasVal = getHasValue(

Env

, Arg1Loc)) {

827 if

(CmpExpr->

getOperator

() == clang::OO_ExclaimEqual)

828

CmpValue = &A.makeNot(*CmpValue);

829 Env

.

assume

(evaluateEquality(A, *CmpValue, LHasVal->formula(),

830

RHasVal->formula()));

838 auto

*CmpValue = &forceBoolValue(

Env

, *CmpExpr);

839 auto

*

Loc

=

Env

.

get

<RecordStorageLocation>(*E);

840 if

(

auto

*HasVal = getHasValue(

Env

,

Loc

)) {

841 if

(CmpExpr->

getOperator

() == clang::OO_ExclaimEqual)

842

CmpValue = &A.makeNot(*CmpValue);

844

evaluateEquality(A, *CmpValue, HasVal->formula(), A.makeLiteral(

true

)));

851 auto

*CmpValue = &forceBoolValue(

Env

, *CmpExpr);

852 auto

*

Loc

=

Env

.

get

<RecordStorageLocation>(*E);

853 if

(

auto

*HasVal = getHasValue(

Env

,

Loc

)) {

854 if

(CmpExpr->

getOperator

() == clang::OO_ExclaimEqual)

855

CmpValue = &A.makeNot(*CmpValue);

856 Env

.

assume

(evaluateEquality(A, *CmpValue, HasVal->formula(),

857

A.makeLiteral(

false

)));

861

std::optional<StatementMatcher>

862

ignorableOptional(

const

UncheckedOptionalAccessModelOptions &Options) {

863 if

(Options.IgnoreSmartPointerDereference) {

866 unless

(hasArgument(0,

expr

(hasOptionalType()))))));

874

valueCall(

const

std::optional<StatementMatcher> &IgnorableOptional) {

875 return

isOptionalMemberCallWithNameMatcher(

hasName

(

"value"

),

880

valueOperatorCall(

const

std::optional<StatementMatcher> &IgnorableOptional) {

881 return expr

(

anyOf

(isOptionalOperatorCallWithName(

"*"

, IgnorableOptional),

882

isOptionalOperatorCallWithName(

"->"

, IgnorableOptional)));

885auto

buildTransferMatchSwitch() {

889 return

CFGMatchSwitchBuilder<LatticeTransferState>()

891

.CaseOfCFGStmt<CallExpr>(isMakeOptionalCall(), transferMakeOptionalCall)

894

.CaseOfCFGStmt<CXXConstructExpr>(

895

isOptionalInPlaceConstructor(),

896

[](

const

CXXConstructExpr *

E

,

const

MatchFinder::MatchResult &,

897

LatticeTransferState &State) {

898

constructOptionalValue(*

E

, State.Env,

899

State.Env.getBoolLiteralValue(

true

));

902

.CaseOfCFGStmt<CXXConstructExpr>(

903

isOptionalNulloptConstructor(),

904

[](

const

CXXConstructExpr *

E

,

const

MatchFinder::MatchResult &,

905

LatticeTransferState &State) {

906

constructOptionalValue(*

E

, State.Env,

907

State.Env.getBoolLiteralValue(

false

));

910

.CaseOfCFGStmt<CXXConstructExpr>(isOptionalValueOrConversionConstructor(),

911

transferValueOrConversionConstructor)

914

.CaseOfCFGStmt<CXXOperatorCallExpr>(

915

isOptionalValueOrConversionAssignment(),

916

transferValueOrConversionAssignment)

917

.CaseOfCFGStmt<CXXOperatorCallExpr>(isOptionalNulloptAssignment(),

918

transferNulloptAssignment)

921

.CaseOfCFGStmt<CXXMemberCallExpr>(

922

valueCall(std::nullopt),

923

[](

const

CXXMemberCallExpr *

E

,

const

MatchFinder::MatchResult &,

924

LatticeTransferState &State) {

925

transferUnwrapCall(

E

,

E

->getImplicitObjectArgument(), State);

929

.CaseOfCFGStmt<CallExpr>(isOptionalOperatorCallWithName(

"*"

),

930

[](

const

CallExpr *

E

,

931 const

MatchFinder::MatchResult &,

932

LatticeTransferState &State) {

933

transferUnwrapCall(

E

,

E

->getArg(0), State);

937

.CaseOfCFGStmt<CallExpr>(isOptionalOperatorCallWithName(

"->"

),

938

[](

const

CallExpr *

E

,

939 const

MatchFinder::MatchResult &,

940

LatticeTransferState &State) {

941

transferArrowOpCall(

E

,

E

->getArg(0), State);

947

.CaseOfCFGStmt<CXXMemberCallExpr>(

948

isOptionalMemberCallWithNameMatcher(

950

transferOptionalHasValueCall)

953

.CaseOfCFGStmt<CXXMemberCallExpr>(

954

isOptionalMemberCallWithNameMatcher(

hasName

(

"operator bool"

)),

955

transferOptionalHasValueCall)

959

.CaseOfCFGStmt<CXXMemberCallExpr>(

960

isOptionalMemberCallWithNameMatcher(

hasName

(

"isNull"

)),

961

transferOptionalIsNullCall)

964

.CaseOfCFGStmt<CXXMemberCallExpr>(

965

isOptionalMemberCallWithNameMatcher(

hasName

(

"emplace"

)),

966

[](

const

CXXMemberCallExpr *

E

,

const

MatchFinder::MatchResult &,

967

LatticeTransferState &State) {

968 if

(RecordStorageLocation *

Loc

=

970

setHasValue(*

Loc

, State.Env.getBoolLiteralValue(

true

), State.Env);

975

.CaseOfCFGStmt<CXXMemberCallExpr>(

976

isOptionalMemberCallWithNameMatcher(

hasName

(

"reset"

)),

977

[](

const

CXXMemberCallExpr *

E

,

const

MatchFinder::MatchResult &,

978

LatticeTransferState &State) {

979 if

(RecordStorageLocation *

Loc

=

981

setHasValue(*

Loc

, State.Env.getBoolLiteralValue(

false

),

987

.CaseOfCFGStmt<CXXMemberCallExpr>(

988

isOptionalMemberCallWithNameMatcher(

hasName

(

"swap"

)),

992

.CaseOfCFGStmt<CallExpr>(isStdSwapCall(), transferStdSwapCall)

995

.CaseOfCFGStmt<CallExpr>(isStdForwardCall(), transferStdForwardCall)

998

.CaseOfCFGStmt<Expr>(isValueOrStringEmptyCall(),

999

transferValueOrStringEmptyCall)

1002

.CaseOfCFGStmt<Expr>(isValueOrNotEqX(), transferValueOrNotEqX)

1005

.CaseOfCFGStmt<CXXOperatorCallExpr>(

1006

isComparisonOperatorCall(hasOptionalType(), hasOptionalType()),

1007

transferOptionalAndOptionalCmp)

1008

.CaseOfCFGStmt<CXXOperatorCallExpr>(

1009

isComparisonOperatorCall(hasOptionalType(), hasNulloptType()),

1011 const

MatchFinder::MatchResult &, LatticeTransferState &State) {

1012

transferOptionalAndNulloptCmp(Cmp, Cmp->getArg(0), State.Env);

1014

.CaseOfCFGStmt<CXXOperatorCallExpr>(

1015

isComparisonOperatorCall(hasNulloptType(), hasOptionalType()),

1017 const

MatchFinder::MatchResult &, LatticeTransferState &State) {

1018

transferOptionalAndNulloptCmp(Cmp, Cmp->getArg(1), State.Env);

1020

.CaseOfCFGStmt<CXXOperatorCallExpr>(

1021

isComparisonOperatorCall(

1023 unless

(

anyOf

(hasOptionalType(), hasNulloptType()))),

1025 const

MatchFinder::MatchResult &, LatticeTransferState &State) {

1026

transferOptionalAndValueCmp(Cmp, Cmp->getArg(0), State.Env);

1028

.CaseOfCFGStmt<CXXOperatorCallExpr>(

1029

isComparisonOperatorCall(

1030 unless

(

anyOf

(hasOptionalType(), hasNulloptType())),

1033 const

MatchFinder::MatchResult &, LatticeTransferState &State) {

1034

transferOptionalAndValueCmp(Cmp, Cmp->getArg(1), State.Env);

1040

.CaseOfCFGStmt<CXXOperatorCallExpr>(

1042

[](

const

CXXOperatorCallExpr *

E

,

1043 const

MatchFinder::MatchResult &

Result

,

1044

LatticeTransferState &State) {

1047

dyn_cast_or_null<RecordStorageLocation>(

1048

getLocBehindPossiblePointer(*

E

->getArg(0), State.Env)),

1049

State, [](StorageLocation &

Loc

) {});

1051

.CaseOfCFGStmt<CXXOperatorCallExpr>(

1053

[](

const

CXXOperatorCallExpr *

E

,

1054 const

MatchFinder::MatchResult &

Result

,

1055

LatticeTransferState &State) {

1058

dyn_cast_or_null<RecordStorageLocation>(

1059

getLocBehindPossiblePointer(*

E

->getArg(0), State.Env)),

1060

State, [](StorageLocation &

Loc

) {});

1062

.CaseOfCFGStmt<CXXMemberCallExpr>(

1064

[](

const

CXXMemberCallExpr *

E

,

const

MatchFinder::MatchResult &

Result

,

1065

LatticeTransferState &State) {

1068

[](StorageLocation &

Loc

) {});

1070

.CaseOfCFGStmt<CXXMemberCallExpr>(

1072

[](

const

CXXMemberCallExpr *

E

,

const

MatchFinder::MatchResult &

Result

,

1073

LatticeTransferState &State) {

1076

[](StorageLocation &

Loc

) {});

1080

.CaseOfCFGStmt<CXXMemberCallExpr>(isZeroParamConstMemberCall(),

1081

transferValue_ConstMemberCall)

1082

.CaseOfCFGStmt<CXXOperatorCallExpr>(isZeroParamConstMemberOperatorCall(),

1083

transferValue_ConstMemberOperatorCall)

1085

.CaseOfCFGStmt<CXXMemberCallExpr>(isNonConstMemberCall(),

1086

transferValue_NonConstMemberCall)

1087

.CaseOfCFGStmt<CXXOperatorCallExpr>(

1088

isNonConstMemberOperatorCall(),

1089

transferValue_NonConstMemberOperatorCall)

1092

.CaseOfCFGStmt<CallExpr>(isCallReturningOptional(),

1093

transferCallReturningOptional)

1099 const

Environment &

Env

) {

1100 if

(

auto

*OptionalLoc = cast_or_null<RecordStorageLocation>(

1101

getLocBehindPossiblePointer(*ObjectExpr,

Env

))) {

1102 auto

*Prop =

Env

.

getValue

(locForHasValue(*OptionalLoc));

1103 if

(

auto

*HasValueVal = cast_or_null<BoolValue>(Prop)) {

1104 if

(

Env

.

proves

(HasValueVal->formula()))

1112 return

{ObjectExpr->getBeginLoc()};

1115auto

buildDiagnoseMatchSwitch(

1116 const

UncheckedOptionalAccessModelOptions &Options) {

1120 auto

IgnorableOptional = ignorableOptional(Options);

1121 return

CFGMatchSwitchBuilder<

const

Environment,

1124

.CaseOfCFGStmt<CXXMemberCallExpr>(

1125

valueCall(IgnorableOptional),

1126

[](

const

CXXMemberCallExpr *

E

,

const

MatchFinder::MatchResult &,

1127 const

Environment &

Env

) {

1128 return

diagnoseUnwrapCall(

E

->getImplicitObjectArgument(),

Env

);

1132

.CaseOfCFGStmt<CallExpr>(valueOperatorCall(IgnorableOptional),

1133

[](

const

CallExpr *

E

,

1134 const

MatchFinder::MatchResult &,

1135 const

Environment &

Env

) {

1136 return

diagnoseUnwrapCall(

E

->getArg(0),

Env

);

1152

TransferMatchSwitch(buildTransferMatchSwitch()) {

1153 Env

.getDataflowAnalysisContext().setSyntheticFieldCallback(

1154

[&Ctx](

QualType

Ty) -> llvm::StringMap<QualType> {

1159 return

{{

"value"

, valueTypeFromOptionalDecl(*

Optional

)},

1160

{

"has_value"

, Ctx.BoolTy}};

1167

LatticeTransferState State(L,

Env

);

1173

: DiagnoseMatchSwitch(buildDiagnoseMatchSwitch(Options)) {}

Defines the clang::ASTContext interface.

#define AST_MATCHER(Type, DefineMatcher)

AST_MATCHER(Type, DefineMatcher) { ... } defines a zero parameter function named DefineMatcher() that...

#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param)

AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } defines a single-parameter function name...

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the clang::Expr interface and subclasses for C++ expressions.

llvm::MachO::RecordLoc RecordLoc

Defines an enumeration for C++ overloaded operators.

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 ...

Represents a top-level expression in a basic block.

Represents a base class of a C++ class.

Represents a call to a member function that may be written either with member call syntax (e....

A call to an overloaded operator written using operator syntax.

OverloadedOperatorKind getOperator() const

Returns the kind of overloaded operator that this expression refers to.

Represents a C++ struct/union/class.

bool hasDefinition() const

Expr * getArg(unsigned Arg)

getArg - Return the specified argument.

DeclContext * getParent()

getParent - Returns the containing DeclContext.

bool isTranslationUnit() const

DeclContext * getDeclContext()

bool isIdentifier() const

Predicate functions for querying what type of name this is.

This represents one expression.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

Represent a C++ namespace.

A (possibly-)qualified type.

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

const Formula & makeImplies(const Formula &LHS, const Formula &RHS)

Returns a formula for LHS => RHS.

A mixin for a lattice that additionally maintains a cache of stable method call return values to mode...

Base class template for dataflow analyses built on a single lattice type.

ASTContext & getASTContext() final

Holds the state of the program (store and heap) at a given program point.

StorageLocation * getStorageLocation(const ValueDecl &D) const

Returns the storage location assigned to D in the environment, or null if D isn't assigned a storage ...

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.

Value * getValue(const StorageLocation &Loc) const

Returns the value assigned to Loc in the environment or null if Loc isn't assigned a value in the env...

void assume(const Formula &)

Record a fact that must be true if this point in the program is reached.

RecordStorageLocation & getResultObjectLocation(const Expr &RecordPRValue) const

Returns the location of the result object for a record-type prvalue.

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...

UncheckedOptionalAccessDiagnoser(UncheckedOptionalAccessModelOptions Options={})

Dataflow analysis that models whether optionals hold values or not.

UncheckedOptionalAccessModel(ASTContext &Ctx, dataflow::Environment &Env)

void transfer(const CFGElement &Elt, UncheckedOptionalAccessLattice &L, Environment &Env)

static ast_matchers::DeclarationMatcher optionalClassDecl()

Returns a matcher for the optional classes covered by this model.

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, StringLiteral > stringLiteral

Matches string literals (also matches wide string literals).

internal::Matcher< NamedDecl > hasName(StringRef Name)

Matches NamedDecl nodes that have the specified name.

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.

internal::TrueMatcher anything()

Matches any node.

const internal::VariadicFunction< internal::Matcher< NamedDecl >, StringRef, internal::hasAnyNameFunc > hasAnyName

Matches NamedDecl nodes that have any of the specified names.

const internal::MapAnyOfMatcher< BinaryOperator, CXXOperatorCallExpr, CXXRewrittenBinaryOperator > binaryOperation

Matches nodes which can be used with binary operators.

const internal::VariadicDynCastAllOfMatcher< Stmt, CXXMemberCallExpr > cxxMemberCallExpr

Matches member call expressions.

const internal::VariadicDynCastAllOfMatcher< Decl, CXXConstructorDecl > cxxConstructorDecl

Matches C++ constructor declarations.

internal::PolymorphicMatcher< internal::ValueEqualsMatcher, void(internal::AllNodeBaseTypes), ValueT > equals(const ValueT &Value)

Matches literals that are equal to the given value of type ValueT.

internal::Matcher< Stmt > StatementMatcher

const internal::VariadicDynCastAllOfMatcher< Stmt, CXXConstructExpr > cxxConstructExpr

Matches constructor call expressions (including implicit ones).

const internal::VariadicDynCastAllOfMatcher< Stmt, CXXOperatorCallExpr > cxxOperatorCallExpr

Matches overloaded operator calls.

internal::PolymorphicMatcher< internal::HasOverloadedOperatorNameMatcher, AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl), std::vector< std::string > > hasOverloadedOperatorName(StringRef Name)

Matches overloaded operator names.

const internal::VariadicDynCastAllOfMatcher< Decl, FunctionDecl > functionDecl

Matches function declarations.

const AstTypeMatcher< RecordType > recordType

Matches record types (e.g.

const internal::VariadicDynCastAllOfMatcher< Stmt, MemberExpr > memberExpr

Matches member expressions.

const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl

Matches C++ class declarations.

const AstTypeMatcher< ReferenceType > referenceType

Matches both lvalue and rvalue reference types.

const internal::VariadicDynCastAllOfMatcher< Decl, RecordDecl > recordDecl

Matches class, struct, and union declarations.

const internal::VariadicDynCastAllOfMatcher< Stmt, IntegerLiteral > integerLiteral

Matches integer literals of all sizes / encodings, e.g.

const internal::VariadicDynCastAllOfMatcher< Stmt, CXXNullPtrLiteralExpr > cxxNullPtrLiteralExpr

Matches nullptr literal.

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::VariadicDynCastAllOfMatcher< Decl, CXXMethodDecl > cxxMethodDecl

Matches method declarations.

const internal::VariadicAllOfMatcher< QualType > qualType

Matches QualTypes in the clang AST.

const internal::VariadicDynCastAllOfMatcher< Stmt, CXXThisExpr > cxxThisExpr

Matches implicit and explicit this expressions.

static bool isFullyQualifiedNamespaceEqualTo(const NamespaceDecl &NS, llvm::StringRef Name, NameTypes... Names)

void transferSmartPointerLikeCachedDeref(const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc, TransferState< LatticeT > &State, llvm::function_ref< void(StorageLocation &)> InitializeLoc)

A transfer function for operator* (and value) calls that can be cached.

static bool hasOptionalClassName(const CXXRecordDecl &RD)

void transferSmartPointerLikeCachedGet(const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc, TransferState< LatticeT > &State, llvm::function_ref< void(StorageLocation &)> InitializeLoc)

A transfer function for operator-> (and get) calls that can be cached.

ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall()

ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall()

void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst, Environment &Env)

Copies a record (struct, class, or union) from Src to Dst.

static bool isSupportedOptionalType(QualType Ty)

ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow()

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...

static const CXXRecordDecl * getOptionalBaseClass(const CXXRecordDecl *RD)

ast_matchers::StatementMatcher isSmartPointerLikeOperatorStar()

Matchers: For now, these match on any class with an operator* or operator-> where the return types ha...

bool Cast(InterpState &S, CodePtr OpPC)

The JSON file list parser is used to communicate input to InstallAPI.

@ Result

The result type of a method or function.


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