зеркало из https://github.com/mozilla/gecko-dev.git
Bug 453343 - Print more complete error messages that trace the base classes and members that cause a particular class to be stack-only, r=dmandelin
This commit is contained in:
Родитель
cb3eb39381
Коммит
1e79d505c8
|
@ -8,16 +8,45 @@ function process_type(c)
|
|||
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 true;
|
||||
return new BlameChain(c.loc, '%s %s is annotated NS_STACK_CLASS'.format(c.kind, c.name));
|
||||
|
||||
for each (let base in c.bases)
|
||||
if (isStack(base.type))
|
||||
return true;
|
||||
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)
|
||||
|
@ -57,10 +86,12 @@ function isStack(c)
|
|||
if (!type.kind || (type.kind != 'class' && type.kind != 'struct'))
|
||||
continue;
|
||||
|
||||
if (isStack(type))
|
||||
return true;
|
||||
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 false;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (c.isIncomplete)
|
||||
|
@ -155,8 +186,9 @@ function process_tree(fndecl)
|
|||
}
|
||||
destType = destType.type;
|
||||
|
||||
if (isStack(destType))
|
||||
error("constructed object of type '" + destType.name + "' not on the stack.", getLocation(stmt));
|
||||
let r = isStack(destType);
|
||||
if (r != null)
|
||||
error('constructed object of type %s on the heap\n%s'.format(destType.name, r), getLocation(stmt));
|
||||
}
|
||||
|
||||
if (TREE_CODE(t) != STATEMENT_LIST)
|
||||
|
|
|
@ -17,6 +17,8 @@ include('unstable/getopt.js');
|
|||
sys.include_path[0] = options.topsrcdir + "/xpcom/analysis";
|
||||
sys.include_path.push(options.topsrcdir);
|
||||
|
||||
include('string-format.js');
|
||||
|
||||
let modules = [];
|
||||
|
||||
function LoadModules(modulelist)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
String.prototype.format = function string_format() {
|
||||
// there are two modes of operation... unnamed indices are read in order;
|
||||
// named indices using %(name)s. The two styles cannot be mixed.
|
||||
// Unnamed indices can be passed as either a single argument to this function,
|
||||
// multiple arguments to this function, or as a single array argument
|
||||
let curindex = 0;
|
||||
let d;
|
||||
|
||||
if (arguments.length > 1) {
|
||||
d = arguments;
|
||||
}
|
||||
else
|
||||
d = arguments[0];
|
||||
|
||||
function r(s, key, type) {
|
||||
let v;
|
||||
if (key == "") {
|
||||
if (curindex == -1)
|
||||
throw Error("Cannot mix named and positional indices in string formatting.");
|
||||
|
||||
if (curindex == 0 && (!(d instanceof Object) || !(0 in d))) {
|
||||
v = d;
|
||||
}
|
||||
else if (!(curindex in d))
|
||||
throw Error("Insufficient number of items in format, requesting item %i".format(curindex));
|
||||
else {
|
||||
v = d[curindex];
|
||||
}
|
||||
|
||||
++curindex;
|
||||
}
|
||||
else {
|
||||
key = key.slice(1, -1);
|
||||
if (curindex > 0)
|
||||
throw Error("Cannot mix named and positional indices in string formatting.");
|
||||
curindex = -1;
|
||||
|
||||
if (!(key in d))
|
||||
throw Error("Key '%s' not present during string substitution.".format(key));
|
||||
v = d[key];
|
||||
}
|
||||
switch (type) {
|
||||
case "s":
|
||||
if (v === undefined)
|
||||
return "<undefined>";
|
||||
return v.toString();
|
||||
case "r":
|
||||
return uneval(v);
|
||||
case "i":
|
||||
return parseInt(v);
|
||||
case "f":
|
||||
return Number(v);
|
||||
case "%":
|
||||
return "%";
|
||||
default:
|
||||
throw Error("Unexpected format character '%s'.".format(type));
|
||||
}
|
||||
}
|
||||
return this.replace(/%(\([^)]+\))?(.)/g, r);
|
||||
};
|
Загрузка…
Ссылка в новой задаче