H.J. Hoogendorp wrote:
Dear Mr. Glek,
I am a student at the university of Groningen in the Netherlands.
Currently I am
working on my master's thesis on program slicing, with Alex Telea as
my supervisor.
An important part of this project concerns the construction of a call
graph. For this,
I am using the Elsa open-source parser. Mr. Telea tells me you have a
great deal of
knowledge and experience with the Elsa parser and it is on this that I
would like to
ask you for your expertise.
For the most part, it is relatively straightforward to extract the
information I'm looking for
from the AST, which Elsa gives me. Extracting function definitions and
most function calls
is not a problem. However, the extraction of "implicit" function calls
is giving me some
problems. Let me elaborate where I encounter this problem, using three
scenarios:
Hey Hessel,
I'm CCing our static analysis mailing list and oink's possibly dead
mailing list. I suggest in the future you post to
them(dev-static-analysis one is a sure bet, but there might be more
knowledgeable lurkers on the oink-devel one).
Elsa provides multiple views of the ast. I think you want the elaborated
AST and you must be looking at the wrong one. I think that implies using
the LoweredASTVisitor(it vists all of the AST nodes I expect to be
visited, unlike the default visitors, not completely sure why).
I suggest you download pork(http://developer.mozilla.org/en/Pork) and
use the staticprint tool to examine the AST. It'll save you a lot of
debugging time.
In this case ./staticprint -fo-print-elaborated-ast yourtestcase.cc will
show you the implicit constructors/destructors you want.
I'm attaching output from running staticprint on the first testcase.
Cheers,
Taras
SCENARIO 1 - Ctor & dtor call on class instantiation
====================================================
class T; // Somewhere, a class T is defined.
void f()
{
// Here, the default ctor of T is called. Then, at the end of the
scope of f,
// T's destructor is called. However, these calls (ctor & dtor)
cannot be found by
// a "normal" tree traversal using an ASTVisitor. At least, I
could not find them.
T t;
}
=== END
SCENARIO 2 - Dtor call on passing an object as a by-value parameter
===================================================================
class T; // Somewhere, a class T is defined.
void g(T t); // Somewhere, a function g is defined,
// taking an instance of T as a by-value argument.
void f()
{
T t;
// The difficulty is with the function call below. When object t
is passed
// to function g, T's copy-ctor is called. This copy-ctor call is
present in
// the AST and can be found by a "normal" tree traversal using an
ASTVisitor.
// However, the corresponding destructor call is not present in
the AST.
g(t);
}
=== END
SCENARIO 3 - Ctor call on returning an object
=============================================
class T; // Somewhere, a class T is defined.
T f()
{
T t;
// The "by-value" return of object t causes a call to the
copy-ctor of T.
// However, I could not find the call by a "normal" tree traversal
using an
// ASTVisitor.
return t;
}
=== END
By a "normal" tree traversal I mean calling 'traverse' only once,
say on the TranslationUnit (and not calling 'traverse' manually on
parts of the
tree that are not visited by default).
Now, my question is as follows:
* Is it possible to find these mentioned function calls by a normal
tree traversal, - or,
* Do I need to manually traverse different parts of the tree, which
are not traversed by default, - or,
* Do I need to infer certain function calls from the relevant contexts
myself?
I am very interested in hearing what you think would be the proper way
of locating these function calls.
In advance, thank you for your time,
Kind regards,
Hessel Hoogendorp
[EMAIL PROTECTED]
---- START ---- implicit.cc
tree = TranslationUnit:
topForms:
topForms[0] = TF_decl:
loc = implicit.cc:1:1
decl = Declaration:
dflags =
spec = TS_classSpec:
loc = implicit.cc:1:1
cv =
keyword = struct
name = PQ_name:
loc = implicit.cc:1:8
name = "T"
bases:
members = MemberList:
list:
list[0] = MR_func:
loc = implicit.cc:1:1
endloc = <noloc>:1:1
f = Function:
funcType = ()()
receiver = T &__receiver, at implicit.cc:1:1 (0x09914218)
retVar: T &<retVar>, at implicit.cc:1:1 (0x099158C8)
dflags = inline (member) (implicit)
retspec = TS_type:
loc = implicit.cc:1:1
cv =
type = T
nameAndParams = Declarator:
var: (member) (definition) (implicit) constructor-special()
(2 overloadings)
context = DC_FUNCTION
decl = D_func:
loc = implicit.cc:1:1
base = D_name:
loc = implicit.cc:1:1
name = PQ_variable:
loc = implicit.cc:1:1
var = constructor-special()
params:
cv =
exnSpec is null
kAndR_params:
ql =
init is null
ctorStatement is null
dtorStatement is null
inits:
body = S_compound:
succ={ }
loc = implicit.cc:1:1
endloc = <noloc>:1:1
stmts:
handlers:
dtorStatement is null
implicitlyDefined = true
list[1] = MR_func:
loc = implicit.cc:1:1
endloc = <noloc>:1:1
f = Function:
funcType = ()(T const &__other)
receiver = T &__receiver, at implicit.cc:1:1 (0x09914158)
retVar: T &<retVar>, at implicit.cc:1:1 (0x09914058)
dflags = inline (member) (implicit)
retspec = TS_type:
loc = implicit.cc:1:1
cv =
type = T
nameAndParams = Declarator:
var: (member) (definition) (implicit) constructor-special(T
const &__other)
context = DC_FUNCTION
decl = D_func:
loc = implicit.cc:1:1
base = D_name:
loc = implicit.cc:1:1
name = PQ_variable:
loc = implicit.cc:1:1
var = constructor-special(T const &__other)
params:
params[0] = ASTTypeId:
spec = TS_type:
loc = implicit.cc:1:1
cv =
type = T const &
decl = Declarator:
var: (parameter) T const &__other
context = DC_D_FUNC
decl = D_name:
loc = implicit.cc:1:1
name = PQ_variable:
loc = implicit.cc:1:1
var = T const &__other
init is null
ctorStatement is null
dtorStatement is null
cv =
exnSpec is null
kAndR_params:
ql =
init is null
ctorStatement is null
dtorStatement is null
inits:
body = S_compound:
succ={ }
loc = implicit.cc:1:1
endloc = <noloc>:1:1
stmts:
handlers:
dtorStatement is null
implicitlyDefined = true
list[2] = MR_func:
loc = implicit.cc:1:1
endloc = <noloc>:1:1
f = Function:
funcType = T &()(T const &__other)
receiver = T &__receiver, at implicit.cc:1:1 (0x09917D48)
retVar: NULL
dflags = inline (member) (implicit)
retspec = TS_type:
loc = implicit.cc:1:1
cv =
type = T &
nameAndParams = Declarator:
var: (member) (definition) (implicit) T &operator=(T const
&__other)
context = DC_FUNCTION
decl = D_func:
loc = implicit.cc:1:1
base = D_name:
loc = implicit.cc:1:1
name = PQ_variable:
loc = implicit.cc:1:1
var = T &operator=(T const &__other)
params:
params[0] = ASTTypeId:
spec = TS_type:
loc = implicit.cc:1:1
cv =
type = T const &
decl = Declarator:
var: (parameter) T const &__other
context = DC_D_FUNC
decl = D_name:
loc = implicit.cc:1:1
name = PQ_variable:
loc = implicit.cc:1:1
var = T const &__other
init is null
ctorStatement is null
dtorStatement is null
cv =
exnSpec is null
kAndR_params:
ql =
init is null
ctorStatement is null
dtorStatement is null
inits:
body = S_compound:
succ={ }
loc = implicit.cc:1:1
endloc = <noloc>:1:1
stmts:
stmts[0] = S_return:
succ={ }
loc = implicit.cc:1:1
endloc = <noloc>:1:1
expr = FullExpression:
expr = E_deref:
type: T &
loc = implicit.cc:1:1
endloc = <noloc>:1:1
ptr = E_this:
type: T * const
loc = implicit.cc:1:1
endloc = <noloc>:1:1
ctorStatement is null
handlers:
dtorStatement is null
implicitlyDefined = true
list[3] = MR_func:
loc = implicit.cc:1:1
endloc = <noloc>:1:1
f = Function:
funcType = ()()
receiver = T &__receiver, at implicit.cc:1:1 (0x09917EC0)
retVar: NULL
dflags = inline (member) (implicit)
retspec = TS_type:
loc = implicit.cc:1:1
cv =
type = void
nameAndParams = Declarator:
var: (member) (definition) (implicit) ~T()
context = DC_FUNCTION
decl = D_func:
loc = implicit.cc:1:1
base = D_name:
loc = implicit.cc:1:1
name = PQ_variable:
loc = implicit.cc:1:1
var = ~T()
params:
cv =
exnSpec is null
kAndR_params:
ql =
init is null
ctorStatement is null
dtorStatement is null
inits:
body = S_compound:
succ={ }
loc = implicit.cc:1:1
endloc = <noloc>:1:1
stmts:
handlers:
dtorStatement = S_compound:
succ={ }
loc = implicit.cc:1:1
endloc = <noloc>:1:1
stmts:
implicitlyDefined = true
decllist:
topForms[1] = TF_func:
loc = implicit.cc:4:1
f = Function:
funcType = void ()()
receiver = NULL
retVar: NULL
dflags =
retspec = TS_simple:
loc = implicit.cc:4:1
cv =
id = void
nameAndParams = Declarator:
var: (global) (definition) void f()
context = DC_FUNCTION
decl = D_func:
loc = implicit.cc:4:6
base = D_name:
loc = implicit.cc:4:6
name = PQ_name:
loc = implicit.cc:4:6
name = "f"
params:
cv =
exnSpec is null
kAndR_params:
ql =
init is null
ctorStatement is null
dtorStatement is null
inits:
body = S_compound:
succ={ }
loc = implicit.cc:5:1
endloc = implicit.cc:10:2
stmts:
stmts[0] = S_decl:
succ={ }
loc = implicit.cc:9:3
endloc = implicit.cc:9:7
decl = Declaration:
dflags =
spec = TS_name:
loc = implicit.cc:9:3
cv =
name = PQ_name:
loc = implicit.cc:9:3
name = "T"
typenameUsed = false
decllist:
decllist[0] = Declarator:
var: (definition) T t
context = DC_S_DECL
decl = D_name:
loc = implicit.cc:9:5
name = PQ_name:
loc = implicit.cc:9:5
name = "t"
init = IN_ctor:
loc = implicit.cc:9:5
args:
was_IN_expr = false
ctorStatement = S_expr:
succ={ }
loc = implicit.cc:9:5
endloc = <noloc>:1:1
expr = FullExpression:
expr = E_constructor:
type: T
ctorVar: constructor-special(), at implicit.cc:1:1
(0x09917B18)
loc = implicit.cc:9:5
endloc = <noloc>:1:1
spec = TS_type:
loc = implicit.cc:9:5
cv =
type = T
args:
artificial = true
retObj = E_variable:
type: T &
var: T t, at implicit.cc:9:5 (0x099184B8)
loc = implicit.cc:9:5
endloc = <noloc>:1:1
name = PQ_variable:
loc = implicit.cc:9:5
var = T t
dtorStatement = S_expr:
succ={ }
loc = implicit.cc:9:5
endloc = <noloc>:1:1
expr = FullExpression:
expr = E_funCall:
type: void
loc = implicit.cc:9:5
endloc = <noloc>:1:1
func = E_fieldAcc:
type: ()()
field: ~T(), at implicit.cc:1:1 (0x09917F18)
loc = implicit.cc:9:5
endloc = <noloc>:1:1
obj = E_variable:
type: T &
var: T t, at implicit.cc:9:5 (0x099184B8)
loc = implicit.cc:9:5
endloc = <noloc>:1:1
name = PQ_variable:
loc = implicit.cc:9:5
var = T t
fieldName = PQ_variable:
loc = implicit.cc:9:5
var = ~T()
args:
retObj is null
handlers:
dtorStatement is null
implicitlyDefined = false
---- STOP ----
_______________________________________________
dev-static-analysis mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-static-analysis