Bug 885515 - Part 1: Add an analysis for detecting non-heap allocations of MOZ_HEAP_CLASS, r=ehsan
authorMichael Layzell <michael@thelayzells.com>
Thu, 06 Aug 2015 14:07:04 -0700
changeset 288682 a9fd67edcf192e9fc8a32a5fac64d5a19363359a
parent 288681 0d6871d66dc07cda204c3814a488f6dafe019507
child 288683 f90e57c732b03c5aba62dbebbfe6511438f20db4
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs885515
milestone42.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 885515 - Part 1: Add an analysis for detecting non-heap allocations of MOZ_HEAP_CLASS, r=ehsan
build/clang-plugin/clang-plugin.cpp
build/clang-plugin/tests/TestHeapClass.cpp
build/clang-plugin/tests/moz.build
--- a/build/clang-plugin/clang-plugin.cpp
+++ b/build/clang-plugin/clang-plugin.cpp
@@ -257,16 +257,18 @@ private:
 };
 
 static CustomTypeAnnotation StackClass =
   CustomTypeAnnotation("moz_stack_class", "stack");
 static CustomTypeAnnotation GlobalClass =
   CustomTypeAnnotation("moz_global_class", "global");
 static CustomTypeAnnotation NonHeapClass =
   CustomTypeAnnotation("moz_nonheap_class", "non-heap");
+static CustomTypeAnnotation HeapClass =
+  CustomTypeAnnotation("moz_heap_class", "heap");
 static CustomTypeAnnotation MustUse =
   CustomTypeAnnotation("moz_must_use", "must-use");
 
 class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
   DiagnosticsEngine &Diag;
   const CompilerInstance &CI;
   DiagnosticsMatcher matcher;
 public:
@@ -1098,32 +1100,47 @@ void DiagnosticsMatcher::ScopeChecker::r
     return;
 
   case AV_Global:
     if (StackClass.hasEffectiveAnnotation(T)) {
       Diag.Report(Loc, StackID) << T;
       Diag.Report(Loc, GlobalNoteID);
       StackClass.dumpAnnotationReason(Diag, T, Loc);
     }
+    if (HeapClass.hasEffectiveAnnotation(T)) {
+      Diag.Report(Loc, HeapID) << T;
+      Diag.Report(Loc, GlobalNoteID);
+      HeapClass.dumpAnnotationReason(Diag, T, Loc);
+    }
     break;
 
   case AV_Automatic:
     if (GlobalClass.hasEffectiveAnnotation(T)) {
       Diag.Report(Loc, GlobalID) << T;
       Diag.Report(Loc, StackNoteID);
       GlobalClass.dumpAnnotationReason(Diag, T, Loc);
     }
+    if (HeapClass.hasEffectiveAnnotation(T)) {
+      Diag.Report(Loc, HeapID) << T;
+      Diag.Report(Loc, StackNoteID);
+      HeapClass.dumpAnnotationReason(Diag, T, Loc);
+    }
     break;
 
   case AV_Temporary:
     if (GlobalClass.hasEffectiveAnnotation(T)) {
       Diag.Report(Loc, GlobalID) << T;
       Diag.Report(Loc, TemporaryNoteID);
       GlobalClass.dumpAnnotationReason(Diag, T, Loc);
     }
+    if (HeapClass.hasEffectiveAnnotation(T)) {
+      Diag.Report(Loc, HeapID) << T;
+      Diag.Report(Loc, TemporaryNoteID);
+      HeapClass.dumpAnnotationReason(Diag, T, Loc);
+    }
     break;
 
   case AV_Heap:
     if (GlobalClass.hasEffectiveAnnotation(T)) {
       Diag.Report(Loc, GlobalID) << T;
       Diag.Report(Loc, HeapNoteID);
       GlobalClass.dumpAnnotationReason(Diag, T, Loc);
     }
new file mode 100644
--- /dev/null
+++ b/build/clang-plugin/tests/TestHeapClass.cpp
@@ -0,0 +1,64 @@
+#define MOZ_HEAP_CLASS __attribute__((annotate("moz_heap_class")))
+#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
+
+#include <stddef.h>
+
+struct MOZ_HEAP_CLASS Heap {
+  int i;
+  Heap() {}
+  MOZ_IMPLICIT Heap(int i) {}
+  Heap(int i, int j) {}
+  void *operator new(size_t x) throw() { return 0; }
+  void *operator new(size_t blah, char *buffer) { return buffer; }
+};
+
+template <class T>
+struct MOZ_HEAP_CLASS TemplateClass {
+  T i;
+};
+
+void gobble(void *) { }
+
+void gobbleref(const Heap&) { }
+
+void misuseHeapClass(int len) {
+  Heap invalid; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}}
+  Heap alsoInvalid[2]; // expected-error {{variable of type 'Heap [2]' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}} expected-note {{'Heap [2]' is a heap type because it is an array of heap type 'Heap'}}
+  static Heap invalidStatic; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
+  static Heap alsoInvalidStatic[2]; // expected-error {{variable of type 'Heap [2]' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}} expected-note {{'Heap [2]' is a heap type because it is an array of heap type 'Heap'}}
+
+  gobble(&invalid);
+  gobble(&invalidStatic);
+  gobble(&alsoInvalid[0]);
+
+  gobbleref(Heap()); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleref(Heap(10, 20)); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleref(Heap(10)); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleref(10); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
+
+  gobble(new Heap);
+  gobble(new Heap[10]);
+  gobble(new TemplateClass<int>);
+  gobble(len <= 5 ? &invalid : new Heap);
+
+  char buffer[sizeof(Heap)];
+  gobble(new (buffer) Heap);
+}
+
+Heap invalidStatic; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
+struct RandomClass {
+  Heap nonstaticMember; // expected-note {{'RandomClass' is a heap type because member 'nonstaticMember' is a heap type 'Heap'}}
+  static Heap staticMember; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
+};
+struct MOZ_HEAP_CLASS RandomHeapClass {
+  Heap nonstaticMember;
+  static Heap staticMember; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
+};
+
+struct BadInherit : Heap {}; // expected-note {{'BadInherit' is a heap type because it inherits from a heap type 'Heap'}}
+struct MOZ_HEAP_CLASS GoodInherit : Heap {};
+
+void useStuffWrongly() {
+  BadInherit i; // expected-error {{variable of type 'BadInherit' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}}
+  RandomClass r; // expected-error {{variable of type 'RandomClass' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}}
+}
--- a/build/clang-plugin/tests/moz.build
+++ b/build/clang-plugin/tests/moz.build
@@ -4,16 +4,17 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SOURCES += [
     'TestBadImplicitConversionCtor.cpp',
     'TestCustomHeap.cpp',
     'TestExplicitOperatorBool.cpp',
     'TestGlobalClass.cpp',
+    'TestHeapClass.cpp',
     'TestInheritTypeAnnotationsFromTemplateArgs.cpp',
     'TestMultipleAnnotations.cpp',
     'TestMustOverride.cpp',
     'TestMustUse.cpp',
     'TestNANTestingExpr.cpp',
     'TestNANTestingExprC.c',
     'TestNeedsNoVTableType.cpp',
     'TestNoAddRefReleaseOnReturn.cpp',