Bug 1493093 - Allow to relax MOZ_NON_TEMPORARY_CLASS for some specific constructors r=andi
authorMike Hommey <mh+mozilla@glandium.org>
Mon, 24 Sep 2018 22:47:12 +0000
changeset 437965 5c8f8fe4ef3e4e95526783d3781aebd14c9395df
parent 437964 a00ad29f71fed213dcfbb41d452a8cd675accf40
child 437966 73a8628576e4e6e6361065044d1dd8ee4296b10c
push id69862
push usermh@glandium.org
push dateMon, 24 Sep 2018 22:48:12 +0000
treeherderautoland@5c8f8fe4ef3e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersandi
bugs1493093
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1493093 - Allow to relax MOZ_NON_TEMPORARY_CLASS for some specific constructors r=andi Differential Revision: https://phabricator.services.mozilla.com/D6566
build/clang-plugin/CustomAttributes.inc
build/clang-plugin/CustomMatchers.h
build/clang-plugin/ScopeChecker.cpp
dom/bindings/BindingDeclarations.h
mfbt/Attributes.h
mfbt/Maybe.h
--- a/build/clang-plugin/CustomAttributes.inc
+++ b/build/clang-plugin/CustomAttributes.inc
@@ -1,8 +1,9 @@
+ATTR(moz_allow_temporary)
 ATTR(moz_can_run_script)
 ATTR(moz_can_run_script_boundary)
 ATTR(moz_global_class)
 ATTR(moz_heap_allocator)
 ATTR(moz_heap_class)
 ATTR(moz_implicit)
 ATTR(moz_inherit_type_annotations_from_template_args)
 ATTR(moz_is_smartptr_to_refcounted)
--- a/build/clang-plugin/CustomMatchers.h
+++ b/build/clang-plugin/CustomMatchers.h
@@ -24,16 +24,20 @@ AST_MATCHER(Decl, noArithmeticExprInArgs
 }
 
 /// This matcher will match any C++ class that is marked as having a trivial
 /// constructor and destructor.
 AST_MATCHER(CXXRecordDecl, hasTrivialCtorDtor) {
   return hasCustomAttribute<moz_trivial_ctor_dtor>(&Node);
 }
 
