michael@0: #define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class"))) michael@0: #define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class"))) michael@0: #include michael@0: michael@0: struct MOZ_NONHEAP_CLASS NonHeap { michael@0: int i; michael@0: void *operator new(size_t x) { return 0; } michael@0: void *operator new(size_t blah, char *buffer) { return buffer; } michael@0: }; michael@0: michael@0: template michael@0: struct MOZ_NONHEAP_CLASS TemplateClass { michael@0: T i; michael@0: }; michael@0: michael@0: void gobble(void *) { } michael@0: michael@0: void misuseNonHeapClass(int len) { michael@0: NonHeap valid; michael@0: NonHeap alsoValid[2]; michael@0: static NonHeap validStatic; michael@0: static NonHeap alsoValidStatic[2]; michael@0: michael@0: gobble(&valid); michael@0: gobble(&validStatic); michael@0: gobble(&alsoValid[0]); michael@0: michael@0: gobble(new NonHeap); // expected-error {{variable of type 'NonHeap' is not valid on the heap}} michael@0: gobble(new NonHeap[10]); // expected-error {{variable of type 'NonHeap' is not valid on the heap}} michael@0: gobble(new TemplateClass); // expected-error {{variable of type 'TemplateClass' is not valid on the heap}} michael@0: gobble(len <= 5 ? &valid : new NonHeap); // expected-error {{variable of type 'NonHeap' is not valid on the heap}} michael@0: michael@0: char buffer[sizeof(NonHeap)]; michael@0: gobble(new (buffer) NonHeap); michael@0: } michael@0: michael@0: NonHeap validStatic; michael@0: struct RandomClass { michael@0: NonHeap nonstaticMember; // expected-note {{'RandomClass' is a non-heap class because member 'nonstaticMember' is a non-heap class 'NonHeap'}} michael@0: static NonHeap staticMember; michael@0: }; michael@0: struct MOZ_NONHEAP_CLASS RandomNonHeapClass { michael@0: NonHeap nonstaticMember; michael@0: static NonHeap staticMember; michael@0: }; michael@0: michael@0: struct BadInherit : NonHeap {}; // expected-note {{'BadInherit' is a non-heap class because it inherits from a non-heap class 'NonHeap'}} michael@0: struct MOZ_NONHEAP_CLASS GoodInherit : NonHeap {}; michael@0: michael@0: void useStuffWrongly() { michael@0: gobble(new BadInherit); // expected-error {{variable of type 'BadInherit' is not valid on the heap}} michael@0: gobble(new RandomClass); // expected-error {{variable of type 'RandomClass' is not valid on the heap}} michael@0: } michael@0: michael@0: // Stack class overrides non-heap classes. michael@0: struct MOZ_STACK_CLASS StackClass {}; michael@0: struct MOZ_NONHEAP_CLASS InferredStackClass : GoodInherit { michael@0: NonHeap nonstaticMember; michael@0: StackClass stackClass; // expected-note {{'InferredStackClass' is a stack class because member 'stackClass' is a stack class 'StackClass'}} michael@0: }; michael@0: michael@0: InferredStackClass global; // expected-error {{variable of type 'InferredStackClass' only valid on the stack}}