[clang] [clang][dataflow] Add test for crash repro and clean up const accessor handling (PR #129930)
Yitzhak Mandelbaum via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 6 12:15:05 PST 2025
================
@@ -551,91 +551,92 @@ void transferCallReturningOptional(const CallExpr *E,
setHasValue(*Loc, State.Env.makeAtomicBoolValue(), State.Env);
}
+// Returns true if the const accessor is handled by caching.
+// Returns false if we could not cache. We should perform default handling
+// in that case.
bool handleConstMemberCall(const CallExpr *CE,
dataflow::RecordStorageLocation *RecordLoc,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) {
if (RecordLoc == nullptr)
return false;
- // If the const method returns an optional or reference to an optional.
- if (isSupportedOptionalType(CE->getType())) {
- const FunctionDecl *DirectCallee = CE->getDirectCallee();
- if (DirectCallee == nullptr)
- return false;
- StorageLocation &Loc =
- State.Lattice.getOrCreateConstMethodReturnStorageLocation(
- *RecordLoc, DirectCallee, State.Env, [&](StorageLocation &Loc) {
- setHasValue(cast<RecordStorageLocation>(Loc),
- State.Env.makeAtomicBoolValue(), State.Env);
- });
- if (CE->isGLValue()) {
- // If the call to the const method returns a reference to an optional,
- // link the call expression to the cached StorageLocation.
- State.Env.setStorageLocation(*CE, Loc);
- } else {
- // If the call to the const method returns an optional by value, we
- // need to use CopyRecord to link the optional to the result object
- // of the call expression.
- auto &ResultLoc = State.Env.getResultObjectLocation(*CE);
- copyRecord(cast<RecordStorageLocation>(Loc), ResultLoc, State.Env);
- }
- return true;
- }
-
- // Cache if the const method returns a reference
+ // Cache if the const method returns a reference.
if (CE->isGLValue()) {
const FunctionDecl *DirectCallee = CE->getDirectCallee();
if (DirectCallee == nullptr)
return false;
+ // Initialize the optional's "has_value" property to true if the type is
+ // optional, otherwise no-op. If we want to support const ref to pointers or
+ // bools we should initialize their values here too.
+ auto Init = [&](StorageLocation &Loc) {
+ if (isSupportedOptionalType(CE->getType()))
+ setHasValue(cast<RecordStorageLocation>(Loc),
+ State.Env.makeAtomicBoolValue(), State.Env);
+ };
StorageLocation &Loc =
State.Lattice.getOrCreateConstMethodReturnStorageLocation(
- *RecordLoc, DirectCallee, State.Env, [&](StorageLocation &Loc) {
- // no-op
- // NOTE: if we want to support const ref to pointers or bools
- // we should initialize their values here.
- });
+ *RecordLoc, DirectCallee, State.Env, Init);
State.Env.setStorageLocation(*CE, Loc);
return true;
- } else if (CE->getType()->isBooleanType() || CE->getType()->isPointerType()) {
- // Cache if the const method returns a boolean or pointer type.
- Value *Val = State.Lattice.getOrCreateConstMethodReturnValue(*RecordLoc, CE,
- State.Env);
- if (Val == nullptr)
- return false;
- State.Env.setValue(*CE, *Val);
- return true;
+ } else {
----------------
ymand wrote:
nit: drop the `else` because the bloc ends in `return`?
https://github.com/llvm/llvm-project/pull/129930
More information about the cfe-commits
mailing list