summaryrefslogtreecommitdiff
path: root/xpcom
diff options
context:
space:
mode:
authortrav90 <travawine@protonmail.ch>2015-12-04 17:07:29 -0600
committertrav90 <travawine@protonmail.ch>2015-12-04 17:07:29 -0600
commit773b1154970428172e80ea737d5f4506a2823493 (patch)
tree9b2f3c8f8f7e6aaa512ac492a32e7e5702c5d6c1 /xpcom
parent5e7e0080bb7452e3c63b5f990fa6f6ee3d3c3aeb (diff)
downloadpalemoon-gre-773b1154970428172e80ea737d5f4506a2823493.tar.gz
Remove GCC-dehydra support
Diffstat (limited to 'xpcom')
-rwxr-xr-xxpcom/analysis/MDC-attach.py23
-rwxr-xr-xxpcom/analysis/MDC-upload.py22
-rw-r--r--xpcom/analysis/Makefile.in53
-rw-r--r--xpcom/analysis/deki.py346
-rwxr-xr-xxpcom/analysis/fix-srcrefs.py41
-rw-r--r--xpcom/analysis/flow.js150
-rw-r--r--xpcom/analysis/mayreturn.js44
-rw-r--r--xpcom/analysis/moz.build6
-rw-r--r--xpcom/analysis/must-override.js52
-rw-r--r--xpcom/analysis/outparams.js880
-rw-r--r--xpcom/analysis/stack.js159
-rw-r--r--xpcom/analysis/static-init.js58
-rw-r--r--xpcom/analysis/type-printer.cpp7
-rw-r--r--xpcom/analysis/type-printer.js402
-rw-r--r--xpcom/moz.build3
-rw-r--r--xpcom/tests/moz.build3
-rw-r--r--xpcom/tests/static-checker/Makefile.in153
-rw-r--r--xpcom/tests/static-checker/TestStaticInitAttr.cpp5
-rw-r--r--xpcom/tests/static-checker/TestStaticInitConstructor.cpp7
-rw-r--r--xpcom/tests/static-checker/TestStaticInitGlobal.cpp5
-rw-r--r--xpcom/tests/static-checker/TestStaticInitGlobalConst.cpp5
-rw-r--r--xpcom/tests/static-checker/TestStaticInitStructOK.cpp5
-rw-r--r--xpcom/tests/static-checker/flow_through_fail.cpp16
-rw-r--r--xpcom/tests/static-checker/flow_through_pass.cpp20
-rw-r--r--xpcom/tests/static-checker/moz.build6
25 files changed, 0 insertions, 2471 deletions
diff --git a/xpcom/analysis/MDC-attach.py b/xpcom/analysis/MDC-attach.py
deleted file mode 100755
index bbeae6f6d..000000000
--- a/xpcom/analysis/MDC-attach.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-# This Source Code Form is subject to the terms of the Mozilla Public
-# 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/.
-
-
-"""
-Upload a file attachment to MDC
-
-Usage: python MDC-attach.py <file> <parent page name> <MIME type> <description>
-Please set MDC_USER and MDC_PASSWORD in the environment
-"""
-
-import os, sys, deki
-
-wikiuser = os.environ['MDC_USER']
-wikipw = os.environ['MDC_PASSWORD']
-
-file, pageid, mimetype, description = sys.argv[1:]
-
-wiki = deki.Deki("http://developer.mozilla.org/@api/deki/", wikiuser, wikipw)
-wiki.create_file(pageid, os.path.basename(file), open(file).read(), mimetype,
- description)
diff --git a/xpcom/analysis/MDC-upload.py b/xpcom/analysis/MDC-upload.py
deleted file mode 100755
index e1691308f..000000000
--- a/xpcom/analysis/MDC-upload.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-# This Source Code Form is subject to the terms of the Mozilla Public
-# 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/.
-
-
-"""
-Upload a page to MDC
-
-Usage: python MDC-upload.py <file> <MDC-path>
-Please set MDC_USER and MDC_PASSWORD in the environment
-"""
-
-import os, sys, deki
-
-wikiuser = os.environ['MDC_USER']
-wikipw = os.environ['MDC_PASSWORD']
-
-(file, wikipath) = sys.argv[1:]
-
-wiki = deki.Deki("http://developer.mozilla.org/@api/deki/", wikiuser, wikipw)
-wiki.create_page(wikipath, open(file).read(), overwrite=True)
diff --git a/xpcom/analysis/Makefile.in b/xpcom/analysis/Makefile.in
deleted file mode 100644
index 96d99f9af..000000000
--- a/xpcom/analysis/Makefile.in
+++ /dev/null
@@ -1,53 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# 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/.
-
-DEPTH = @DEPTH@
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MOZILLA_INTERNAL_API = 1
-
-include $(topsrcdir)/config/rules.mk
-
-DUMP_CLASSES = \
- nsAString_internal \
- nsACString_internal \
- $(NULL)
-
-SPACE = $(NULL) $(NULL)
-COMMA = ,
-
-HGREV = $(shell hg -R $(topsrcdir) id -i)
-
-classapi: DEHYDRA_MODULES = $(srcdir)/type-printer.js
-classapi: TREEHYDRA_MODULES =
-classapi: DEHYDRA_ARGS += --dump-types=$(subst $(SPACE),$(COMMA),$(strip $(DUMP_CLASSES))) --rev=$(HGREV)
-classapi: $(call mkdir_deps,$(MDDEPDIR))
- $(CCC) $(OUTOPTION)/dev/null -c $(COMPILE_CXXFLAGS) $(srcdir)/type-printer.cpp >classapi.out 2>&1
- perl -e 'while (<>) {if (/DUMP-TYPE\((.*)\)/) {print "$$1 ";}}' <classapi.out >dumptypes.list
- perl -e 'while (<>) {if (/GRAPH-TYPE\((.*)\)/) {print "$$1 ";}}' <classapi.out >graphtypes.list
- $(EXIT_ON_ERROR) \
- for class in `cat graphtypes.list`; do \
- dot -Tpng -o$${class}-graph.png -Tcmapx -o$${class}-graph.map $${class}-graph.gv; \
- done
- $(EXIT_ON_ERROR) \
- for class in `cat dumptypes.list`; do \
- $(PYTHON) $(srcdir)/fix-srcrefs.py $(topsrcdir) < $${class}.html > $${class}-fixed.html; \
- done
-
-upload_classapi:
- $(EXIT_ON_ERROR) \
- for class in `cat dumptypes.list`; do \
- $(PYTHON) $(srcdir)/MDC-upload.py $${class}-fixed.html en/$${class}; \
- done
- $(EXIT_ON_ERROR) \
- for class in `cat graphtypes.list`; do \
- $(PYTHON) $(srcdir)/MDC-attach.py $${class}-graph.png en/$${class} "image/png" "Class inheritance graph"; \
- done
-
-GARBAGE += $(wildcard *.html) $(wildcard *.png) $(wildcard *.map) \
- $(wildcard *.gv) classapi.out graphtypes.list dumptypes.list
diff --git a/xpcom/analysis/deki.py b/xpcom/analysis/deki.py
deleted file mode 100644
index 52814a6de..000000000
--- a/xpcom/analysis/deki.py
+++ /dev/null
@@ -1,346 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# 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/.
-
-""" deki.py - Access the wiki pages on a MindTouch Deki server via the API.
-
-Here's what this code can do:
-
- wiki = deki.Deki("http://developer.mozilla.org/@api/deki/", username, password)
- page = wiki.get_page("Sheep")
- print page.title
- print page.doc.toxml()
-
- page.title = "Bananas"
- page.save()
-
-There are also some additional methods:
- wiki.create_page(path, content, title=, override=)
- wiki.move_page(old, new)
- wiki.get_subpages(page)
-
-This module does not try to mimic the MindTouch "Plug" API. It's meant to be
-higher-level than that.
-"""
-
-import sys
-import urllib2, cookielib, httplib
-import xml.dom.minidom as dom
-from urllib import quote as _urllib_quote
-from urllib import urlencode as _urlencode
-import urlparse
-from datetime import datetime
-import re
-
-__all__ = ['Deki']
-
-
-# === Utils
-
-def _check(fact):
- if not fact:
- raise AssertionError('check failed')
-
-def _urlquote(s, *args):
- return _urllib_quote(s.encode('utf-8'), *args)
-
-def _make_url(*dirs, **params):
- """ dirs must already be url-encoded, params must not """
- url = '/'.join(dirs)
- if params:
- url += '?' + _urlencode(params)
- return url
-
-class PutRequest(urllib2.Request):
- def get_method(self):
- return "PUT"
-
-# === Dream framework client code
-
-# This handler causes python to "always be logged in" when it's talking to the
-# server. If you're just accessing public pages, it generates more requests
-# than are strictly needed, but this is the behavior you want for a bot.
-#
-# The users/authenticate request is sent twice: once without any basic auth and
-# once with. Dumb. Feel free to fix.
-#
-class _LoginHandler(urllib2.HTTPCookieProcessor):
- def __init__(self, server):
- policy = cookielib.DefaultCookiePolicy(rfc2965=True)
- cookiejar = cookielib.CookieJar(policy)
- urllib2.HTTPCookieProcessor.__init__(self, cookiejar)
- self.server = server
-
- def http_request(self, req):
- #print "DEBUG- Requesting " + req.get_full_url()
- s = self.server
- req = urllib2.HTTPCookieProcessor.http_request(self, req)
- if ('Cookie' not in req.unredirected_hdrs
- and req.get_full_url() != s.base + 'users/authenticate'):
- s.login()
- # Retry - should have a new cookie.
- req = urllib2.HTTPCookieProcessor.http_request(self, req)
- _check('Cookie' in req.unredirected_hdrs)
- return req
-
-class DreamClient:
- def __init__(self, base, user, password):
- """
- base - The base URI of the Deki API, with trailing slash.
- Typically, 'http://wiki.example.org/@api/deki/'.
- user, password - Your Deki login information.
- """
- self.base = base
- pm = urllib2.HTTPPasswordMgrWithDefaultRealm()
- pm.add_password(None, self.base, user, password)
- ah = urllib2.HTTPBasicAuthHandler(pm)
- lh = _LoginHandler(self)
- self._opener = urllib2.build_opener(ah, lh)
-
- def login(self):
- response = self._opener.open(self.base + 'users/authenticate')
- response.close()
-
- def open(self, url):
- return self._opener.open(self.base + url)
-
- def _handleResponse(self, req):
- """Helper method shared between post() and put()"""
- resp = self._opener.open(req)
- try:
- ct = resp.headers.get('Content-Type', '(none)')
- if '/xml' in ct or '+xml' in ct:
- return dom.parse(resp)
- else:
- #print "DEBUG- Content-Type:", ct
- crud = resp.read()
- #print 'DEBUG- crud:\n---\n%s\n---' % re.sub(r'(?m)^', ' ', crud)
- return None
- finally:
- resp.close()
-
-
- def post(self, url, data, type):
- #print "DEBUG- posting to:", self.base + url
- req = urllib2.Request(self.base + url, data, {'Content-Type': type})
- return self._handleResponse(req)
-
- def put(self, url, data, type):
- #print "DEBUG- putting to:", self.base + url
- req = PutRequest(self.base + url, data, {'Content-Type': type})
- return self._handleResponse(req)
-
- def get_xml(self, url):
- resp = self.open(url)
- try:
- return dom.parse(resp)
- finally:
- resp.close()
-
-
-# === DOM
-
-def _text_of(node):
- if node.nodeType == node.ELEMENT_NODE:
- return u''.join(_text_of(n) for n in node.childNodes)
- elif node.nodeType == node.TEXT_NODE:
- return node.nodeValue
- else:
- return u''
-
-def _the_element_by_name(doc, tagName):
- elts = doc.getElementsByTagName(tagName)
- if len(elts) != 1:
- raise ValueError("Expected exactly one <%s> tag, got %d." % (tagName, len(elts)))
- return elts[0]
-
-def _first_element(node):
- n = node.firstChild
- while n is not None:
- if n.nodeType == n.ELEMENT_NODE:
- return n
- n = node.nextSibling
- return None
-
-def _find_elements(node, path):
- if u'/' in path:
- [first, rest] = path.split(u'/', 1)
- for child in _find_elements(node, first):
- for desc in _find_elements(child, rest):
- yield desc
- else:
- for n in node.childNodes:
- if n.nodeType == node.ELEMENT_NODE and n.nodeName == path:
- yield n
-
-
-# === Deki
-
-def _format_page_id(id):
- if isinstance(id, int):
- return str(id)
- elif id is Deki.HOME:
- return 'home'
- elif isinstance(id, basestring):
- # Double-encoded, per the Deki API reference.
- return '=' + _urlquote(_urlquote(id, ''))
-
-class Deki(DreamClient):
- HOME = object()
-
- def get_page(self, page_id):
- """ Get the content of a page from the wiki.
-
- The page_id argument must be one of:
- an int - The page id (an arbitrary number assigned by Deki)
- a str - The page name (not the title, the full path that shows up in the URL)
- Deki.HOME - Refers to the main page of the wiki.
-
- Returns a Page object.
- """
- p = Page(self)
- p._load(page_id)
- return p
-
- def create_page(self, path, content, title=None, overwrite=False):
- """ Create a new wiki page.
-
- Parameters:
- path - str - The page id.
- content - str - The XML content to put in the new page.
- The document element must be a <body>.
- title - str - The page title. Keyword argument only.
- Defaults to the last path-segment of path.
- overwrite - bool - Whether to overwrite an existing page. If false,
- and the page already exists, the method will throw an error.
- """
- if title is None:
- title = path.split('/')[-1]
- doc = dom.parseString(content)
- _check(doc.documentElement.tagName == 'body')
- p = Page(self)
- p._create(path, title, doc, overwrite)
-
- def attach_file(self, page, name, data, mimetype, description=None):
- """Create or update a file attachment.
-
- Parameters:
- page - str - the page ID this file is related to
- name - str - the name of the file
- data - str - the file data
- mimetype - str - the MIME type of the file
- description - str - a description of the file
- """
-
- p = {}
- if description is not None:
- p['description'] = description
-
- url = _make_url('pages', _format_page_id(page),
- 'files', _format_page_id(name), **p)
-
- r = self.put(url, data, mimetype)
- _check(r.documentElement.nodeName == u'file')
-
- def get_subpages(self, page_id):
- """ Return the ids of all subpages of the given page. """
- doc = self.get_xml(_make_url("pages", _format_page_id(page_id),
- "files,subpages"))
- for elt in _find_elements(doc, u'page/subpages/page.subpage/path'):
- yield _text_of(elt)
-
- def move_page(self, page_id, new_title, redirects=True):
- """ Move an existing page to a new location.
-
- A page cannot be moved to a destination that already exists, is a
- descendant, or has a protected title (ex. Special:xxx, User:,
- Template:).
-
- When a page is moved, subpages under the specified page are also moved.
- For each moved page, the system automatically creates an alias page
- that redirects from the old to the new destination.
- """
- self.post(_make_url("pages", _format_page_id(page_id), "move",
- to=new_title,
- redirects=redirects and "1" or "0"),
- "", "text/plain")
-
-class Page:
- """ A Deki wiki page.
-
- To obtain a page, call wiki.get_page(id).
- Attributes:
- title : unicode - The page title.
- doc : Document - The content of the page as a DOM Document.
- The root element of this document is a <body>.
- path : unicode - The path. Use this to detect redirects, as otherwise
- page.save() will overwrite the redirect with a copy of the content!
- deki : Deki - The Deki object from which the page was loaded.
- page_id : str/id/Deki.HOME - The page id used to load the page.
- load_time : datetime - The time the page was loaded,
- according to the clock on the client machine.
- Methods:
- save() - Save the modified document back to the server.
- Only the page.title and the contents of page.doc are saved.
- """
-
- def __init__(self, deki):
- self.deki = deki
-
- def _create(self, path, title, doc, overwrite):
- self.title = title
- self.doc = doc
- self.page_id = path
- if overwrite:
- self.load_time = datetime(2500, 1, 1)
- else:
- self.load_time = datetime(1900, 1, 1)
- self.path = path
- self.save()
-
- def _load(self, page_id):
- """ page_id - See comment near the definition of `HOME`. """
- load_time = datetime.utcnow()
-
- # Getting the title is a whole separate query!
- url = 'pages/%s/info' % _format_page_id(page_id)
- doc = self.deki.get_xml(url)
- title = _text_of(_the_element_by_name(doc, 'title'))
- path = _text_of(_the_element_by_name(doc, 'path'))
-
- # If you prefer to sling regexes, you can request format=raw instead.
- # The result is an XML document with one big fat text node in the body.
- url = _make_url('pages', _format_page_id(page_id), 'contents',
- format='xhtml', mode='edit')
- doc = self.deki.get_xml(url)
-
- content = doc.documentElement
- _check(content.tagName == u'content')
- body = _first_element(content)
- _check(body is not None)
- _check(body.tagName == u'body')
-
- doc.removeChild(content)
- doc.appendChild(body)
-
- self.page_id = page_id
- self.load_time = load_time
- self.title = title
- self.path = path
- self.doc = doc
-
- def save(self):
- p = {'edittime': _urlquote(self.load_time.strftime('%Y%m%d%H%M%S')),
- 'abort': 'modified'}
-
- if self.title is not None:
- p['title'] = _urlquote(self.title)
-
- url = _make_url('pages', _format_page_id(self.page_id), 'contents', **p)
-
- body = self.doc.documentElement
- bodyInnerXML = ''.join(n.toxml('utf-8') for n in body.childNodes)
-
- reply = self.deki.post(url, bodyInnerXML, 'text/plain; charset=utf-8')
- _check(reply.documentElement.nodeName == u'edit')
- _check(reply.documentElement.getAttribute(u'status') == u'success')
diff --git a/xpcom/analysis/fix-srcrefs.py b/xpcom/analysis/fix-srcrefs.py
deleted file mode 100755
index 30cc9efea..000000000
--- a/xpcom/analysis/fix-srcrefs.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python
-# This Source Code Form is subject to the terms of the Mozilla Public
-# 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/.
-
-
-"""
-Fix references to source files of the form [LOCpath]
-so that they are relative to a given source directory.
-
-Substitute the DOT-generated image map into the document.
-"""
-
-import os, sys, re
-
-(srcdir, ) = sys.argv[1:]
-srcdir = os.path.realpath(srcdir)
-
-f = re.compile(r'\[LOC(.*?)\]')
-
-def replacer(m):
- file = m.group(1)
- file = os.path.realpath(file)
- if not file.startswith(srcdir):
- raise Exception("File %s doesn't start with %s" % (file, srcdir))
-
- file = file[len(srcdir) + 1:]
- return file
-
-s = re.compile(r'\[MAP(.*?)\]')
-
-def mapreplace(m):
- file = m.group(1)
- c = open(file).read()
- return c
-
-for line in sys.stdin:
- line = f.sub(replacer, line)
- line = s.sub(mapreplace, line)
-
- sys.stdout.write(line)
diff --git a/xpcom/analysis/flow.js b/xpcom/analysis/flow.js
deleted file mode 100644
index 5153f3056..000000000
--- a/xpcom/analysis/flow.js
+++ /dev/null
@@ -1,150 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-require({ version: '1.8' });
-require({ after_gcc_pass: 'cfg' });
-
-include('treehydra.js');
-
-include('util.js');
-include('gcc_util.js');
-include('gcc_print.js');
-include('unstable/adts.js');
-include('unstable/analysis.js');
-include('unstable/esp.js');
-
-/* This implements the control flows-through analysis in bug 432917 */
-var Zero_NonZero = {}
-include('unstable/zero_nonzero.js', Zero_NonZero);
-
-MapFactory.use_injective = true;
-
-// Print a trace for each function analyzed
-let TRACE_FUNCTIONS = 0;
-// Trace operation of the ESP analysis, use 2 or 3 for more detail
-let TRACE_ESP = 0;
-// Print time-taken stats
-let TRACE_PERF = 0;
-
-function process_tree(fndecl) {
- // At this point we have a function we want to analyze
- if (TRACE_FUNCTIONS) {
- print('* function ' + decl_name(fndecl));
- print(' ' + loc_string(location_of(fndecl)));
- }
- if (TRACE_PERF) timer_start(fstring);
-
- let cfg = function_decl_cfg(fndecl);
-
- try {
- let trace = TRACE_ESP;
- let a = new FlowCheck(cfg, trace);
- a.run();
- } catch (e if e == "skip") {
- return
- }
- print("checked " + decl_name(fndecl))
- if (cfg.x_exit_block_ptr.stateIn.substates)
- for each (let substate in cfg.x_exit_block_ptr.stateIn.substates.getValues()) {
- for each (let v in substate.getVariables()) {
- let var_state= substate.get (v)
- let blame = substate.getBlame(v)
- if (var_state != ESP.TOP && typeof var_state == 'string')
- error(decl_name(fndecl) + ": Control did not flow through " +var_state, location_of(blame))
- }
- }
-
- if (TRACE_PERF) timer_stop(fstring);
-}
-
-let track_return_loc = 0;
-const FLOW_THROUGH = "MUST_FLOW_THROUGH"
-
-function FlowCheck(cfg, trace) {
- let found = create_decl_set(); // ones we already found
- for (let bb in cfg_bb_iterator(cfg)) {
- for (let isn in bb_isn_iterator(bb)) {
- switch (isn.tree_code()) {
- case GIMPLE_CALL: {
- let fn = gimple_call_fndecl(isn)
- if (!fn || decl_name(fn) != FLOW_THROUGH)
- continue;
- this.must_flow_fn = fn
- break
- }
- case GIMPLE_RETURN:
- let ret_expr = return_expr(isn);
- if (track_return_loc && ret_expr) {
- TREE_CHECK(ret_expr, VAR_DECL, RESULT_DECL);
- this.rval = ret_expr;
- }
- break;
- }
- }
- }
- if (!this.must_flow_fn)
- throw "skip"
-
- let psvar_list = [new ESP.PropVarSpec(this.must_flow_fn, true)]
-
- if (this.rval)
- psvar_list.push(new ESP.PropVarSpec(this.rval))
-
- this.zeroNonzero = new Zero_NonZero.Zero_NonZero()
- ESP.Analysis.call(this, cfg, psvar_list, Zero_NonZero.meet, trace);
-}
-
-FlowCheck.prototype = new ESP.Analysis;
-
-function char_star_arg2string(tree) {
- return TREE_STRING_POINTER(tree.tree_check(ADDR_EXPR).operands()[0].tree_check(ARRAY_REF).operands()[0])
-}
-
-// State transition function. Mostly, we delegate everything to
-// another function as either an assignment or a call.
-FlowCheck.prototype.flowState = function(isn, state) {
- switch (TREE_CODE(isn)) {
- case GIMPLE_CALL: {
- let fn = gimple_call_fndecl(isn)
- if (fn == this.must_flow_fn)
- state.assignValue(fn, char_star_arg2string(gimple_call_arg(isn, 0)), isn)
- break
- }
- case GIMPLE_LABEL: {
- let label = decl_name(gimple_op(isn, 0))
- for ([value, blame] in state.yieldPreconditions(this.must_flow_fn)) {
- if (label != value) continue
- // reached the goto label we wanted =D
- state.assignValue(this.must_flow_fn, ESP.TOP, isn)
- }
- break
- }
- case GIMPLE_RETURN:
- for ([value, blame] in state.yieldPreconditions(this.must_flow_fn)) {
- if (typeof value != 'string') continue
- let loc;
- if (this.rval)
- for ([value, blame] in state.yieldPreconditions(this.rval)) {
- loc = value
- break
- }
- error("return without going through label "+ value, loc);
- return
- }
- break
- case GIMPLE_ASSIGN:
- if (track_return_loc && gimple_op(isn, 0) == this.rval) {
- state.assignValue(this.rval, location_of(isn), isn)
- break
- }
- default:
- this.zeroNonzero.flowState(isn, state)
- }
-}
-
-// State transition function to apply branch filters. This is kind
-// of boilerplate--we're just handling some stuff that GCC generates.
-FlowCheck.prototype.flowStateCond = function(isn, truth, state) {
- this.zeroNonzero.flowStateCond (isn, truth, state)
-}
diff --git a/xpcom/analysis/mayreturn.js b/xpcom/analysis/mayreturn.js
deleted file mode 100644
index 9a9779749..000000000
--- a/xpcom/analysis/mayreturn.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-/* May-return analysis.
- * This makes sense only for functions that return a value. The analysis
- * determines the set of variables that may transitively reach the return
- * statement. */
-
-function MayReturnAnalysis() {
- BackwardAnalysis.apply(this, arguments);
- // May-return variables. We collect them all here.
- this.vbls = create_decl_set();
- // The return value variable itself
- this.retvar = undefined;
-}
-
-MayReturnAnalysis.prototype = new BackwardAnalysis;
-
-MayReturnAnalysis.prototype.flowState = function(isn, state) {
- if (TREE_CODE(isn) == GIMPLE_RETURN) {
- let v = return_expr(isn);
- if (!v)
- return;
- if (v.tree_code() == RESULT_DECL) // only an issue with 4.3
- throw new Error("Weird case hit");
- this.vbls.add(v);
- state.add(v);
- this.retvar = v;
- } else if (TREE_CODE(isn) == GIMPLE_ASSIGN) {
- let lhs = gimple_op(isn, 0);
- let rhs = gimple_op(isn, 1);
- if (DECL_P(rhs) && DECL_P(lhs) && state.has(lhs)) {
- this.vbls.add(rhs);
- state.add(rhs);
- }
-
- for (let e in isn_defs(isn, 'strong')) {
- if (DECL_P(e)) {
- state.remove(e);
- }
- }
- }
-};
diff --git a/xpcom/analysis/moz.build b/xpcom/analysis/moz.build
deleted file mode 100644
index 895d11993..000000000
--- a/xpcom/analysis/moz.build
+++ /dev/null
@@ -1,6 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# 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/.
-
diff --git a/xpcom/analysis/must-override.js b/xpcom/analysis/must-override.js
deleted file mode 100644
index 4d1ed6115..000000000
--- a/xpcom/analysis/must-override.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-/*
- * Detect classes that should have overridden members of their parent
- * classes but didn't.
- *
- * Example:
- *
- * struct S {
- * virtual NS_MUST_OVERRIDE void f();
- * virtual void g();
- * };
- *
- * struct A : S { virtual void f(); }; // ok
- * struct B : S { virtual NS_MUST_OVERRIDE void f(); }; // also ok
- *
- * struct C : S { virtual void g(); }; // ERROR: must override f()
- * struct D : S { virtual void f(int); }; // ERROR: different overload
- * struct E : A { }; // ok: A's definition of f() is good for subclasses
- * struct F : B { }; // ERROR: B's definition of f() is still must-override
- *
- * We don't care if you define the method or not.
- */
-
-function get_must_overrides(cls)
-{
- let mos = {};
- for each (let base in cls.bases)
- for each (let m in base.type.members)
- if (hasAttribute(m, 'NS_must_override'))
- mos[m.shortName] = m;
-
- return mos;
-}
-
-function process_type(t)
-{
- if (t.isIncomplete || (t.kind != 'class' && t.kind != 'struct'))
- return;
-
- let mos = get_must_overrides(t);
- for each (let m in t.members) {
- let mos_m = mos[m.shortName]
- if (mos_m && signaturesMatch(mos_m, m))
- delete mos[m.shortName];
- }
-
- for each (let u in mos)
- error(t.kind + " " + t.name + " must override " + u.name, t.loc);
-}
diff --git a/xpcom/analysis/outparams.js b/xpcom/analysis/outparams.js
deleted file mode 100644
index f789e30d0..000000000
--- a/xpcom/analysis/outparams.js
+++ /dev/null
@@ -1,880 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-require({ version: '1.8' });
-require({ after_gcc_pass: 'cfg' });
-
-include('treehydra.js');
-
-include('util.js');
-include('gcc_util.js');
-include('gcc_print.js');
-include('unstable/adts.js');
-include('unstable/analysis.js');
-include('unstable/esp.js');
-let Zero_NonZero = {};
-include('unstable/zero_nonzero.js', Zero_NonZero);
-
-include('xpcom/analysis/mayreturn.js');
-
-function safe_location_of(t) {
- if (t === undefined)
- return UNKNOWN_LOCATION;
-
- return location_of(t);
-}
-
-MapFactory.use_injective = true;
-
-// Print a trace for each function analyzed
-let TRACE_FUNCTIONS = 0;
-// Trace operation of the ESP analysis, use 2 or 3 for more detail
-let TRACE_ESP = 0;
-// Trace determination of function call parameter semantics, 2 for detail
-let TRACE_CALL_SEM = 0;
-// Print time-taken stats
-let TRACE_PERF = 0;
-// Log analysis results in a special format
-let LOG_RESULTS = false;
-
-const WARN_ON_SET_NULL = false;
-const WARN_ON_SET_FAILURE = false;
-
-// Filter functions to process per CLI
-let func_filter;
-if (this.arg == undefined || this.arg == '') {
- func_filter = function(fd) true;
-} else {
- func_filter = function(fd) function_decl_name(fd) == this.arg;
-}
-
-function process_tree(func_decl) {
- if (!func_filter(func_decl)) return;
-
- // Determine outparams and return if function not relevant
- if (DECL_CONSTRUCTOR_P(func_decl)) return;
- let psem = OutparamCheck.prototype.func_param_semantics(func_decl);
- if (!psem.some(function(x) x.check)) return;
- let decl = rectify_function_decl(func_decl);
- if (decl.resultType != 'nsresult' && decl.resultType != 'PRBool' &&
- decl.resultType != 'void') {
- warning("Cannot analyze outparam usage for function with return type '" +
- decl.resultType + "'", location_of(func_decl));
- return;
- }
-
- let params = [ v for (v in flatten_chain(DECL_ARGUMENTS(func_decl))) ];
- let outparam_list = [];
- let psem_list = [];
- for (let i = 0; i < psem.length; ++i) {
- if (psem[i].check) {
- outparam_list.push(params[i]);
- psem_list.push(psem[i]);
- }
- }
- if (outparam_list.length == 0) return;
-
- // At this point we have a function we want to analyze
- let fstring = rfunc_string(decl);
- if (TRACE_FUNCTIONS) {
- print('* function ' + fstring);
- print(' ' + loc_string(location_of(func_decl)));
- }
- if (TRACE_PERF) timer_start(fstring);
- for (let i = 0; i < outparam_list.length; ++i) {
- let p = outparam_list[i];
- if (TRACE_FUNCTIONS) {
- print(" outparam " + expr_display(p) + " " + DECL_UID(p) + ' ' +
- psem_list[i].label);
- }
- }
-
- let cfg = function_decl_cfg(func_decl);
-
- let [retvar, retvars] = function() {
- let trace = 0;
- let a = new MayReturnAnalysis(cfg, trace);
- a.run();
- return [a.retvar, a.vbls];
- }();
- if (retvar == undefined && decl.resultType != 'void') throw new Error("assert");
-
- {
- let trace = TRACE_ESP;
- for (let i = 0; i < outparam_list.length; ++i) {
- let psem = [ psem_list[i] ];
- let outparam = [ outparam_list[i] ];
- let a = new OutparamCheck(cfg, psem, outparam, retvar, retvars, trace);
- // This is annoying, but this field is only used for logging anyway.
- a.fndecl = func_decl;
- a.run();
- a.check(decl.resultType == 'void', func_decl);
- }
- }
-
- if (TRACE_PERF) timer_stop(fstring);
-}
-
-// Outparam check analysis
-function OutparamCheck(cfg, psem_list, outparam_list, retvar, retvar_set,
- trace) {
- // We need to save the retvars so we can detect assignments through
- // their addresses passed as arguments.
- this.retvar_set = retvar_set;
- this.retvar = retvar;
-
- // We need both an ordered set and a lookup structure
- this.outparam_list = outparam_list
- this.outparams = create_decl_set(outparam_list);
- this.psem_list = psem_list;
-
- // Set up property state vars for ESP
- let psvar_list = [];
- for each (let v in outparam_list) {
- psvar_list.push(new ESP.PropVarSpec(v, true, av.NOT_WRITTEN));
- }
- for (let v in retvar_set.items()) {
- psvar_list.push(new ESP.PropVarSpec(v, v == this.retvar, ESP.TOP));
- }
- if (trace) {
- print("PS vars");
- for each (let v in this.psvar_list) {
- print(" " + expr_display(v.vbl));
- }
- }
- this.zeroNonzero = new Zero_NonZero.Zero_NonZero();
- ESP.Analysis.call(this, cfg, psvar_list, av.meet, trace);
-}
-
-// Abstract values for outparam check
-function AbstractValue(name, ch) {
- this.name = name;
- this.ch = ch;
-}
-
-AbstractValue.prototype.equals = function(v) {
- return this === v;
-}
-
-AbstractValue.prototype.toString = function() {
- return this.name + ' (' + this.ch + ')';
-}
-
-AbstractValue.prototype.toShortString = function() {
- return this.ch;
-}
-
-let avspec = [
- // Abstract values for outparam contents write status
- [ 'NULL', 'x' ], // is a null pointer
- [ 'NOT_WRITTEN', '-' ], // not written
- [ 'WROTE_NULL', '/' ], // had NULL written to
- [ 'WRITTEN', '+' ], // had anything written to
- // MAYBE_WRITTEN is special. "Officially", it means the same thing as
- // NOT_WRITTEN. What it really means is that an outparam was passed
- // to another function as a possible outparam (outparam type, but not
- // in last position), so if there is an error with it not being written,
- // we can give a hint about the possible outparam in the warning.
- [ 'MAYBE_WRITTEN', '?' ], // written if possible outparam is one
-];
-
-let av = {};
-for each (let [name, ch] in avspec) {
- av[name] = new AbstractValue(name, ch);
-}
-
-av.ZERO = Zero_NonZero.Lattice.ZERO;
-av.NONZERO = Zero_NonZero.Lattice.NONZERO;
-
-/*
-av.ZERO.negation = av.NONZERO;
-av.NONZERO.negation = av.ZERO;
-
-// Abstract values for int constants. We use these to figure out feasible
-// paths in the presence of GCC finally_tmp-controlled switches.
-function makeIntAV(v) {
- let key = 'int_' + v;
- if (cachedAVs.hasOwnProperty(key)) return cachedAVs[key];
-
- let s = "" + v;
- let ans = cachedAVs[key] = new AbstractValue(s, s);
- ans.int_val = v;
- return ans;
-}
-*/
-
-let cachedAVs = {};
-
-// Abstract values for pointers that contain a copy of an outparam
-// pointer. We use these to figure out writes to a casted copy of
-// an outparam passed to another method.
-function makeOutparamAV(v) {
- let key = 'outparam_' + DECL_UID(v);
- if (key in cachedAVs) return cachedAVs[key];
-
- let ans = cachedAVs[key] =
- new AbstractValue('OUTPARAM:' + expr_display(v), 'P');
- ans.outparam = v;
- return ans;
-}
-
-/** Return the integer value if this is an integer av, otherwise undefined. */
-av.intVal = function(v) {
- if (v.hasOwnProperty('int_val'))
- return v.int_val;
- return undefined;
-}
-
-/** Meet function for our abstract values. */
-av.meet = function(v1, v2) {
- // At this point we know v1 != v2.
- let values = [v1,v2]
- if (values.indexOf(av.LOCKED) != -1
- || values.indexOf(av.UNLOCKED) != -1)
- return ESP.NOT_REACHED;
-
- return Zero_NonZero.meet(v1, v2)
-};
-
-// Outparam check analysis
-OutparamCheck.prototype = new ESP.Analysis;
-
-OutparamCheck.prototype.split = function(vbl, v) {
- // Can't happen for current version of ESP, but could change
- if (v != ESP.TOP) throw new Error("not implemented");
- return [ av.ZERO, av.NONZERO ];
-}
-
-OutparamCheck.prototype.updateEdgeState = function(e) {
- e.state.keepOnly(e.dest.keepVars);
-}
-
-OutparamCheck.prototype.flowState = function(isn, state) {
- switch (TREE_CODE(isn)) {
- case GIMPLE_ASSIGN:
- this.processAssign(isn, state);
- break;
- case GIMPLE_CALL:
- this.processCall(isn, isn, state);
- break;
- case GIMPLE_SWITCH:
- case GIMPLE_COND:
- // This gets handled by flowStateCond instead, has no exec effect
- break;
- default:
- this.zeroNonzero.flowState(isn, state);
- }
-}
-
-OutparamCheck.prototype.flowStateCond = function(isn, truth, state) {
- this.zeroNonzero.flowStateCond(isn, truth, state);
-}
-
-// For any outparams-specific semantics, we handle it here and then
-// return. Otherwise we delegate to the zero-nonzero analysis.
-OutparamCheck.prototype.processAssign = function(isn, state) {
- let lhs = gimple_op(isn, 0);
- let rhs = gimple_op(isn, 1);
-
- if (DECL_P(lhs)) {
- // Unwrap NOP_EXPR, which is semantically a copy.
- if (TREE_CODE(rhs) == NOP_EXPR) {
- rhs = rhs.operands()[0];
- }
-
- if (DECL_P(rhs) && this.outparams.has(rhs)) {
- // Copying an outparam pointer. We have to remember this so that
- // if it is assigned thru later, we pick up the write.
- state.assignValue(lhs, makeOutparamAV(rhs), isn);
- return;
- }
-
- // Cases of this switch that handle something should return from
- // the function. Anything that does not return is picked up afteward.
- switch (TREE_CODE(rhs)) {
- case INTEGER_CST:
- if (this.outparams.has(lhs)) {
- warning("assigning to outparam pointer");
- return;
- }
- break;
- case EQ_EXPR: {
- // We only care about testing outparams for NULL (and then not writing)
- let [op1, op2] = rhs.operands();
- if (DECL_P(op1) && this.outparams.has(op1) && expr_literal_int(op2) == 0) {
- state.update(function(ss) {
- let [s1, s2] = [ss, ss.copy()]; // s1 true, s2 false
- s1.assignValue(lhs, av.NONZERO, isn);
- s1.assignValue(op1, av.NULL, isn);
- s2.assignValue(lhs, av.ZERO, isn);
- return [s1, s2];
- });
- return;
- }
- }
- break;
- case CALL_EXPR:
- /* Embedded CALL_EXPRs are a 4.3 issue */
- this.processCall(rhs, isn, state, lhs);
- return;
-
- case INDIRECT_REF:
- // If rhs is *outparam and pointer-typed, lhs is NULL iff rhs is
- // WROTE_NULL. Required for testcase onull.cpp.
- let v = rhs.operands()[0];
- if (DECL_P(v) && this.outparams.has(v) &&
- TREE_CODE(TREE_TYPE(v)) == POINTER_TYPE) {
- state.update(function(ss) {
- let val = ss.get(v) == av.WROTE_NULL ? av.ZERO : av.NONZERO;
- ss.assignValue(lhs, val, isn);
- return [ ss ];
- });
- return;
- }
- }
-
- // Nothing special -- delegate
- this.zeroNonzero.processAssign(isn, state);
- return;
- }
-
- switch (TREE_CODE(lhs)) {
- case INDIRECT_REF:
- // Writing to an outparam. We want to try to figure out if we're
- // writing NULL.
- let e = TREE_OPERAND(lhs, 0);
- if (this.outparams.has(e)) {
- if (expr_literal_int(rhs) == 0) {
- state.assignValue(e, av.WROTE_NULL, isn);
- } else if (DECL_P(rhs)) {
- state.update(function(ss) {
- let [s1, s2] = [ss.copy(), ss]; // s1 NULL, s2 non-NULL
- s1.assignValue(e, av.WROTE_NULL, isn);
- s1.assignValue(rhs, av.ZERO, isn);
- s2.assignValue(e, av.WRITTEN, isn);
- s2.assignValue(rhs, av.NONZERO, isn);
- return [s1,s2];
- });
- } else {
- state.assignValue(e, av.WRITTEN, isn);
- }
- } else {
- // unsound -- could be writing to anything through this ptr
- }
- break;
- case COMPONENT_REF: // unsound
- case ARRAY_REF: // unsound
- case EXC_PTR_EXPR:
- case FILTER_EXPR:
- break;
- default:
- print(TREE_CODE(lhs));
- throw new Error("ni");
- }
-}
-
-// Handle an assignment x := test(foo) where test is a simple predicate
-OutparamCheck.prototype.processTest = function(lhs, call, val, blame, state) {
- let arg = gimple_call_arg(call, 0);
- if (DECL_P(arg)) {
- this.zeroNonzero.predicate(state, lhs, val, arg, blame);
- } else {
- state.assignValue(lhs, ESP.TOP, blame);
- }
-};
-
-// The big one: outparam semantics of function calls.
-OutparamCheck.prototype.processCall = function(call, blame, state, dest) {
- if (!dest)
- dest = gimple_call_lhs(call);
-
- let args = gimple_call_args(call);
- let callable = callable_arg_function_decl(gimple_call_fn(call));
- let psem = this.func_param_semantics(callable);
-
- let name = function_decl_name(callable);
- if (name == 'NS_FAILED') {
- this.processTest(dest, call, av.NONZERO, call, state);
- return;
- } else if (name == 'NS_SUCCEEDED') {
- this.processTest(dest, call, av.ZERO, call, state);
- return;
- } else if (name == '__builtin_expect') {
- // Same as an assign from arg 0 to lhs
- state.assign(dest, args[0], call);
- return;
- }
-
- if (TRACE_CALL_SEM) {
- print("param semantics:" + psem);
- }
-
- if (args.length != psem.length) {
- let ct = TREE_TYPE(callable);
- if (TREE_CODE(ct) == POINTER_TYPE) ct = TREE_TYPE(ct);
- if (args.length < psem.length || !stdarg_p(ct)) {
- // TODO Can __builtin_memcpy write to an outparam? Probably not.
- if (name != 'operator new' && name != 'operator delete' &&
- name != 'operator new []' && name != 'operator delete []' &&
- name.substr(0, 5) != '__cxa' &&
- name.substr(0, 9) != '__builtin') {
- throw Error("bad len for '" + name + "': " + args.length + ' args, ' +
- psem.length + ' params');
- }
- }
- }
-
- // Collect variables that are possibly written to on callee success
- let updates = [];
- for (let i = 0; i < psem.length; ++i) {
- let arg = args[i];
- // The arg could be the address of a return-value variable.
- // This means it's really the nsresult code for the call,
- // so we treat it the same as the target of an rv assignment.
- if (TREE_CODE(arg) == ADDR_EXPR) {
- let v = arg.operands()[0];
- if (DECL_P(v) && this.retvar_set.has(v)) {
- dest = v;
- }
- }
- // The arg could be a copy of an outparam. We'll unwrap to the
- // outparam if it is. The following is cheating a bit because
- // we munge states together, but it should be OK in practice.
- arg = unwrap_outparam(arg, state);
- let sem = psem[i];
- if (sem == ps.CONST) continue;
- // At this point, we know the call can write thru this param.
- // Invalidate any vars whose addresses are passed here. This
- // is distinct from the rv handling above.
- if (TREE_CODE(arg) == ADDR_EXPR) {
- let v = arg.operands()[0];
- if (DECL_P(v)) {
- state.remove(v);
- }
- }
- if (!DECL_P(arg) || !this.outparams.has(arg)) continue;
- // At this point, we may be writing to an outparam
- updates.push([arg, sem]);
- }
-
- if (updates.length) {
- if (dest != undefined && DECL_P(dest)) {
- // Update & stored rv. Do updates predicated on success.
- let [ succ_ret, fail_ret ] = ret_coding(callable);
-
- state.update(function(ss) {
- let [s1, s2] = [ss.copy(), ss]; // s1 success, s2 fail
- for each (let [vbl, sem] in updates) {
- s1.assignValue(vbl, sem.val, blame);
- s1.assignValue(dest, succ_ret, blame);
- }
- s2.assignValue(dest, fail_ret, blame);
- return [s1,s2];
- });
- } else {
- // Discarded rv. Per spec in the bug, we assume that either success
- // or failure is possible (if not, callee should return void).
- // Exceptions: Methods that return void and string mutators are
- // considered no-fail.
- state.update(function(ss) {
- for each (let [vbl, sem] in updates) {
- if (sem == ps.OUTNOFAIL || sem == ps.OUTNOFAILNOCHECK) {
- ss.assignValue(vbl, av.WRITTEN, blame);
- return [ss];
- } else {
- let [s1, s2] = [ss.copy(), ss]; // s1 success, s2 fail
- for each (let [vbl, sem] in updates) {
- s1.assignValue(vbl, sem.val, blame);
- }
- return [s1,s2];
- }
- }
- });
- }
- } else {
- // no updates, just kill any destination for the rv
- if (dest != undefined && DECL_P(dest)) {
- state.remove(dest, blame);
- }
- }
-};
-
-/** Return the return value coding of the given function. This is a pair
- * [ succ, fail ] giving the abstract values of the return value under
- * success and failure conditions. */
-function ret_coding(callable) {
- let type = TREE_TYPE(callable);
- if (TREE_CODE(type) == POINTER_TYPE) type = TREE_TYPE(type);
-
- let rtname = TYPE_NAME(TREE_TYPE(type));
- if (rtname && IDENTIFIER_POINTER(DECL_NAME(rtname)) == 'PRBool') {
- return [ av.NONZERO, av.ZERO ];
- } else {
- return [ av.ZERO, av.NONZERO ];
- }
-}
-
-function unwrap_outparam(arg, state) {
- if (!DECL_P(arg) || state.factory.outparams.has(arg)) return arg;
-
- let outparam;
- for (let ss in state.substates.getValues()) {
- let val = ss.get(arg);
- if (val != undefined && val.hasOwnProperty('outparam')) {
- outparam = val.outparam;
- }
- }
- if (outparam) return outparam;
- return arg;
-}
-
-// Check for errors. Must .run() analysis before calling this.
-OutparamCheck.prototype.check = function(isvoid, fndecl) {
- let state = this.cfg.x_exit_block_ptr.stateOut;
- for (let substate in state.substates.getValues()) {
- this.checkSubstate(isvoid, fndecl, substate);
- }
-}
-
-OutparamCheck.prototype.checkSubstate = function(isvoid, fndecl, ss) {
- if (isvoid) {
- this.checkSubstateSuccess(ss);
- } else {
- let [succ, fail] = ret_coding(fndecl);
- let rv = ss.get(this.retvar);
- // We want to check if the abstract value of the rv is entirely
- // contained in the success or failure condition.
- if (av.meet(rv, succ) == rv) {
- this.checkSubstateSuccess(ss);
- } else if (av.meet(rv, fail) == rv) {
- this.checkSubstateFailure(ss);
- } else {
- // This condition indicates a bug in outparams.js. We'll just
- // warn so we don't break static analysis builds.
- warning("Outparams checker cannot determine rv success/failure",
- location_of(fndecl));
- this.checkSubstateSuccess(ss);
- this.checkSubstateFailure(ss);
- }
- }
-}
-
-/* @return The return statement in the function
- * that writes the return value in the given substate.
- * If the function returns void, then the substate doesn't
- * matter and we just look for the return. */
-OutparamCheck.prototype.findReturnStmt = function(ss) {
- if (this.retvar != undefined)
- return ss.getBlame(this.retvar);
-
- if (this.cfg._cached_return)
- return this.cfg._cached_return;
-
- for (let bb in cfg_bb_iterator(this.cfg)) {
- for (let isn in bb_isn_iterator(bb)) {
- if (isn.tree_code() == GIMPLE_RETURN) {
- return this.cfg._cached_return = isn;
- }
- }
- }
-
- return undefined;
-}
-
-OutparamCheck.prototype.checkSubstateSuccess = function(ss) {
- for (let i = 0; i < this.psem_list.length; ++i) {
- let [v, psem] = [ this.outparam_list[i], this.psem_list[i] ];
- if (psem == ps.INOUT) continue;
- let val = ss.get(v);
- if (val == av.NOT_WRITTEN) {
- this.logResult('succ', 'not_written', 'error');
- this.warn([this.findReturnStmt(ss), "outparam '" + expr_display(v) + "' not written on NS_SUCCEEDED(return value)"],
- [v, "outparam declared here"]);
- } else if (val == av.MAYBE_WRITTEN) {
- this.logResult('succ', 'maybe_written', 'error');
-
- let blameStmt = ss.getBlame(v);
- let callMsg;
- let callName = "";
- try {
- let call = TREE_CHECK(blameStmt, GIMPLE_CALL, GIMPLE_MODIFY_STMT);
- let callDecl = callable_arg_function_decl(gimple_call_fn(call));
-
- callMsg = [callDecl, "declared here"];
- callName = " '" + decl_name(callDecl) + "'";
- }
- catch (e if e.TreeCheckError) { }
-
- this.warn([this.findReturnStmt(ss), "outparam '" + expr_display(v) + "' not written on NS_SUCCEEDED(return value)"],
- [v, "outparam declared here"],
- [blameStmt, "possibly written by unannotated function call" + callName],
- callMsg);
- } else {
- this.logResult('succ', '', 'ok');
- }
- }
-}
-
-OutparamCheck.prototype.checkSubstateFailure = function(ss) {
- for (let i = 0; i < this.psem_list.length; ++i) {
- let [v, ps] = [ this.outparam_list[i], this.psem_list[i] ];
- let val = ss.get(v);
- if (val == av.WRITTEN) {
- this.logResult('fail', 'written', 'error');
- if (WARN_ON_SET_FAILURE) {
- this.warn([this.findReturnStmt(ss), "outparam '" + expr_display(v) + "' written on NS_FAILED(return value)"],
- [v, "outparam declared here"],
- [ss.getBlame(v), "written here"]);
- }
- } else if (val == av.WROTE_NULL) {
- this.logResult('fail', 'wrote_null', 'warning');
- if (WARN_ON_SET_NULL) {
- this.warn([this.findReturnStmt(ss), "NULL written to outparam '" + expr_display(v) + "' on NS_FAILED(return value)"],
- [v, "outparam declared here"],
- [ss.getBlame(v), "written here"]);
- }
- } else {
- this.logResult('fail', '', 'ok');
- }
- }
-}
-
-/**
- * Generate a warning from one or more tuples [treeforloc, message]
- */
-OutparamCheck.prototype.warn = function(arg0) {
- let loc = safe_location_of(arg0[0]);
- let msg = arg0[1];
-
- for (let i = 1; i < arguments.length; ++i) {
- if (arguments[i] === undefined) continue;
- let [atree, amsg] = arguments[i];
- msg += "\n" + loc_string(safe_location_of(atree)) + ": " + amsg;
- }
- warning(msg, loc);
-}
-
-OutparamCheck.prototype.logResult = function(rv, msg, kind) {
- if (LOG_RESULTS) {
- let s = [ '"' + x + '"' for each (x in [ loc_string(location_of(this.fndecl)), function_decl_name(this.fndecl), rv, msg, kind ]) ].join(', ');
- print(":LR: (" + s + ")");
- }
-}
-
-// Parameter Semantics values -- indicates whether a parameter is
-// an outparam.
-// label Used for debugging output
-// val Abstract value (state) that holds on an argument after
-// a call
-// check True if parameters with this semantics should be
-// checked by this analysis
-let ps = {
- OUTNOFAIL: { label: 'out-no-fail', val: av.WRITTEN, check: true },
- // Special value for receiver of strings methods. Callers should
- // consider this to be an outparam (i.e., it modifies the string),
- // but we don't want to check the method itself.
- OUTNOFAILNOCHECK: { label: 'out-no-fail-no-check' },
- OUT: { label: 'out', val: av.WRITTEN, check: true },
- INOUT: { label: 'inout', val: av.WRITTEN, check: true },
- MAYBE: { label: 'maybe', val: av.MAYBE_WRITTEN}, // maybe out
- CONST: { label: 'const' } // i.e. not out
-};
-
-// Return the param semantics of a FUNCTION_DECL or VAR_DECL representing
-// a function pointer. The result is a pair [ ann, sems ].
-OutparamCheck.prototype.func_param_semantics = function(callable) {
- let ftype = TREE_TYPE(callable);
- if (TREE_CODE(ftype) == POINTER_TYPE) ftype = TREE_TYPE(ftype);
- // What failure semantics to use for outparams
- let rtype = TREE_TYPE(ftype);
- let nofail = TREE_CODE(rtype) == VOID_TYPE;
- // Whether to guess outparams by type
- let guess = type_string(rtype) == 'nsresult';
-
- // Set up param lists for analysis
- let params; // param decls, if available
- let types; // param types
- let string_mutator = false;
- if (TREE_CODE(callable) == FUNCTION_DECL) {
- params = [ p for (p in function_decl_params(callable)) ];
- types = [ TREE_TYPE(p) for each (p in params) ];
- string_mutator = is_string_mutator(callable);
- } else {
- types = [ p for (p in function_type_args(ftype))
- if (TREE_CODE(p) != VOID_TYPE) ];
- }
-
- // Analyze params
- let ans = [];
- for (let i = 0; i < types.length; ++i) {
- let sem;
- if (i == 0 && string_mutator) {
- // Special case: string mutator receiver is an no-fail outparams
- // but not checkable
- sem = ps.OUTNOFAILNOCHECK;
- } else {
- if (params) sem = decode_attr(DECL_ATTRIBUTES(params[i]));
- if (TRACE_CALL_SEM >= 2) print("param " + i + ": annotated " + sem);
- if (sem == undefined) {
- sem = decode_attr(TYPE_ATTRIBUTES(types[i]));
- if (TRACE_CALL_SEM >= 2) print("type " + i + ": annotated " + sem);
- if (sem == undefined) {
- if (guess && type_is_outparam(types[i])) {
- // Params other than last are guessed as MAYBE
- sem = i < types.length - 1 ? ps.MAYBE : ps.OUT;
- } else {
- sem = ps.CONST;
- }
- }
- }
- if (sem == ps.OUT && nofail) sem = ps.OUTNOFAIL;
- }
- if (sem == undefined) throw new Error("assert");
- ans.push(sem);
- }
- return ans;
-}
-
-/* Decode parameter semantics GCC attributes.
- * @param attrs GCC attributes of a parameter. E.g., TYPE_ATTRIBUTES
- * or DECL_ATTRIBUTES of an item
- * @return The parameter semantics value defined by the attributes,
- * or undefined if no such attributes were present. */
-function decode_attr(attrs) {
- // Note: we're not checking for conflicts, we just take the first
- // one we find.
- for each (let attr in rectify_attributes(attrs)) {
- if (attr.name == 'user') {
- for each (let arg in attr.args) {
- if (arg == 'NS_outparam') {
- return ps.OUT;
- } else if (arg == 'NS_inoutparam') {
- return ps.INOUT;
- } else if (arg == 'NS_inparam') {
- return ps.CONST;
- }
- }
- }
- }
- return undefined;
-}
-
-/* @return true if the given type appears to be an outparam
- * type based on the type alone (i.e., not considering
- * attributes. */
-function type_is_outparam(type) {
- switch (TREE_CODE(type)) {
- case POINTER_TYPE:
- return pointer_type_is_outparam(TREE_TYPE(type));
- case REFERENCE_TYPE:
- let rt = TREE_TYPE(type);
- return !TYPE_READONLY(rt) && is_string_type(rt);
- default:
- // Note: This is unsound for UNION_TYPE, because the union could
- // contain a pointer.
- return false;
- }
-}
-
-/* Helper for type_is_outparam.
- * @return true if 'pt *' looks like an outparam type. */
-function pointer_type_is_outparam(pt) {
- if (TYPE_READONLY(pt)) return false;
-
- switch (TREE_CODE(pt)) {
- case POINTER_TYPE:
- case ARRAY_TYPE: {
- // Look for void **, nsIFoo **, char **, PRUnichar **
- let ppt = TREE_TYPE(pt);
- let tname = TYPE_NAME(ppt);
- if (tname == undefined) return false;
- let name = decl_name_string(tname);
- return name == 'void' || name == 'char' || name == 'PRUnichar' ||
- name.substr(0, 3) == 'nsI';
- }
- case INTEGER_TYPE: {
- // char * and PRUnichar * are probably strings, otherwise guess
- // it is an integer outparam.
- let name = decl_name_string(TYPE_NAME(pt));
- return name != 'char' && name != 'PRUnichar';
- }
- case ENUMERAL_TYPE:
- case REAL_TYPE:
- case UNION_TYPE:
- case BOOLEAN_TYPE:
- return true;
- case RECORD_TYPE:
- // TODO: should we consider field writes?
- return false;
- case FUNCTION_TYPE:
- case VOID_TYPE:
- return false;
- default:
- throw new Error("can't guess if a pointer to this type is an outparam: " +
- TREE_CODE(pt) + ': ' + type_string(pt));
- }
-}
-
-// Map type name to boolean as to whether it is a string.
-let cached_string_types = MapFactory.create_map(
- function (x, y) x == y,
- function (x) x,
- function (t) t,
- function (t) t);
-
-// Base string types. Others will be found by searching the inheritance
-// graph.
-
-cached_string_types.put('nsAString', true);
-cached_string_types.put('nsACString', true);
-cached_string_types.put('nsAString_internal', true);
-cached_string_types.put('nsACString_internal', true);
-
-// Return true if the given type represents a Mozilla string type.
-// The binfo arg is the binfo to use for further iteration. This is
-// for internal use only, users of this function should pass only
-// one arg.
-function is_string_type(type, binfo) {
- if (TREE_CODE(type) != RECORD_TYPE) return false;
- //print(">>>IST " + type_string(type));
- let name = decl_name_string(TYPE_NAME(type));
- let ans = cached_string_types.get(name);
- if (ans != undefined) return ans;
-
- ans = false;
- binfo = binfo != undefined ? binfo : TYPE_BINFO(type);
- if (binfo != undefined) {
- for each (let base in VEC_iterate(BINFO_BASE_BINFOS(binfo))) {
- let parent_ans = is_string_type(BINFO_TYPE(base), base);
- if (parent_ans) {
- ans = true;
- break;
- }
- }
- }
- cached_string_types.put(name, ans);
- //print("<<<IST " + type_string(type) + ' ' + ans);
- return ans;
-}
-
-function is_string_ptr_type(type) {
- return TREE_CODE(type) == POINTER_TYPE && is_string_type(TREE_TYPE(type));
-}
-
-// Return true if the given function is a mutator method of a Mozilla
-// string type.
-function is_string_mutator(fndecl) {
- let first_param = function() {
- for (let p in function_decl_params(fndecl)) {
- return p;
- }
- return undefined;
- }();
-
- return first_param != undefined &&
- decl_name_string(first_param) == 'this' &&
- is_string_ptr_type(TREE_TYPE(first_param)) &&
- !TYPE_READONLY(TREE_TYPE(TREE_TYPE(first_param)));
-}
-
diff --git a/xpcom/analysis/stack.js b/xpcom/analysis/stack.js
deleted file mode 100644
index 20fa7e7d2..000000000
--- a/xpcom/analysis/stack.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-require({ after_gcc_pass: "cfg" });
-
-include("gcc_util.js");
-include("unstable/lazy_types.js");
-
-function process_type(c)
-{
- if ((c.kind == 'class' || c.kind == 'struct') &&
- !c.isIncomplete)
- isStack(c);
-}
-
-/**
- * A BlameChain records a chain of one or more location/message pairs. It
- * can be used to issue a complex error message such as:
- * location: error: Allocated class Foo on the heap
- * locationofFoo: class Foo inherits from class Bar
- * locationofBar: in class Bar
- * locationofBarMem: Member Bar::mFoo
- * locationofBaz: class Baz is annotated NS_STACK
- */
-function BlameChain(loc, message, prev)
-{
- this.loc = loc;
- this.message = message;
- this.prev = prev;
-}
-
-BlameChain.prototype.toString = function()
-{
- let loc = this.loc;
- if (loc === undefined)
- loc = "<unknown location>";
-
- let str = '%s: %s'.format(loc.toString(), this.message);
- if (this.prev)
- str += "\n%s".format(this.prev);
- return str;
-};
-
-function isStack(c)
-{
- function calculate()
- {
- if (hasAttribute(c, 'NS_stack'))
- return new BlameChain(c.loc, '%s %s is annotated NS_STACK_CLASS'.format(c.kind, c.name));
-
- for each (let base in c.bases) {
- let r = isStack(base.type);
- if (r != null)
- return new BlameChain(c.loc, '%s %s is a base of %s %s'.format(base.type.kind, base.type.name, c.kind, c.name), r);
- }
-
- for each (let member in c.members) {
- if (member.isFunction)
- continue;
-
- if (hasAttribute(member, 'NS_okonheap'))
- continue;
-
- let type = member.type;
- while (true) {
- if (type === undefined)
- break;
-
- if (type.isArray) {
- type = type.type;
- continue;
- }
-
- if (type.typedef) {
- if (hasAttribute(type, 'NS_stack'))
- return true;
-
- type = type.typedef;
- continue;
- }
- break;
- }
-
- if (type === undefined) {
- warning("incomplete type for member " + member + ".", member.loc);
- continue;
- }
-
- if (type.isPointer || type.isReference)
- continue;
-
- if (!type.kind || (type.kind != 'class' && type.kind != 'struct'))
- continue;
-
- let r = isStack(type);
- if (r != null)
- return new BlameChain(c.loc, 'In class %s'.format(c.name),
- new BlameChain(member.loc, 'Member %s'.format(member.name), r));
- }
- return null;
- }
-
- if (!c.hasOwnProperty('isStack'))
- c.isStack = calculate();
-
- return c.isStack;
-}
-
-function process_tree(fn)
-{
- if (hasAttribute(dehydra_convert(fn), 'NS_suppress_stackcheck'))
- return;
-
- let cfg = function_decl_cfg(fn);
-
- for (let bb in cfg_bb_iterator(cfg)) {
- let it = bb_isn_iterator(bb);
- for (let isn in it) {
- if (isn.tree_code() != GIMPLE_CALL)
- continue;
-
- let name = gimple_call_function_name(isn);
- if (name != "operator new" && name != "operator new []")
- continue;
-
- // ignore placement new
- // TODO? ensure 2nd arg is local stack variable
- if (gimple_call_num_args(isn) == 2 &&
- TREE_TYPE(gimple_call_arg(isn, 1)).tree_code() == POINTER_TYPE)
- continue;
-
- let newLhs = gimple_call_lhs(isn);
- if (!newLhs)
- error("Non assigning call to operator new", location_of(isn));
-
- // if isn is the last of its block there are other problems...
- assign = it.next();
-
- // Calls to |new| are always followed by an assignment, casting the void ptr to which
- // |new| was assigned, to a ptr variable of the same type as the allocated object.
- // Exception: explicit calls to |::operator new (size_t)|, which can be ignored.
- if (assign.tree_code() != GIMPLE_ASSIGN)
- continue;
-
- let assignRhs = gimple_op(assign, 1);
- if (newLhs != assignRhs)
- continue;
-
- let assignLhs = gimple_op(assign, 0);
- let type = TREE_TYPE(TREE_TYPE(assignLhs));
- let dehydraType = dehydra_convert(type);
-
- let r = isStack(dehydraType);
- if (r)
- warning("constructed object of type '%s' not on the stack: %s".format(dehydraType.name, r), location_of(isn));
- }
- }
-}
diff --git a/xpcom/analysis/static-init.js b/xpcom/analysis/static-init.js
deleted file mode 100644
index 11d576640..000000000
--- a/xpcom/analysis/static-init.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-/**
- * Detects static initializers i.e. functions called during static initialization.
- */
-
-require({ after_gcc_pass: "cfg" });
-
-function process_tree(fn) {
- for each (let attr in translate_attributes(DECL_ATTRIBUTES(fn)))
- if (attr.name == "constructor")
- warning(pretty_func(fn) + " marked with constructor attribute\n");
-
- if (decl_name_string(fn) != "__static_initialization_and_destruction_0")
- return;
-
- let cfg = function_decl_cfg(fn);
- for (let isn in cfg_isn_iterator(cfg)) {
- if (isn.tree_code() != GIMPLE_CALL)
- continue;
- let decl = gimple_call_fndecl(isn);
- let lhs = gimple_call_lhs(isn);
- if (lhs) {
- warning(pretty_var(lhs) + " defined by call to " + pretty_func(decl) +
- " during static initialization", location_of(lhs));
- } else {
- let arg = constructorArg(isn);
- if (arg)
- warning(pretty_var(arg) + " defined by call to constructor " + pretty_func(decl) +
- " during static initialization", location_of(arg));
- else
- warning(pretty_func(decl) + " called during static initialization", location_of(decl));
- }
- }
-}
-
-function constructorArg(call) {
- let decl = gimple_call_fndecl(call);
-
- if (!DECL_CONSTRUCTOR_P(decl))
- return null;
-
- let arg = gimple_call_arg_iterator(call).next();
- if (TYPE_MAIN_VARIANT(TREE_TYPE(TREE_TYPE(arg))) != DECL_CONTEXT(decl))
- throw new Error("malformed constructor call?!");
-
- return arg.tree_code() == ADDR_EXPR ? TREE_OPERAND(arg, 0) : arg;
-}
-
-function pretty_func(fn) {
- return rfunc_string(rectify_function_decl(fn));
-}
-
-function pretty_var(v) {
- return type_string(TREE_TYPE(v)) + " " + expr_display(v);
-}
diff --git a/xpcom/analysis/type-printer.cpp b/xpcom/analysis/type-printer.cpp
deleted file mode 100644
index 59d60fd62..000000000
--- a/xpcom/analysis/type-printer.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-#include "nsString.h"
-
-/* do nothing else */
diff --git a/xpcom/analysis/type-printer.js b/xpcom/analysis/type-printer.js
deleted file mode 100644
index 672c3ab10..000000000
--- a/xpcom/analysis/type-printer.js
+++ /dev/null
@@ -1,402 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-let dumpTypes = options['dump-types'].split(',');
-
-let interestingList = {};
-let typelist = {};
-
-function interestingType(t)
-{
- let name = t.name;
-
- if (dumpTypes.some(function(n) n == name)) {
- interestingList[name] = t;
- typelist[name] = t;
- return true;
- }
-
- for each (let base in t.bases) {
- if (base.access == 'public' && interestingType(base.type)) {
- typelist[name] = t;
- return true;
- }
- }
-
- return false;
-}
-
-function addSubtype(t, subt)
-{
- if (subt.typedef === undefined &&
- subt.kind === undefined)
- throw Error("Unexpected subtype: not class or typedef: " + subt);
-
- if (t.subtypes === undefined)
- t.subtypes = [];
-
- t.subtypes.push(subt);
-}
-
-function process_type(t)
-{
- interestingType(t);
-
- for each (let base in t.bases)
- addSubtype(base.type, t);
-}
-
-function process_decl(d)
-{
- if (d.typedef !== undefined && d.memberOf)
- addSubtype(d.memberOf, d);
-}
-
-function publicBases(t)
-{
- yield t;
-
- for each (let base in t.bases)
- if (base.access == "public")
- for each (let gbase in publicBases(base.type))
- yield gbase;
-}
-
-function publicMembers(t)
-{
- for each (let base in publicBases(t)) {
- for each (let member in base.members) {
- if (member.access === undefined)
- throw Error("Harumph: member without access? " + member);
-
- if (member.access != "public")
- continue;
-
- yield member;
- }
- }
-}
-
-/**
- * Get the short name of a decl name. E.g. turn
- * "MyNamespace::MyClass::Method(int j) const" into
- * "Method"
- */
-function getShortName(decl)
-{
- let name = decl.name;
- let lp = name.lastIndexOf('(');
- if (lp != -1)
- name = name.slice(0, lp);
-
- lp = name.lastIndexOf('::');
- if (lp != -1)
- name = name.slice(lp + 2);
-
- return name;
-}
-
-/**
- * Remove functions in a base class which were overridden in a derived
- * class.
- *
- * Although really, we should perhaps do this the other way around, or even
- * group the two together, but that can come later.
- */
-function removeOverrides(members)
-{
- let overrideMap = {};
- for (let i = members.length - 1; i >= 0; --i) {
- let m = members[i];
- if (!m.isFunction)
- continue;
-
- let shortName = getShortName(m);
-
- let overrides = overrideMap[shortName];
- if (overrides === undefined) {
- overrideMap[shortName] = [m];
- continue;
- }
-
- let found = false;
- for each (let override in overrides) {
- if (signaturesMatch(override, m)) {
- // remove members[i], it was overridden
- members.splice(i, 1);
- found = true;
- }
- }
- if (found)
- continue;
-
- overrides.push(m);
- }
-}
-
-/**
- * Generates the starting position of lines within a file.
- */
-function getLineLocations(fdata)
-{
- yield 0;
-
- let r = /\n/y;
- let pos = 0;
- let i = 1;
- for (;;) {
- pos = fdata.indexOf('\n', pos) + 1;
- if (pos == 0)
- break;
-
- yield pos;
- i++;
- }
-}
-
-/**
- * Find and return the doxygen comment immediately prior to the location
- * object that was passed in.
- *
- * @todo: parse doccomment data such as @param, @returns
- * @todo: parse comments for markup
- */
-function getDocComment(loc)
-{
- let fdata = read_file(loc.file);
- let linemap = [l for (l in getLineLocations(fdata))];
-
- if (loc.line >= linemap.length) {
- warning("Location larger than actual header: " + loc);
- return <></>;
- }
-
- let endpos = linemap[loc.line - 1] + loc.column - 1;
- let semipos = fdata.lastIndexOf(';', endpos);
- let bracepos = fdata.lastIndexOf('}', endpos);
- let searchslice = fdata.slice(Math.max(semipos, bracepos) + 1, endpos);
-
- let m = searchslice.match(/\/\*\*[\s\S]*?\*\//gm);
- if (m === null)
- return <></>;
-
- let dc = m[m.length - 1].slice(3, -2);
- dc = dc.replace(/^\s*(\*+[ \t]*)?/gm, "");
-
- return <pre class="doccomment">{dc}</pre>;
-}
-
-function typeName(t)
-{
- if (t.name !== undefined)
- return t.name;
-
- if (t.isPointer)
- return "%s%s*".format(t.isConst ? "const " : "", typeName(t.type));
-
- if (t.isReference)
- return "%s%s&".format(t.isConst ? "const " : "", typeName(t.type));
-
- return t.toString();
-}
-
-function publicBaseList(t)
-{
- let l = <ul/>;
- for each (let b in t.bases) {
- if (b.access == 'public')
- l.* += <li><a href={"/en/%s".format(b.type.name)}>{b.type.name}</a></li>;
- }
-
- if (l.*.length() == 0)
- return <></>;
-
- return <>
- <h2>Base Classes</h2>
- {l}
- </>;
-}
-
-/**
- * Get a source-link for a given location.
- */
-function getLocLink(loc, text)
-{
- return <a class="loc"
- href={"http://hg.mozilla.org/mozilla-central/file/%s/[LOC%s]#l%i".format(options.rev, loc.file, loc.line)}>{text}</a>;
-}
-
-function dumpType(t)
-{
- print("DUMP-TYPE(%s)".format(t.name));
-
- let methodOverview = <tbody />;
- let methodList = <div/>;
- let memberList = <></>;
-
- let shortNameMap = {};
-
- let members = [m for (m in publicMembers(t))];
-
- removeOverrides(members);
-
- for each (let m in members) {
- let qname = m.memberOf.name + '::';
-
- // we don't inherit constructors from base classes
- if (m.isConstructor && m.memberOf !== t)
- continue;
-
- if (m.name.indexOf(qname) != 0)
- throw Error("Member name not qualified?");
-
- let name = m.name.slice(qname.length);
-
- if (name.indexOf('~') == 0)
- continue;
-
- if (m.isFunction) {
- let innerList;
-
- let shortName = getShortName(m);
- if (m.isConstructor)
- shortName = 'Constructors';
-
- if (shortNameMap.hasOwnProperty(shortName)) {
- innerList = shortNameMap[shortName];
- }
- else {
- let overview =
- <tr><td>
- <a href={'#%s'.format(escape(shortName))}>{shortName}</a>
- </td></tr>;
-
- if (m.isConstructor)
- methodOverview.insertChildAfter(null, overview);
- else
- methodOverview.appendChild(overview);
-
- let shortMarkup =
- <div>
- <h3 id={shortName}>{shortName}</h3>
- <dl/>
- </div>;
-
-
- if (m.isConstructor)
- methodList.insertChildAfter(null, shortMarkup);
- else
- methodList.appendChild(shortMarkup);
-
- innerList = shortMarkup.dl;
- shortNameMap[shortName] = innerList;
- }
-
- let parameters = <ul/>;
- for each (p in m.parameters) {
- let name = p.name;
- if (name == 'this')
- continue;
-
- if (/^D_\d+$/.test(name))
- name = '<anonymous>';
-
- parameters.* += <li>{typeName(p.type)} {name}</li>;
- }
-
- innerList.* +=
- <>
- <dt id={name} class="methodName">
- <code>{typeName(m.type.type)} {name}</code> - {getLocLink(m.loc, "source")}
- </dt>
- <dd>
- {getDocComment(m.loc)}
- {parameters.*.length() > 0 ?
- <>
- <h4>Parameters</h4>
- {parameters}
- </> : <></>}
- </dd>
- </>;
- }
- else {
- memberList += <li class="member">{name}</li>;
- }
- }
-
- let r =
- <body>
- <p>{getLocLink(t.loc, "Class Declaration")}</p>
-
- {getDocComment(t.loc)}
-
- {dumpTypes.some(function(n) n == t.name) ?
- <>
- [MAP{t.name}-graph.map]
- <img src={"/@api/deki/pages/=en%%252F%s/files/=%s-graph.png".format(t.name, t.name)} usemap="#classes" />
- </> : <></>
- }
-
- {methodOverview.*.length() > 0 ?
- <>
- <h2>Method Overview</h2>
- <table class="standard-table">{methodOverview}</table>
- </> :
- ""
- }
-
- {publicBaseList(t)}
-
- <h2>Data Members</h2>
-
- {memberList.*.length() > 0 ?
- memberList :
- <p><em>No public members.</em></p>
- }
-
- <h2>Methods</h2>
-
- {methodList.*.length() > 0 ?
- methodList :
- <p><em>No public methods.</em></p>
- }
-
- </body>;
-
- write_file(t.name + ".html", r.toXMLString());
-}
-
-function graphType(t)
-{
- print("GRAPH-TYPE(%s)".format(t.name));
-
- let contents = "digraph classes {\n"
- + " node [shape=rectangle fontsize=11]\n"
- + " %s;\n".format(t.name);
-
- function graphClass(c)
- {
- contents += '%s [URL="http://developer.mozilla.org/en/%s"]\n'.format(c.name, c.name);
-
- for each (let st in c.subtypes) {
- contents += " %s -> %s;\n".format(c.name, st.name);
- graphClass(st);
- }
- }
-
- graphClass(t);
-
- contents += "}\n";
-
- write_file(t.name + "-graph.gv", contents);
-}
-
-function input_end()
-{
- for (let p in typelist)
- dumpType(typelist[p]);
-
- for (let n in interestingList)
- graphType(interestingList[n]);
-}
diff --git a/xpcom/moz.build b/xpcom/moz.build
index 670ea52a6..fe45fe208 100644
--- a/xpcom/moz.build
+++ b/xpcom/moz.build
@@ -35,8 +35,5 @@ TEST_TOOL_DIRS += [
# 'reflect/xptcall/tests,
#]
-if CONFIG['DEHYDRA_PATH']:
- DIRS += ['analysis']
-
MODULE = 'xpcom'
diff --git a/xpcom/tests/moz.build b/xpcom/tests/moz.build
index ea3f5a2c6..e8749921e 100644
--- a/xpcom/tests/moz.build
+++ b/xpcom/tests/moz.build
@@ -24,9 +24,6 @@ if CONFIG['WRAP_STL_INCLUDES']:
'TestSTLWrappers.cpp',
]
-if CONFIG['DEHYDRA_PATH']:
- DIRS += ['static-checker']
-
MODULE = 'xpcom'
XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
diff --git a/xpcom/tests/static-checker/Makefile.in b/xpcom/tests/static-checker/Makefile.in
deleted file mode 100644
index cfacd6e70..000000000
--- a/xpcom/tests/static-checker/Makefile.in
+++ /dev/null
@@ -1,153 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# 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/.
-
-DEPTH = @DEPTH@
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-OUTPARAMS_WARNING_TESTCASES = \
- e1.cpp \
- e4.cpp \
- e6.cpp \
- e7.cpp \
- e8.cpp \
- e9.cpp \
- e10.cpp \
- e11.cpp \
- e12.cpp \
- e13.cpp \
- $(NULL)
-
-OUTPARAMS_NS_FAILED_TESTCASES = \
- e2.cpp \
- e5.cpp \
- $(NULL)
-
-OUTPARAMS_PASS_TESTCASES = \
- o1.cpp \
- o2.cpp \
- o3.cpp \
- o4.cpp \
- o5.cpp \
- o6.cpp \
- o7.cpp \
- o8.cpp \
- o9.cpp \
- o10.cpp \
- o11.cpp \
- o12.cpp \
- o13.cpp \
- o14.cpp \
- o15.cpp \
- o16.cpp \
- onull.cpp \
- onull2.cpp \
- opmember.cpp \
- $(NULL)
-
-FLOW_PASS_TESTCASES = \
- flow_through_pass.cpp
-
-FLOW_FAILURE_TESTCASES = \
- flow_through_fail.cpp
-
-MUST_OVERRIDE_PASS_TESTCASES = \
- OverrideOK1.cpp \
- OverrideOK2.cpp \
- OverrideOK3-NamespaceTypedef.cpp \
- $(NULL)
-
-MUST_OVERRIDE_FAILURE_TESTCASES = \
- OverrideFail1.cpp \
- OverrideFail2.cpp \
- OverrideFail3.cpp \
- OverrideFail4.cpp \
- $(NULL)
-
-OVERRIDE_PASS_TESTCASES = \
- override-pass.cpp \
- override-namespace-typedef.cpp \
- $(NULL)
-
-OVERRIDE_FAILURE_TESTCASES = \
- override-global.cpp \
- override-signature.cpp \
- override-static.cpp \
- override-virtual.cpp \
- $(NULL)
-
-STATIC_INIT_PASS_TESTCASES = \
- TestStaticInitStructOK.cpp \
- $(NULL)
-
-STATIC_INIT_WARNING_TESTCASES = \
- TestStaticInitAttr.cpp \
- TestStaticInitConstructor.cpp \
- TestStaticInitGlobal.cpp \
- TestStaticInitGlobalConst.cpp \
- $(NULL)
-
-STATIC_FAILURE_TESTCASES = \
- $(FLOW_FAILURE_TESTCASES) \
- $(MUST_OVERRIDE_FAILURE_TESTCASES) \
- $(OVERRIDE_FAILURE_TESTCASES) \
- $(NULL)
-
-STATIC_WARNING_TESTCASES = \
- $(OUTPARAMS_WARNING_TESTCASES) \
- $(STATIC_INIT_WARNING_TESTCASES) \
- $(NULL)
-
-STATIC_PASS_TESTCASES = \
- $(OUTPARAMS_NS_FAILED_TESTCASES) \
- $(OUTPARAMS_PASS_TESTCASES) \
- $(FLOW_PASS_TESTCASES) \
- $(MUST_OVERRIDE_PASS_TESTCASES) \
- $(OVERRIDE_PASS_TESTCASES) \
- $(STATIC_INIT_PASS_TESTCASES) \
- $(NULL)
-
-
-include $(topsrcdir)/config/rules.mk
-
-# We want to compile each file and invert the result to ensure that
-# compilation failed.
-check:: \
- $(STATIC_FAILURE_TESTCASES:.cpp=.s-fail) \
- $(STATIC_WARNING_TESTCASES:.cpp=.s-warn) \
- $(STATIC_PASS_TESTCASES:.cpp=.s-pass)
-
-%.s-fail: %.cpp $(GLOBAL_DEPS) $(DEHYDRA_SCRIPTS) $(call mkdir_deps,$(MDDEPDIR))
- @printf "Compiling $(<F) to check that the static-analysis script is checking properly..."
- @if $(CCC) $(OUTOPTION)/dev/null -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) >$(*F).errlog 2>&1; then \
- printf "fail:\nerror: compilation of $(<F) succeeded. It shouldn't have!\n"; \
- exit 1; \
- else \
- printf "ok.\n"; \
- fi
-
-%.s-warn: %.cpp $(GLOBAL_DEPS) $(DEHYDRA_SCRIPTS) $(call mkdir_deps,$(MDDEPDIR))
- @printf "Compiling $(<F) to check that the static-analysis script is checking properly..."
- @if $(CCC) -Werror $(OUTOPTION)/dev/null -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) >$(*F).errlog 2>&1; then \
- printf "fail:\nerror: compilation of $(<F) succeeded with -Werror. It shouldn't have!\n"; \
- exit 1; \
- fi
- @if $(CCC) $(OUTOPTION)/dev/null -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) >$(*F).werrlog 2>&1; then \
- printf "ok.\n"; \
- else \
- printf "fail:\nerror: compilation of $(<F) without -Werror failed. A warning should have been issued.\n"; \
- exit 1; \
- fi
-
-%.s-pass: %.cpp $(GLOBAL_DEPS) $(DEHYDRA_SCRIPTS) $(call mkdir_deps,$(MDDEPDIR))
- @printf "Compiling $(<F) to check that the static-analysis script is checking properly..."
- @if $(CCC) -Werror $(OUTOPTION)/dev/null -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) >$(*F).errlog 2>&1; then \
- printf "ok.\n"; \
- else \
- printf "fail:\nerror: compilation of $(<F) failed. It shouldn't have!\n"; \
- exit 1; \
- fi
diff --git a/xpcom/tests/static-checker/TestStaticInitAttr.cpp b/xpcom/tests/static-checker/TestStaticInitAttr.cpp
deleted file mode 100644
index a50d7e4f2..000000000
--- a/xpcom/tests/static-checker/TestStaticInitAttr.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-int foo() __attribute__((constructor));
-
-int foo() {
- return 0;
-}
diff --git a/xpcom/tests/static-checker/TestStaticInitConstructor.cpp b/xpcom/tests/static-checker/TestStaticInitConstructor.cpp
deleted file mode 100644
index d2d99468f..000000000
--- a/xpcom/tests/static-checker/TestStaticInitConstructor.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-struct Blah {
- public:
- Blah() { }
- ~Blah() { } // raises call to __cxa_atexit
-};
-
-Blah b;
diff --git a/xpcom/tests/static-checker/TestStaticInitGlobal.cpp b/xpcom/tests/static-checker/TestStaticInitGlobal.cpp
deleted file mode 100644
index ca44a30f7..000000000
--- a/xpcom/tests/static-checker/TestStaticInitGlobal.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-int foo() {
- return 0;
-}
-
-int x = foo();
diff --git a/xpcom/tests/static-checker/TestStaticInitGlobalConst.cpp b/xpcom/tests/static-checker/TestStaticInitGlobalConst.cpp
deleted file mode 100644
index c1efe10ea..000000000
--- a/xpcom/tests/static-checker/TestStaticInitGlobalConst.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-int foo() {
- return 0;
-}
-
-const static int x = foo();
diff --git a/xpcom/tests/static-checker/TestStaticInitStructOK.cpp b/xpcom/tests/static-checker/TestStaticInitStructOK.cpp
deleted file mode 100644
index aadc44681..000000000
--- a/xpcom/tests/static-checker/TestStaticInitStructOK.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-struct Blah {
- int i;
-};
-
-Blah b = { 3 };
diff --git a/xpcom/tests/static-checker/flow_through_fail.cpp b/xpcom/tests/static-checker/flow_through_fail.cpp
deleted file mode 100644
index 9374e77e7..000000000
--- a/xpcom/tests/static-checker/flow_through_fail.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-static void MUST_FLOW_THROUGH(const char *label) {
-}
-
-int test(int x, int y) {
- MUST_FLOW_THROUGH("out");
-
- if (!x) {
- x = y;
- goto out;
- }
-
- return y;
- out:
- x--;
- return x;
-}
diff --git a/xpcom/tests/static-checker/flow_through_pass.cpp b/xpcom/tests/static-checker/flow_through_pass.cpp
deleted file mode 100644
index 164225f86..000000000
--- a/xpcom/tests/static-checker/flow_through_pass.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-static void MUST_FLOW_THROUGH(const char *label) {
-}
-
-int test(int x, int y) {
- if (x == 3)
- return 0;
-
- if(x)
- MUST_FLOW_THROUGH("out");
-
- if (x) {
- x = y;
- goto out;
- }
-
- return y;
- out:
- x--;
- return x;
-}
diff --git a/xpcom/tests/static-checker/moz.build b/xpcom/tests/static-checker/moz.build
deleted file mode 100644
index 895d11993..000000000
--- a/xpcom/tests/static-checker/moz.build
+++ /dev/null
@@ -1,6 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# 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/.
-