Return type of statement

I am starting a project that will use clang. I'm asking to be pointed
in the right direction with a question I have. Here goes.

Given a context (ie a source file) and a statement somewhere in that
file, what's the easiest way to find the return type of that statement
with clang?

For example, for an assignment, it's the type of the variable, for a
function call, it's the return type, but obviously there are more
complicated examples in C semantics.

Surely, clang must be aware of this information, so what's the easiest
way to get at it (using code)?

-Alexei Svitkine

Alexei,

Statements that evalute to a value are known as expressions. Expressions are represented by the Expr class (which subclasses Stmt). The method Expr::getType() will return the information you want. I recommend looking at the Clang sources for example uses of this method.

Alexei,

Statements that evalute to a value are known as expressions.
Expressions are represented by the Expr class (which subclasses
Stmt). The method Expr::getType() will return the information you
want. I recommend looking at the Clang sources for example uses of
this method.

Try something like:

Stmt *S = ...

if (Expr *E = dyn_cast<Expr>(S))
   if (E->getType() == ... )
     ...

If something is a statement but not an expr, it doesn't produce a value (things like "if" or "break").

-Chris

Thanks for the pointers.

What's the best way to map from a location in the source to the
corresponding Stmt (and hence Expr if it is exists)?

-Alexei

There isn't an efficient way to do it. You'd have to walk the whole function body and look at the source ranges that each stmt covers, stopping at the smallest one that covers the point of interest. You could do this once and build a location -> stmt mapping of course. This would be useful if you do repeated queries (such as having a mouse float over code etc).

-Chris

Thanks for info.

I'm now getting a crash in getAsString() on the Expr's type:

if (clang::Expr *E = dyn_cast<clang::Expr>(S)) {
  std::cout << "Type: '" << E->getType().getAsString() << "'\n";
}

GDB prints:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xc000000f
0x00072d8a in clang::QualType::getAsStringInternal (this=0xbffff758,
S=@0xbffff754) at Type.cpp:894
894 getTypePtr()->getAsStringInternal(S);
(gdb) bt
#0 0x00072d8a in clang::QualType::getAsStringInternal
(this=0xbffff758, S=@0xbffff754) at Type.cpp:894
#1 0x000050a8 in clang::QualType::getAsString (this=0xbffff758) at Type.h:168

Am I doing something wrong, or is this a bug I stumbled upon?

Also, is there some better way to ask questions I encounter, rather
than emailing each one? Like some kind of irc chat? (I joined #llvm
but there didn't seem to be any clang discussion going on there...)

Or is bombarding this list with questions the way to go? :stuck_out_tongue:

-Alexei

Thanks for info.

I'm now getting a crash in getAsString() on the Expr's type:

if (clang::Expr *E = dyn_cast<clang::Expr>(S)) {
std::cout << "Type: '" << E->getType().getAsString() << "'\n";
}

GDB prints:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xc000000f
0x00072d8a in clang::QualType::getAsStringInternal (this=0xbffff758,
S=@0xbffff754) at Type.cpp:894
894 getTypePtr()->getAsStringInternal(S);
(gdb) bt
#0 0x00072d8a in clang::QualType::getAsStringInternal
(this=0xbffff758, S=@0xbffff754) at Type.cpp:894
#1 0x000050a8 in clang::QualType::getAsString (this=0xbffff758) at Type.h:168

Am I doing something wrong, or is this a bug I stumbled upon?

Hi Alexei,

It's hard to say without seeing the code being analyzed.

The ObjC rewriter uses the "getAsString()" API fairly extensively (so if there's a bug, it's not easy to diagnose without seeing the source).

Also, is there some better way to ask questions I encounter, rather
than emailing each one? Like some kind of irc chat? (I joined #llvm
but there didn't seem to be any clang discussion going on there...)

I'm not aware of any public IRC chat for clang. I believe the llvm IRC is fine for clang related stuff. In this case, however, email works fine. You could also submit a bugzilla.

snaroff

Oops, this meant to be a reply to all:

I'm attaching a sample program that demonstrates the issue.

The program is not trying to parse anything complicated... only:

int main(void){int i=0;i+=10;return 0;}

And trying to get the type of "i+=10". However, as I've mentioned, it
instead crashes when calling E->getType().getAsString().

But as Steve pointed out to me, using clang on the command line with
ast-print and -ast-dump on that little program works correctly, and
apparently that option does end up calling getAsString().

So I'm wondering if I'm using the API incorrectly in some way... can
anyone glance over my code and possibly give me a hint of what I'm
doing differently than how ast-print/ast-dump works that would cause
such a crash?

-Alexei

test2.cpp (2.52 KB)

You're using freed memory. Change:

  clang::ParseAST(pp, &consumer);

to:

clang::ParseAST(pp, &consumer, false, false);

This will disable ParseAST from destroying the ASTContext object (which includes the Types) and the statements when it completes. With this change I see the following output from your program:

   Type: 'int'