|
25 | 25 | #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" |
26 | 26 | #include "clang/Analysis/FlowSensitive/MatchSwitch.h" |
27 | 27 | #include "clang/Analysis/FlowSensitive/RecordOps.h" |
| 28 | +#include "clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h" |
28 | 29 | #include "clang/Analysis/FlowSensitive/StorageLocation.h" |
29 | 30 | #include "clang/Analysis/FlowSensitive/Value.h" |
30 | 31 | #include "clang/Basic/LLVM.h" |
@@ -849,6 +850,16 @@ transferNonConstMemberOperatorCall(const CXXOperatorCallExpr *Expr, |
849 | 850 | handleNonConstMemberCall(Expr, RecordLoc, Result, State); |
850 | 851 | } |
851 | 852 |
|
| 853 | +static RecordStorageLocation * |
| 854 | +getSmartPtrLikeStorageLocation(const Expr &E, const Environment &Env) { |
| 855 | + if (!E.isPRValue()) |
| 856 | + return dyn_cast_or_null<RecordStorageLocation>(Env.getStorageLocation(E)); |
| 857 | + if (auto *PointerVal = dyn_cast_or_null<PointerValue>(Env.getValue(E))) |
| 858 | + return dyn_cast_or_null<RecordStorageLocation>( |
| 859 | + &PointerVal->getPointeeLoc()); |
| 860 | + return nullptr; |
| 861 | +} |
| 862 | + |
852 | 863 | CFGMatchSwitch<LatticeTransferState> |
853 | 864 | buildTransferMatchSwitch(ASTContext &Ctx, |
854 | 865 | CFGMatchSwitchBuilder<LatticeTransferState> Builder) { |
@@ -906,6 +917,43 @@ buildTransferMatchSwitch(ASTContext &Ctx, |
906 | 917 | transferLoggingGetReferenceableValueCall) |
907 | 918 | .CaseOfCFGStmt<CallExpr>(isLoggingCheckEqImpl(), |
908 | 919 | transferLoggingCheckEqImpl) |
| 920 | + // This needs to go before the const accessor call matcher, because these |
| 921 | + // look like them, but we model `operator`* and `get` to return the same |
| 922 | + // object. Also, we model them for non-const cases. |
| 923 | + .CaseOfCFGStmt<CXXOperatorCallExpr>( |
| 924 | + isPointerLikeOperatorStar(), |
| 925 | + [](const CXXOperatorCallExpr *E, |
| 926 | + const MatchFinder::MatchResult &Result, |
| 927 | + LatticeTransferState &State) { |
| 928 | + transferSmartPointerLikeCachedDeref( |
| 929 | + E, getSmartPtrLikeStorageLocation(*E->getArg(0), State.Env), |
| 930 | + State, [](StorageLocation &Loc) {}); |
| 931 | + }) |
| 932 | + .CaseOfCFGStmt<CXXOperatorCallExpr>( |
| 933 | + isPointerLikeOperatorArrow(), |
| 934 | + [](const CXXOperatorCallExpr *E, |
| 935 | + const MatchFinder::MatchResult &Result, |
| 936 | + LatticeTransferState &State) { |
| 937 | + transferSmartPointerLikeCachedGet( |
| 938 | + E, getSmartPtrLikeStorageLocation(*E->getArg(0), State.Env), |
| 939 | + State, [](StorageLocation &Loc) {}); |
| 940 | + }) |
| 941 | + .CaseOfCFGStmt<CXXMemberCallExpr>( |
| 942 | + isSmartPointerLikeValueMethodCall(), |
| 943 | + [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &Result, |
| 944 | + LatticeTransferState &State) { |
| 945 | + transferSmartPointerLikeCachedDeref( |
| 946 | + E, getImplicitObjectLocation(*E, State.Env), State, |
| 947 | + [](StorageLocation &Loc) {}); |
| 948 | + }) |
| 949 | + .CaseOfCFGStmt<CXXMemberCallExpr>( |
| 950 | + isSmartPointerLikeGetMethodCall(), |
| 951 | + [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &Result, |
| 952 | + LatticeTransferState &State) { |
| 953 | + transferSmartPointerLikeCachedGet( |
| 954 | + E, getImplicitObjectLocation(*E, State.Env), State, |
| 955 | + [](StorageLocation &Loc) {}); |
| 956 | + }) |
909 | 957 | // const accessor calls |
910 | 958 | .CaseOfCFGStmt<CXXMemberCallExpr>(isConstStatusOrAccessorMemberCall(), |
911 | 959 | transferConstStatusOrAccessorMemberCall) |
|
0 commit comments