Bug 1255894: Allow capturing `this` in lambda expressions when marked safe. r?mystor
MozReview-Commit-ID: E9suVDbOZKY
--- a/build/clang-plugin/CustomTypeAnnotation.cpp
+++ b/build/clang-plugin/CustomTypeAnnotation.cpp
@@ -12,16 +12,18 @@ CustomTypeAnnotation GlobalClass =
CustomTypeAnnotation NonHeapClass =
CustomTypeAnnotation("moz_nonheap_class", "non-heap");
CustomTypeAnnotation HeapClass =
CustomTypeAnnotation("moz_heap_class", "heap");
CustomTypeAnnotation NonTemporaryClass =
CustomTypeAnnotation("moz_non_temporary_class", "non-temporary");
CustomTypeAnnotation NonParam =
CustomTypeAnnotation("moz_non_param", "non-param");
+CustomTypeAnnotation SafeForLambdaCapture =
+ CustomTypeAnnotation("moz_safe_for_lambda_capture", "lambda-safe");
void CustomTypeAnnotation::dumpAnnotationReason(BaseCheck &Check,
QualType T,
SourceLocation Loc) {
const char* Inherits =
"%1 is a %0 type because it inherits from a %0 type %2";
const char* Member =
"%1 is a %0 type because member %2 is a %0 type %3";
--- a/build/clang-plugin/CustomTypeAnnotation.h
+++ b/build/clang-plugin/CustomTypeAnnotation.h
@@ -63,10 +63,11 @@ protected:
};
extern CustomTypeAnnotation StackClass;
extern CustomTypeAnnotation GlobalClass;
extern CustomTypeAnnotation NonHeapClass;
extern CustomTypeAnnotation HeapClass;
extern CustomTypeAnnotation NonTemporaryClass;
extern CustomTypeAnnotation NonParam;
+extern CustomTypeAnnotation SafeForLambdaCapture;
#endif
--- a/build/clang-plugin/RefCountedInsideLambdaChecker.cpp
+++ b/build/clang-plugin/RefCountedInsideLambdaChecker.cpp
@@ -103,17 +103,17 @@ void RefCountedInsideLambdaChecker::chec
}
}
// Now we can go through and produce errors for any captured variables or this pointers.
for (const LambdaCapture& Capture : Lambda->captures()) {
if (Capture.capturesVariable()) {
QualType Pointee = Capture.getCapturedVar()->getType()->getPointeeType();
- if (!Pointee.isNull() && isClassRefCounted(Pointee)) {
+ if (!Pointee.isNull() && isClassRefCounted(Pointee) && !SafeForLambdaCapture.hasEffectiveAnnotation(Pointee)) {
emitDiagnostics(Capture.getLocation(), Capture.getCapturedVar()->getName(), Pointee);
return;
}
}
// The situation with captures of `this` is more complex. All captures of
// `this` look the same-ish (they are LCK_This). We want to complain about
// captures of `this` where `this` is a refcounted type, and the capture is
@@ -135,15 +135,15 @@ void RefCountedInsideLambdaChecker::chec
return;
}
}
}
}
bool RefCountedInsideLambdaChecker::ThisVisitor::VisitCXXThisExpr(CXXThisExpr *This) {
QualType Pointee = This->getType()->getPointeeType();
- if (!Pointee.isNull() && isClassRefCounted(Pointee)) {
+ if (!Pointee.isNull() && isClassRefCounted(Pointee) && !SafeForLambdaCapture.hasEffectiveAnnotation(Pointee)) {
Checker.emitDiagnostics(This->getLocStart(), "this", Pointee);
return false;
}
return true;
}
--- a/mfbt/Attributes.h
+++ b/mfbt/Attributes.h
@@ -462,16 +462,19 @@
*
* Examples include an nsIAtom* member which is known at compile time to point to a
* static atom which is valid throughout the lifetime of the program, or an API which
* stores a pointer, but doesn't take ownership over it, instead requiring the API
* consumer to correctly null the value before it becomes invalid.
*
* Use of this annotation is discouraged when a strong reference or one of the above
* two annotations can be used instead.
+ * MOZ_SAFE_FOR_LAMBDA_CAPTURE: Applies to class declarations. Allows `this` to
+ * be captured by value in lambda expressions, for classes which ensure that a
+ * reference is kept alive for the lifetime of all such lambdas.
* MOZ_NO_ADDREF_RELEASE_ON_RETURN: Applies to function declarations. Makes it
* a compile time error to call AddRef or Release on the return value of a
* function. This is intended to be used with operator->() of our smart
* pointer classes to ensure that the refcount of an object wrapped in a
* smart pointer is not manipulated directly.
* MOZ_MUST_USE_TYPE: Applies to type declarations. Makes it a compile time
* error to not use the return value of a function which has this type. This
* is intended to be used with types which it is an error to not use.
@@ -537,16 +540,17 @@
# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class"))) \
MOZ_TRIVIAL_CTOR_DTOR
# endif
# define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT __attribute__((annotate("moz_no_arith_expr_in_arg")))
# define MOZ_OWNING_REF __attribute__((annotate("moz_strong_ref")))
# define MOZ_NON_OWNING_REF __attribute__((annotate("moz_weak_ref")))
# define MOZ_UNSAFE_REF(reason) __attribute__((annotate("moz_weak_ref")))
+# define MOZ_SAFE_FOR_LAMBDA_CAPTURE __attribute__((annotate("moz_safe_for_lambda_capture")))
# define MOZ_NO_ADDREF_RELEASE_ON_RETURN __attribute__((annotate("moz_no_addref_release_on_return")))
# define MOZ_MUST_USE_TYPE __attribute__((annotate("moz_must_use_type")))
# define MOZ_NEEDS_NO_VTABLE_TYPE __attribute__((annotate("moz_needs_no_vtable_type")))
# define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
# define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
# define MOZ_NEEDS_MEMMOVABLE_MEMBERS __attribute__((annotate("moz_needs_memmovable_members")))
# define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS \
__attribute__((annotate("moz_inherit_type_annotations_from_template_args")))
@@ -582,16 +586,17 @@
# define MOZ_TRIVIAL_CTOR_DTOR /* nothing */
# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS /* nothing */
# define MOZ_IMPLICIT /* nothing */
# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT /* nothing */
# define MOZ_HEAP_ALLOCATOR /* nothing */
# define MOZ_OWNING_REF /* nothing */
# define MOZ_NON_OWNING_REF /* nothing */
# define MOZ_UNSAFE_REF(reason) /* nothing */
+# define MOZ_SAFE_FOR_LAMBDA_CAPTURE /* nothing */
# define MOZ_NO_ADDREF_RELEASE_ON_RETURN /* nothing */
# define MOZ_MUST_USE_TYPE /* nothing */
# define MOZ_NEEDS_NO_VTABLE_TYPE /* nothing */
# define MOZ_NON_MEMMOVABLE /* nothing */
# define MOZ_NEEDS_MEMMOVABLE_TYPE /* nothing */
# define MOZ_NEEDS_MEMMOVABLE_MEMBERS /* nothing */
# define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS /* nothing */
# define MOZ_INIT_OUTSIDE_CTOR /* nothing */