llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-static-analyzer-1
Author: Ryosuke Niwa (rniwa)
<details>
<summary>Changes</summary>
Emit a warning for a member variable which is a raw pointer or raw reference to
a smart pointer as such a variable is not memory safe as the underlying smart
pointer might get free'ed elsewhere.
Also add a support for [[clang::annotate_type("webkit.unsafeptr")]], which
explicitly annotate and allow such a member variable in container classes such
as Vector and HashTable.
---
Patch is 35.57 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/200599.diff
8 Files Affected:
- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
(+26-6)
- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h (+10)
- (modified)
clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp (+76-36)
- (modified) clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp (+24-4)
- (modified) clang/test/Analysis/Checkers/WebKit/uncounted-members-objc.mm
(+24)
- (modified) clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp (+25-2)
- (modified) clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
(+41-1)
- (modified) clang/test/Analysis/Checkers/WebKit/unretained-members.mm (+62-1)
``````````diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 2ca34ff0587e1..0565c7540f845 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -225,6 +225,14 @@ static bool isPtrOfType(const clang::QualType T, Predicate
Pred) {
return false;
}
+bool isRefPtrType(const clang::QualType T) {
+ return isPtrOfType(T, [](auto Name) { return isRefType(Name); });
+}
+
+bool isCheckedPtrType(const clang::QualType T) {
+ return isPtrOfType(T, [](auto Name) { return isCheckedPtr(Name); });
+}
+
bool isRefOrCheckedPtrType(const clang::QualType T) {
return isPtrOfType(
T, [](auto Name) { return isRefType(Name) || isCheckedPtr(Name); });
@@ -427,14 +435,15 @@ enum class WebKitAnnotation : uint8_t {
None,
PointerConversion,
NoDelete,
+ UnsafePtr,
};
-static WebKitAnnotation typeAnnotationForReturnType(const FunctionDecl *FD) {
- auto RetType = FD->getReturnType();
- auto *Type = RetType.getTypePtrOrNull();
- if (auto *MacroQualified = dyn_cast_or_null<MacroQualifiedType>(Type))
- Type = MacroQualified->desugar().getTypePtrOrNull();
- auto *Attr = dyn_cast_or_null<AttributedType>(Type);
+static WebKitAnnotation typeAnnotation(const Type *T) {
+ if (!T)
+ return WebKitAnnotation::None;
+ if (auto *MacroQualified = dyn_cast_or_null<MacroQualifiedType>(T))
+ T = MacroQualified->desugar().getTypePtrOrNull();
+ auto *Attr = dyn_cast_or_null<AttributedType>(T);
if (!Attr)
return WebKitAnnotation::None;
auto *AnnotateType = dyn_cast_or_null<AnnotateTypeAttr>(Attr->getAttr());
@@ -445,9 +454,16 @@ static WebKitAnnotation typeAnnotationForReturnType(const
FunctionDecl *FD) {
return WebKitAnnotation::PointerConversion;
if (Annotation == "webkit.nodelete")
return WebKitAnnotation::NoDelete;
+ if (Annotation == "webkit.unsafeptr")
+ return WebKitAnnotation::UnsafePtr;
return WebKitAnnotation::None;
}
+static WebKitAnnotation typeAnnotationForReturnType(const FunctionDecl *FD) {
+ auto RetType = FD->getReturnType();
+ return typeAnnotation(RetType.getTypePtrOrNull());
+}
+
bool isPtrConversion(const FunctionDecl *F) {
assert(F);
if (isCtorOfRefCounted(F))
@@ -494,6 +510,10 @@ bool isNoDeleteFunction(const FunctionDecl *F) {
return false;
}
+bool isExplicitlyAllowedUnsafePtr(const Type *T) {
+ return typeAnnotation(T) == WebKitAnnotation::UnsafePtr;
+}
+
bool isTrivialBuiltinFunction(const FunctionDecl *F) {
if (!F || !F->getDeclName().isIdentifier())
return false;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index a2fd12656d391..13e78e0beb0ae 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -109,6 +109,12 @@ std::optional<bool> isUncountedPtr(const clang::QualType
T);
/// class, false if not, std::nullopt if inconclusive.
std::optional<bool> isUncheckedPtr(const clang::QualType T);
+/// \returns true if \p T is a RefPtr or Ref or its variant, false if not.
+bool isRefPtrType(const clang::QualType T);
+
+/// \returns true if \p T is a RefPtr or Ref or its variant, false if not.
+bool isCheckedPtrType(const clang::QualType T);
+
/// \returns true if \p T is a RefPtr, Ref, CheckedPtr, CheckedRef, or its
/// variant, false if not.
bool isRefOrCheckedPtrType(const clang::QualType T);
@@ -162,6 +168,10 @@ bool isPtrConversion(const FunctionDecl *F);
/// [[clang::annotate_type("webkit.nodelete")]].
bool isNoDeleteFunction(const FunctionDecl *F);
+/// \returns true if \p T is annotated with
+/// [[clang::annotate_type("webkit.unsafeptr")]].
+bool isExplicitlyAllowedUnsafePtr(const Type *T);
+
/// \returns true if \p F is a builtin function which is considered trivial.
bool isTrivialBuiltinFunction(const FunctionDecl *F);
diff --git
a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
index 0e23ae34ea212..1f0bbb09da61b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -39,6 +39,7 @@ class RawPtrRefMemberChecker
virtual std::optional<bool> isUnsafePtr(QualType,
bool ignoreARC = false) const = 0;
+ virtual bool isSafePtr(QualType) const = 0;
virtual const char *typeName() const = 0;
virtual const char *invariant() const = 0;
@@ -90,26 +91,39 @@ class RawPtrRefMemberChecker
}
void visitMember(const FieldDecl *Member, const RecordDecl *RD) const {
+ visitMemberDecl(Member, RD);
+ }
+
+ template <typename DeclType, typename ParentDeclType>
+ bool visitMemberDecl(DeclType *Member, const ParentDeclType *D) const {
auto QT = Member->getType();
const Type *MemberType = QT.getTypePtrOrNull();
+ bool IsPtrToSafePtr = false;
while (MemberType) {
auto IsUnsafePtr = isUnsafePtr(QT);
if (IsUnsafePtr && *IsUnsafePtr)
break;
- if (!MemberType->isPointerType())
- return;
+ if (!MemberType->isPointerType() && !MemberType->isReferenceType())
+ return false;
QT = MemberType->getPointeeType();
+ if (isSafePtr(QT) && !isExplicitlyAllowedUnsafePtr(MemberType)) {
+ IsPtrToSafePtr = true;
+ break;
+ }
MemberType = QT.getTypePtrOrNull();
}
if (!MemberType)
- return;
+ return false;
if (auto *MemberCXXRD = MemberType->getPointeeCXXRecordDecl())
- reportBug(Member, MemberType, MemberCXXRD, RD);
+ reportBug(Member, MemberType, MemberCXXRD, D, IsPtrToSafePtr);
else if (auto *ObjCDecl = getObjCDecl(MemberType))
- reportBug(Member, MemberType, ObjCDecl, RD);
+ reportBug(Member, MemberType, ObjCDecl, D, IsPtrToSafePtr);
+ else
+ return false;
+ return true;
}
ObjCInterfaceDecl *getObjCDecl(const Type *TypePtr) const {
@@ -156,21 +170,8 @@ class RawPtrRefMemberChecker
if (IvarDeclsToIgnore.contains(Ivar))
return;
- auto QT = Ivar->getType();
- const Type *IvarType = QT.getTypePtrOrNull();
- if (!IvarType)
- return;
-
- auto IsUnsafePtr = isUnsafePtr(QT);
- if (!IsUnsafePtr || !*IsUnsafePtr)
- return;
-
- IvarDeclsToIgnore.insert(Ivar);
-
- if (auto *MemberCXXRD = IvarType->getPointeeCXXRecordDecl())
- reportBug(Ivar, IvarType, MemberCXXRD, CD);
- else if (auto *ObjCDecl = getObjCDecl(IvarType))
- reportBug(Ivar, IvarType, ObjCDecl, CD);
+ if (visitMemberDecl(Ivar, CD))
+ IvarDeclsToIgnore.insert(Ivar);
}
void visitObjCPropertyDecl(const ObjCContainerDecl *CD,
@@ -184,14 +185,14 @@ class RawPtrRefMemberChecker
return;
}
- auto [IsUnsafe, PropType] = isPropImplUnsafePtr(PD);
+ auto [IsUnsafe, PropType, IsPtrToSafePtr] = isPropImplUnsafePtr(PD);
if (!IsUnsafe)
return;
if (auto *MemberCXXRD = PropType->getPointeeCXXRecordDecl())
- reportBug(PD, PropType, MemberCXXRD, CD);
+ reportBug(PD, PropType, MemberCXXRD, CD, IsPtrToSafePtr);
else if (auto *ObjCDecl = getObjCDecl(PropType))
- reportBug(PD, PropType, ObjCDecl, CD);
+ reportBug(PD, PropType, ObjCDecl, CD, IsPtrToSafePtr);
}
void visitPropImpl(const ObjCContainerDecl *CD,
@@ -208,25 +209,25 @@ class RawPtrRefMemberChecker
return;
IvarDeclsToIgnore.insert(IvarDecl);
}
- auto [IsUnsafe, PropType] = isPropImplUnsafePtr(PropDecl);
+ auto [IsUnsafe, PropType, IsPtrToSafePtr] = isPropImplUnsafePtr(PropDecl);
if (!IsUnsafe)
return;
if (auto *MemberCXXRD = PropType->getPointeeCXXRecordDecl())
- reportBug(PropDecl, PropType, MemberCXXRD, CD);
+ reportBug(PropDecl, PropType, MemberCXXRD, CD, IsPtrToSafePtr);
else if (auto *ObjCDecl = getObjCDecl(PropType))
- reportBug(PropDecl, PropType, ObjCDecl, CD);
+ reportBug(PropDecl, PropType, ObjCDecl, CD, IsPtrToSafePtr);
}
- std::pair<bool, const Type *>
+ std::tuple<bool, const Type *, bool>
isPropImplUnsafePtr(const ObjCPropertyDecl *PD) const {
if (!PD)
- return {false, nullptr};
+ return {false, nullptr, false};
auto QT = PD->getType();
const Type *PropType = QT.getTypePtrOrNull();
if (!PropType)
- return {false, nullptr};
+ return {false, nullptr, false};
// "assign" property doesn't retain even under ARC so treat it as unsafe.
bool ignoreARC =
@@ -235,7 +236,22 @@ class RawPtrRefMemberChecker
PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak;
bool HasSafeAttr = PD->isRetaining() || IsWeak;
auto IsUnsafePtr = isUnsafePtr(QT, ignoreARC);
- return {IsUnsafePtr && *IsUnsafePtr && !HasSafeAttr, PropType};
+ if (IsUnsafePtr && *IsUnsafePtr)
+ return {!HasSafeAttr, PropType, false};
+
+ while (PropType->isPointerType() || PropType->isReferenceType()) {
+ auto PointeeQT = PropType->getPointeeType();
+ if (isSafePtr(PointeeQT))
+ return {true, PropType, true};
+ PropType = PointeeQT.getTypePtrOrNull();
+ if (!PropType)
+ break;
+ auto IsUnsafePtr = isUnsafePtr(PointeeQT);
+ if (IsUnsafePtr && *IsUnsafePtr)
+ return {true, PropType, false};
+ }
+
+ return {false, nullptr, false};
}
bool shouldSkipDecl(const RecordDecl *RD) const {
@@ -275,7 +291,8 @@ class RawPtrRefMemberChecker
template <typename DeclType, typename PointeeType, typename ParentDeclType>
void reportBug(const DeclType *Member, const Type *MemberType,
const PointeeType *Pointee,
- const ParentDeclType *ClassCXXRD) const {
+ const ParentDeclType *ClassCXXRD,
+ bool IsPtrToSafe = false) const {
assert(Member);
assert(MemberType);
assert(Pointee);
@@ -297,7 +314,7 @@ class RawPtrRefMemberChecker
Os << " is a ";
else
Os << " contains a ";
- if (printPointer(Os, MemberType) == PrintDeclKind::Pointer) {
+ if (printPointer(Os, MemberType, IsPtrToSafe) == PrintDeclKind::Pointer) {
auto Typedef = MemberType->getAs<TypedefType>();
assert(Typedef);
printQuotedQualifiedName(Os, Typedef->getDecl());
@@ -314,12 +331,22 @@ class RawPtrRefMemberChecker
enum class PrintDeclKind { Pointee, Pointer };
virtual PrintDeclKind printPointer(llvm::raw_svector_ostream &Os,
- const Type *T) const {
+ const Type *T, bool IsPtrToSafe) const {
T = T->getUnqualifiedDesugaredType();
bool IsPtr = isa<PointerType>(T) || isa<ObjCObjectPointerType>(T);
- Os << (IsPtr ? "raw pointer" : "reference") << " to " << typeName() << " ";
+ Os << "raw " << (IsPtr ? "pointer" : "reference") << " to ";
+ if (!IsPtrToSafe)
+ Os << typeName() << " ";
return PrintDeclKind::Pointee;
}
+
+ void printTypeName(llvm::raw_ostream &Os, const Type *T) const {
+ if (auto *RD = T->getAsRecordDecl())
+ RD->getNameForDiagnostic(Os, RD->getASTContext().getPrintingPolicy(),
+ /*Qualified=*/true);
+ else
+ Os << typeName();
+ }
};
class NoUncountedMemberChecker final : public RawPtrRefMemberChecker {
@@ -332,6 +359,10 @@ class NoUncountedMemberChecker final : public
RawPtrRefMemberChecker {
return isUncountedPtr(QT.getCanonicalType());
}
+ bool isSafePtr(QualType QT) const final {
+ return isRefPtrType(QT);
+ }
+
const char *typeName() const final { return "ref-countable type"; }
const char *invariant() const final {
@@ -349,6 +380,10 @@ class NoUncheckedPtrMemberChecker final : public
RawPtrRefMemberChecker {
return isUncheckedPtr(QT.getCanonicalType());
}
+ bool isSafePtr(QualType QT) const final {
+ return isCheckedPtrType(QT);
+ }
+
const char *typeName() const final { return "CheckedPtr capable type"; }
const char *invariant() const final {
@@ -371,6 +406,10 @@ class NoUnretainedMemberChecker final : public
RawPtrRefMemberChecker {
return RTC->isUnretained(QT, ignoreARC);
}
+ bool isSafePtr(QualType QT) const final {
+ return isRetainPtrOrOSPtrType(QT);
+ }
+
const char *typeName() const final { return "retainable type"; }
const char *invariant() const final {
@@ -378,12 +417,13 @@ class NoUnretainedMemberChecker final : public
RawPtrRefMemberChecker {
}
PrintDeclKind printPointer(llvm::raw_svector_ostream &Os,
- const Type *T) const final {
+ const Type *T, bool IsPtrToSafe) const final {
+ // FIXME: Support IsPtrToSafe.
if (!isa<ObjCObjectPointerType>(T) && T->getAs<TypedefType>()) {
Os << typeName() << " ";
return PrintDeclKind::Pointer;
}
- return RawPtrRefMemberChecker::printPointer(Os, T);
+ return RawPtrRefMemberChecker::printPointer(Os, T, IsPtrToSafe);
}
};
diff --git a/clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp
b/clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp
index 3fe15d88ff312..57ca3f98a14da 100644
--- a/clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp
@@ -9,7 +9,7 @@ namespace members {
CheckedObj* a = nullptr;
// expected-warning@-1{{Member variable 'a' in 'members::Foo' is a raw pointer
to CheckedPtr capable type 'CheckedObj'}}
CheckedObj& b;
-// expected-warning@-1{{Member variable 'b' in 'members::Foo' is a reference
to CheckedPtr capable type 'CheckedObj'}}
+// expected-warning@-1{{Member variable 'b' in 'members::Foo' is a raw
reference to CheckedPtr capable type 'CheckedObj'}}
[[clang::suppress]]
CheckedObj* a_suppressed = nullptr;
@@ -19,6 +19,14 @@ namespace members {
CheckedPtr<CheckedObj> c;
CheckedRef<CheckedObj> d;
+ CheckedRef<RefCountable>* e;
+// expected-warning@-1{{Member variable 'e' in 'members::Foo' is a raw pointer
to 'CheckedRef<RefCountable>'}}
+ CheckedRef<RefCountable>& f;
+// expected-warning@-1{{Member variable 'f' in 'members::Foo' is a raw
reference to 'CheckedRef<RefCountable>'}}
+ CheckedRef<RefCountable>** g;
+// expected-warning@-1{{Member variable 'g' in 'members::Foo' contains a raw
pointer to 'CheckedRef<RefCountable>'}}
+ CheckedRef<RefCountable>* h;
+// expected-warning@-1{{Member variable 'h' in 'members::Foo' is a raw pointer
to 'CheckedRef<RefCountable>'}}
public:
Foo();
@@ -39,8 +47,12 @@ namespace unions {
union Foo {
CheckedObj* a;
// expected-warning@-1{{Member variable 'a' in 'unions::Foo' is a raw
pointer to CheckedPtr capable type 'CheckedObj'}}
- CheckedPtr<CheckedObj> c;
- CheckedRef<CheckedObj> d;
+ CheckedPtr<CheckedObj> b;
+ CheckedRef<CheckedObj> c;
+ CheckedObj** d;
+ // expected-warning@-1{{Member variable 'd' in 'unions::Foo' contains a
raw pointer to CheckedPtr capable type 'CheckedObj'}}
+ CheckedPtr<CheckedObj>* e;
+ // expected-warning@-1{{Member variable 'e' in 'unions::Foo' is a raw
pointer to 'CheckedPtr<CheckedObj>'}}
};
template<class T>
@@ -76,8 +88,16 @@ namespace ptr_to_ptr_to_checked_ptr_capable {
};
TemplateList<CheckedObj> list;
- struct SafeList {
+ struct FormerlySafeList {
CheckedPtr<CheckedObj>* elements;
+ // expected-warning@-1{{Member variable 'elements' in
'ptr_to_ptr_to_checked_ptr_capable::FormerlySafeList' is a raw pointer to
'CheckedPtr<CheckedObj>'}}
+ };
+
+ struct Container {
+ CheckedPtr<CheckedObj>* [[clang::annotate_type("webkit.unsafeptr")]]
elements1;
+ CheckedPtr<CheckedObj>** [[clang::annotate_type("webkit.unsafeptr")]]
elements2;
+ // expected-warning@-1{{Member variable 'elements2' in
'ptr_to_ptr_to_checked_ptr_capable::Container' contains a raw pointer to
'CheckedPtr<CheckedObj>'}}
+ CheckedRef<CheckedObj>* [[clang::annotate_type("webkit.unsafeptr")]]*
[[clang::annotate_type("webkit.unsafeptr")]] elements3;
};
} // namespace ptr_to_ptr_to_checked_ptr_capable
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-members-objc.mm
b/clang/test/Analysis/Checkers/WebKit/uncounted-members-objc.mm
index 83b08a6841d26..dcbc6e74eee9b 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-members-objc.mm
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-members-objc.mm
@@ -17,7 +17,25 @@ @interface SomeObjC : NSObject {
// expected-warning@-1{{Instance variable '_uncounted1' in 'SomeObjC' is a raw
pointer to ref-countable type 'RefCountable'}}
RefPtr<RefCountable> _counted1;
[[clang::suppress]] RefCountable* _uncounted2;
+ RefCountable** _ptr_to_ptr_to_uncounted;
+// expected-warning@-1{{Instance variable '_ptr_to_ptr_to_uncounted' in
'SomeObjC' contains a raw pointer to ref-countable type 'RefCountable'}}
+ RefPtr<RefCountable>* ptr_to_refptr1;
+// expected-warning@-1{{Instance variable 'ptr_to_refptr1' in 'SomeObjC' is a
raw pointer to 'RefPtr<RefCountable>'}}
+ RefPtr<RefCountable>* [[clang::annotate_type("webkit.unsafeptr")]]
_ptr_to_refptr2;
+ RefPtr<RefCountable>** _ptr_to_refptr3;
+// expected-warning@-1{{Instance variable '_ptr_to_refptr3' in 'SomeObjC'
contains a raw pointer to 'RefPtr<RefCountable>'}}
+ Ref<RefCountable>* [[clang::annotate_type("webkit.unsafeptr")]] _ptr_to_ref1;
+ Ref<RefCountable>** _ptr_to_ref2;
+// expected-warning@-1{{Instance variable '_ptr_to_ref2' in 'SomeObjC'
contains a raw pointer to 'Ref<RefCountable>'}}
}
+@property (nonatomic) RefCountable **obj1;
+// expected-warning@-1{{Property 'obj1' in 'SomeObjC' contains a raw pointer
to ref-countable type 'RefCountable'}}
+@property (nonatomic) RefPtr<RefCountable> *obj2;
+// expected-warning@-1{{Property 'obj2' in 'SomeObjC' is a raw pointer to
'RefPtr<RefCountable>'}}
+@property (nonatomic) RefPtr<RefCountable> **obj3;
+// expected-warning@-1{{Property 'obj3' in 'SomeObjC' contains a raw pointer
to 'RefPtr<RefCountable>'}}
+@property(nonatomic, readonly) Ref<RefCountable> *syn_prop;
+// expected-warning@-1{{Property 'syn_prop' in 'SomeObjC' is a raw pointer to
'Ref<RefCountable>'}}
- (void)doWork;
@end
@@ -26,8 +44,14 @@ @implementation SomeObjC {
// expected-warning@-1{{Instance variable '_uncounted3' in 'SomeObjC' is a raw
pointer to ref-countable type 'RefCountable'}}
RefPtr<RefCountable> _counted2;
[[clang::suppress]] RefCountable* _uncounted4;
+ RefCountable** _uncounted5;
+// expected-warning@-1{{Instance variable '_uncounted5' in 'SomeObjC' contains
a raw pointer to ref-countable type 'RefCountable'}}
+ RefPtr<RefCountable>* _ptr_to_refptr1;
+// expected-warning@-1{{Instance variable '_ptr_to_refptr1' in 'SomeObjC' is a
raw pointer to 'RefPtr<RefCountable>'}}
}
+@synthesize syn_prop;
+
- (void)doWork {
doSomeWork();
}
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp
b/clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp
index b8c443cda4f8e..37464d0ddb0ac 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp
@@ -16,10 +16,20 @@ namespace members {
RefPtr<RefCountable> b;
public:
+ Foo();
+
RefCountable silenceWarningAboutInit;
RefCountable& c = silenceWarningAboutInit;
-// expected-warning@-1{{Member variable 'c' in 'members::Foo' is a reference
to ref-countable type 'RefCountable'}}
+// expected-warning@-1{{Member variable 'c' in 'members::Foo' is a raw
reference to ref-countable type 'RefCountable'}}
Ref<RefCountable> d;
+ Ref<RefCountable>* e;
+// expected-warning@-1{{Member variable 'e' in 'members::Foo' is a raw pointer
to 'Ref<RefCountable>'}}
+ Ref<RefCountable>& f;
+// expected-warning@-1{{Member variable 'f' in 'members::Foo' is a raw
reference to 'Ref<RefCountable>'}}
+ Ref<RefCountable>** g;
+// expected-warning@-1{{Member variable 'g' in 'members::Foo' contains a raw
pointer to 'Ref<RefCountable>'}}
+ RefPtr<RefCountable>* h;
+// expected-warning@-1{{Member variable 'h' in 'members::Foo' is a raw pointer
to 'RefPtr<RefCountable>'}}
};
template<class T>
@@ -34,6 +44,7 @@ namespace members {
private:
RefCountable* a = nullptr;
};
+
} // members
namespace unions {...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/200599
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits