Skip to content

[RawPtrRefMemberChecker] Member variable checker should allow T* in smart pointer classes #136503

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,13 @@ bool isRetainPtr(const CXXRecordDecl *R) {
return false;
}

bool isSmartPtr(const CXXRecordDecl *R) {
assert(R);
if (auto *TmplR = R->getTemplateInstantiationPattern())
return isSmartPtrClass(safeGetName(TmplR));
return false;
}

bool isPtrConversion(const FunctionDecl *F) {
assert(F);
if (isCtorOfRefCounted(F))
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ bool isCheckedPtr(const clang::CXXRecordDecl *Class);
/// \returns true if \p Class is a RetainPtr, false if not.
bool isRetainPtr(const clang::CXXRecordDecl *Class);

/// \returns true if \p Class is a smart pointer (RefPtr, WeakPtr, etc...),
/// false if not.
bool isSmartPtr(const clang::CXXRecordDecl *Class);

/// \returns true if \p Class is ref-countable AND not ref-counted, false if
/// not, std::nullopt if inconclusive.
std::optional<bool> isUncounted(const clang::QualType T);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class RawPtrRefMemberChecker
virtual std::optional<bool>
isPtrCompatible(const clang::QualType,
const clang::CXXRecordDecl *R) const = 0;
virtual bool isPtrCls(const clang::CXXRecordDecl *) const = 0;
virtual const char *typeName() const = 0;
virtual const char *invariant() const = 0;

Expand Down Expand Up @@ -205,8 +204,8 @@ class RawPtrRefMemberChecker
// Ref-counted smartpointers actually have raw-pointer to uncounted type as
// a member but we trust them to handle it correctly.
auto CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(RD);
if (CXXRD)
return isPtrCls(CXXRD);
if (CXXRD && isSmartPtr(CXXRD))
return true;

return false;
}
Expand Down Expand Up @@ -270,10 +269,6 @@ class NoUncountedMemberChecker final : public RawPtrRefMemberChecker {
return R ? isRefCountable(R) : std::nullopt;
}

bool isPtrCls(const clang::CXXRecordDecl *R) const final {
return isRefCounted(R);
}

const char *typeName() const final { return "ref-countable type"; }

const char *invariant() const final {
Expand All @@ -293,10 +288,6 @@ class NoUncheckedPtrMemberChecker final : public RawPtrRefMemberChecker {
return R ? isCheckedPtrCapable(R) : std::nullopt;
}

bool isPtrCls(const clang::CXXRecordDecl *R) const final {
return isCheckedPtr(R);
}

const char *typeName() const final { return "CheckedPtr capable type"; }

const char *invariant() const final {
Expand All @@ -319,10 +310,6 @@ class NoUnretainedMemberChecker final : public RawPtrRefMemberChecker {
return RTC->isUnretained(QT);
}

bool isPtrCls(const clang::CXXRecordDecl *R) const final {
return isRetainPtr(R);
}

const char *typeName() const final { return "retainable type"; }

const char *invariant() const final {
Expand Down
9 changes: 9 additions & 0 deletions clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,12 @@ namespace ignore_unions {
void forceTmplToInstantiate(FooTmpl<CheckedObj>) { }

} // namespace ignore_unions

namespace checked_ptr_ref_ptr_capable {

RefCountableAndCheckable* provide();
void foo() {
RefPtr<RefCountableAndCheckable> foo = provide();
}

} // checked_ptr_ref_ptr_capable
15 changes: 12 additions & 3 deletions clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace members {
private:
RefCountable* a = nullptr;
};
}
} // members

namespace ignore_unions {
union Foo {
Expand All @@ -49,7 +49,7 @@ namespace ignore_unions {
};

void forceTmplToInstantiate(RefPtr<RefCountable>) {}
}
} // ignore_unions

namespace ignore_system_header {

Expand All @@ -67,4 +67,13 @@ namespace ignore_non_ref_countable {
struct Bar {
Foo* foo;
};
}
} // ignore_non_ref_countable

namespace checked_ptr_ref_ptr_capable {

RefCountableAndCheckable* provide();
void foo() {
CheckedPtr<RefCountableAndCheckable> foo = provide();
}

} // checked_ptr_ref_ptr_capable
Loading