+AST_MATCHER(CXXConstructExpr, allowsTemporary) {
+  return hasCustomAttribute<moz_allow_temporary>(Node.getConstructor());
+}
+
 /// This matcher will match lvalue-ref-qualified methods.
 AST_MATCHER(CXXMethodDecl, isLValueRefQualified) {
   return Node.getRefQualifier() == RQ_LValue;
 }
 
 /// This matcher will match rvalue-ref-qualified methods.
 AST_MATCHER(CXXMethodDecl, isRValueRefQualified) {
   return Node.getRefQualifier() == RQ_RValue;
--- a/build/clang-plugin/ScopeChecker.cpp
+++ b/build/clang-plugin/ScopeChecker.cpp
@@ -3,17 +3,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ScopeChecker.h"
 #include "CustomMatchers.h"
 
 void ScopeChecker::registerMatchers(MatchFinder *AstMatcher) {
   AstMatcher->addMatcher(varDecl().bind("node"), this);
   AstMatcher->addMatcher(cxxNewExpr().bind("node"), this);
-  AstMatcher->addMatcher(materializeTemporaryExpr().bind("node"), this);
+  AstMatcher->addMatcher(
+      materializeTemporaryExpr(
+          unless(hasDescendant(cxxConstructExpr(allowsTemporary())))
+      ).bind("node"), this);
   AstMatcher->addMatcher(
       callExpr(callee(functionDecl(heapAllocator()))).bind("node"), this);
 }
 
 // These enum variants determine whether an allocation has occured in the code.
 enum AllocationVariety {
   AV_None,
   AV_Global,
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -216,31 +216,31 @@ private:
 protected:
   Maybe<InternalType> mImpl;
 };
 
 template<typename T>
 class Optional : public Optional_base<T, T>
 {
 public:
-  Optional() :
+  MOZ_ALLOW_TEMPORARY Optional() :
     Optional_base<T, T>()
   {}
 
   explicit Optional(const T& aValue) :
     Optional_base<T, T>(aValue)
   {}
 };
 
 template<typename T>
 class Optional<JS::Handle<T> > :
   public Optional_base<JS::Handle<T>, JS::Rooted<T> >
 {
 public:
-  Optional() :
+  MOZ_ALLOW_TEMPORARY Optional() :
     Optional_base<JS::Handle<T>, JS::Rooted<T> >()
   {}
 
   explicit Optional(JSContext* cx) :
     Optional_base<JS::Handle<T>, JS::Rooted<T> >()
   {
     this->Construct(cx);
   }
--- a/mfbt/Attributes.h
+++ b/mfbt/Attributes.h
@@ -593,16 +593,20 @@
  *   currently makes it a compile-time error to instantiate these classes
  *   anywhere other than at the global scope, or as a static member of a class.
  *   In non-debug mode, it also prohibits non-trivial constructors and
  *   destructors.
  * MOZ_TRIVIAL_CTOR_DTOR: Applies to all classes that must have both a trivial
  *   or constexpr constructor and a trivial destructor. Setting this attribute
  *   on a class makes it a compile-time error for that class to get a
  *   non-trivial constructor or destructor for any reason.
+ * MOZ_ALLOW_TEMPORARY: Applies to constructors. This indicates that using the
+ *   constructor is allowed in temporary expressions, if it would have otherwise
+ *   been forbidden by the type being a MOZ_NON_TEMPORARY_CLASS. Useful for
+ *   constructors like Maybe(Nothing).
  * MOZ_HEAP_ALLOCATOR: Applies to any function. This indicates that the return
  *   value is allocated on the heap, and will as a result check such allocations
  *   during MOZ_STACK_CLASS and MOZ_NONHEAP_CLASS annotation checking.
  * MOZ_IMPLICIT: Applies to constructors. Implicit conversion constructors
  *   are disallowed by default unless they are marked as MOZ_IMPLICIT. This
  *   attribute must be used for constructors which intend to provide implicit
  *   conversions.
  * MOZ_IS_REFPTR: Applies to class declarations of ref pointer to mark them as
@@ -716,16 +720,17 @@
 #  define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override")))
 #  define MOZ_STATIC_CLASS __attribute__((annotate("moz_global_class")))
 #  define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
 #  define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class")))
 #  define MOZ_HEAP_CLASS __attribute__((annotate("moz_heap_class")))
 #  define MOZ_NON_TEMPORARY_CLASS __attribute__((annotate("moz_non_temporary_class")))
 #  define MOZ_TEMPORARY_CLASS __attribute__((annotate("moz_temporary_class")))
 #  define MOZ_TRIVIAL_CTOR_DTOR __attribute__((annotate("moz_trivial_ctor_dtor")))
+#  define MOZ_ALLOW_TEMPORARY __attribute__((annotate("moz_allow_temporary")))
 #  ifdef DEBUG
      /* in debug builds, these classes do have non-trivial constructors. */
 #    define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class")))
 #  else
 #    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")))
@@ -771,16 +776,17 @@
 #  define MOZ_MUST_OVERRIDE /* nothing */
 #  define MOZ_STATIC_CLASS /* nothing */
 #  define MOZ_STACK_CLASS /* nothing */
 #  define MOZ_NONHEAP_CLASS /* nothing */
 #  define MOZ_HEAP_CLASS /* nothing */
 #  define MOZ_NON_TEMPORARY_CLASS /* nothing */
 #  define MOZ_TEMPORARY_CLASS /* nothing */
 #  define MOZ_TRIVIAL_CTOR_DTOR /* nothing */
+#  define MOZ_ALLOW_TEMPORARY /* nothing */
 #  define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS /* nothing */
 #  define MOZ_IMPLICIT /* nothing */
 #  define MOZ_IS_SMARTPTR_TO_REFCOUNTED /* nothing */
 #  define MOZ_IS_REFPTR /* 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 */
--- a/mfbt/Maybe.h
+++ b/mfbt/Maybe.h
@@ -177,22 +177,22 @@ class MOZ_NON_PARAM MOZ_INHERIT_TYPE_ANN
   void poisonData()
   {
     detail::MaybePoisoner<T>::poison(data());
   }
 
 public:
   using ValueType = T;
 
-  Maybe() : mIsSome(false)
+  MOZ_ALLOW_TEMPORARY Maybe() : mIsSome(false)
   {
   }
   ~Maybe() { reset(); }
 
-  MOZ_IMPLICIT Maybe(Nothing) : mIsSome(false)
+  MOZ_ALLOW_TEMPORARY MOZ_IMPLICIT Maybe(Nothing) : mIsSome(false)
   {
   }
 
   Maybe(const Maybe& aOther)
     : mIsSome(false)
   {
     if (aOther.mIsSome) {
       emplace(*aOther);