[cfe-dev] API for auto type deduction in libclang

Kevin Funk krf at gmx.de
Tue Jan 28 03:40:06 PST 2014


Am Sonntag, 26. Januar 2014, 13:00:24 schrieb Jacob Carlborg:
> On 2014-01-25 22:03, Kevin Funk wrote:
> > That doesn't work for me.
> > 
> > For testing we have a small wrapper binary that basically creates a
> > CXTranslationUnit and then traverses through the AST via
> > clang_visitChildren().
> > 
> > During the call to 'visit' it does the following (amongst other things):
> > - auto location = clang_getCursorLocation(cursor)
> > - auto type = clang_getCursorType(cursor)
> > - auto typeString = clang_getTypeSpelling(type)
> > - now: auto canonicalTypeString =
> > 
> >      clang_getTypeSpelling(clang_getCanonicalType(type))
> > 
> > It outputs all the values of those variabes to stdout, and when I pass
> > "auto i = 5;" to it I get:
> > 
> > """
> > decl: "auto (canonical type: auto) i " of kind VarDecl (9) in
> > stdin.cpp at 1:6
> > 
> >    "int (canonical type: int) " of kind IntegerLiteral (106) in
> >    stdin.cpp at 1:10
> > 
> > """
> > 
> > So the 'canonical type' of VarDecl still resolves to 'auto', instead of
> > 'int'. Sorry, if we're doing something completely wrong, but I don't seem
> > to get this working as you suggest.
> 
> Ok, I see, you're using clang_getTypeSpelling. I created my tool before
> clang_getTypeSpelling was available. For aggregates, typedefs and a
> couple of other types I'm using the following code[1]:
> 
> auto cursor = clang_getTypeDeclaration(type);
> auto str = clang_getCursorSpelling(cursor);
> 
> For basic types like "int", "char" and so on, the above will return an
> empty string. For those types I use a big switch statement on the type
> kind and just returns a string representation [2].
> 
> [1]
> https://github.com/jacob-carlborg/dstep/blob/master/dstep/translator/Type.d#
> L43
> 
> [2]
> https://github.com/jacob-carlborg/dstep/blob/master/dstep/translator/Type.d#
> L248

Unfortunately, your source code doesn't help me, nor can I get it to work 
using any combination of getTypeDeclaration, getCursorSpelling, and the ones I 
referred to earlier...

I wonder if there's some bug in Clang's type printers I'm experiencing here.

Let's do some testing:
Test file: test.cpp, containing 'auto i = 5;'

$ clang -cc1 -std=c++11 -ast-dump test.cpp
(...)
`-VarDecl 0x1c2e5b0 <test.cpp:1:1, col:10> i 'int':'int'
  `-IntegerLiteral 0x1c2e608 <col:10> 'int' 5

=> What I'd expect! ('auto' => 'int')

Next try: My clang-standalone-parser (basically emulating 'clang -cc1 -dump') 
but using libclang only [1]:

$ ./clang-standalone-parser -std=c++11 test.cpp
test.cpp:1:6 (5, 0-10) kind: VarDecl type: auto display name: i (...)
  test.cpp:1:10 (9, 9-10) kind: IntegerLiteral type: int

=> Not what I'd expect, 'auto' is not deduced

And the odd part here is: Breaking on the symbol 
'clang::AutoType::getDeducedType()' for both clang and clang-standalone-parser 
shows that *both* versions actually call that function when trying to find a 
string representation for the type 'auto'. But with clang-standalone-parser, 
'clang::AutoType::getDeducedType()' always returns an null QualType.

Can someone make any sense out of this? Bug in Clang/LLVM? Note that the 
backtrace towards the call of getDeducedType is slightly different for the two 
versions (see attached file). Maybe this is the reason?

Any help greatly appreciated!

Greets

[1] http://quickgit.kde.org/?p=kdev-clang.git&a=blob&h=dbad9e8942cc5e20fd005677fc32a5a0b54977ae&hb=1fa9eca7a9a58404c3ef687fcfa63800d459cff5&f=tests%2Fclang-standalone-parser.c

Compiling is simple:
$ clang clang-standalone-parser.c -I/path/to/llvm/include -L/path/to/llvm/lib 
-lclang -Wl,-rpath,'/path/to/llvm/lib' -o clang-standalone-parser

-- 
Kevin Funk
-------------- next part --------------
BACKTRACE with 'clang':
#0  clang::AutoType::getDeducedType (this=0x5661170) at /home/krf/devel/src/llvm/tools/clang/include/clang/AST/Type.h:3670
#1  0x000000000327135a in (anonymous namespace)::TypePrinter::printAutoBefore (this=0x7fffffffbe40, T=0x5661170, OS=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/TypePrinter.cpp:815
#2  0x000000000326ebe8 in (anonymous namespace)::TypePrinter::printBefore (this=0x7fffffffbe40, T=0x5661170, Quals=..., OS=...) at /home/krf/devel/src/llvm/tools/clang/include/clang/AST/TypeNodes.def:99
#3  0x000000000326e311 in (anonymous namespace)::TypePrinter::print (this=0x7fffffffbe40, T=0x5661170, Quals=..., OS=..., PlaceHolder=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/TypePrinter.cpp:149
#4  0x0000000003274078 in clang::QualType::getAsStringInternal (ty=0x5661170, qs=..., buffer=..., policy=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/TypePrinter.cpp:1555
#5  0x0000000003273ec3 in clang::QualType::getAsString (ty=0x5661170, qs=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/TypePrinter.cpp:1537
#6  0x0000000001eddb3b in clang::QualType::getAsString (split=...) at /home/krf/devel/src/llvm/tools/clang/include/clang/AST/Type.h:868
#7  0x00000000030f254c in (anonymous namespace)::ASTDumper::dumpBareType (this=0x7fffffffc3f0, T=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/ASTDumper.cpp:444
#8  0x00000000030f2673 in (anonymous namespace)::ASTDumper::dumpType (this=0x7fffffffc3f0, T=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/ASTDumper.cpp:456
#9  0x00000000030fa1cc in (anonymous namespace)::ASTDumper::VisitVarDecl (this=0x7fffffffc3f0, D=0x5661050) at /home/krf/devel/src/llvm/tools/clang/lib/AST/ASTDumper.cpp:956
#10 0x0000000003100873 in clang::declvisitor::Base<clang::declvisitor::make_const_ptr, (anonymous namespace)::ASTDumper, void>::Visit (this=0x7fffffffc3f0, D=0x5661050) at tools/clang/include/clang/AST/DeclNodes.inc:391
#11 0x00000000030f958a in (anonymous namespace)::ASTDumper::dumpDecl (this=0x7fffffffc3f0, D=0x5661050) at /home/krf/devel/src/llvm/tools/clang/lib/AST/ASTDumper.cpp:762
#12 0x00000000030f29d5 in (anonymous namespace)::ASTDumper::dumpDeclContext (this=0x7fffffffc3f0, DC=0x5660690) at /home/krf/devel/src/llvm/tools/clang/lib/AST/ASTDumper.cpp:511
#13 0x00000000030f96a1 in (anonymous namespace)::ASTDumper::dumpDecl (this=0x7fffffffc3f0, D=0x5660670) at /home/krf/devel/src/llvm/tools/clang/lib/AST/ASTDumper.cpp:781
#14 0x00000000030fec53 in clang::Decl::dump (this=0x5660670, OS=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/ASTDumper.cpp:2107
#15 0x0000000001e63392 in (anonymous namespace)::ASTPrinter::print (this=0x56590d0, D=0x5660670) at /home/krf/devel/src/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp:87
#16 0x0000000001e63099 in (anonymous namespace)::ASTPrinter::HandleTranslationUnit (this=0x56590d0, Context=...) at /home/krf/devel/src/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp:48
#17 0x000000000296c1fa in clang::ParseAST (S=..., PrintStats=false, SkipFunctionBodies=false) at /home/krf/devel/src/llvm/tools/clang/lib/Parse/ParseAST.cpp:153
#18 0x0000000001e2abe0 in clang::ASTFrontendAction::ExecuteAction (this=0x5633650) at /home/krf/devel/src/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:477
#19 0x0000000001e2a713 in clang::FrontendAction::Execute (this=0x5633650) at /home/krf/devel/src/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:379
#20 0x0000000001e01406 in clang::CompilerInstance::ExecuteAction (this=0x5632ac0, Act=...) at /home/krf/devel/src/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp:705
#21 0x0000000001f1472e in clang::ExecuteCompilerInvocation (Clang=0x5632ac0) at /home/krf/devel/src/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:238
#22 0x0000000000c77355 in cc1_main (ArgBegin=0x7fffffffd3d8, ArgEnd=0x7fffffffd3f0, Argv0=0x7fffffffe170 "/home/krf/devel/build/llvm/bin/clang++", MainAddr=0xc70f33 <GetExecutablePath(char const*, bool)>
) at /home/krf/devel/src/llvm/tools/clang/tools/driver/cc1_main.cpp:101

BACKTRACE with 'clang-standalone-parser':
#0  clang::AutoType::getDeducedType (this=0x7ffff0033e10) at /home/krf/devel/src/llvm/tools/clang/include/clang/AST/Type.h:3670
#1  0x00007ffff6cfc47a in (anonymous namespace)::TypePrinter::printAutoBefore (this=0x7fffffffd2f0, T=0x7ffff0033e10, OS=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/TypePrinter.cpp:815
#2  0x00007ffff6cf9d08 in (anonymous namespace)::TypePrinter::printBefore (this=0x7fffffffd2f0, T=0x7ffff0033e10, Quals=..., OS=...) at /home/krf/devel/src/llvm/tools/clang/include/clang/AST/TypeNodes.de
f:99
#3  0x00007ffff6cf9431 in (anonymous namespace)::TypePrinter::print (this=0x7fffffffd2f0, T=0x7ffff0033e10, Quals=..., OS=..., PlaceHolder=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/TypePrinter
.cpp:149
#4  0x00007ffff6cfef42 in clang::QualType::print (ty=0x7ffff0033e10, qs=..., OS=..., policy=..., PlaceHolder=...) at /home/krf/devel/src/llvm/tools/clang/lib/AST/TypePrinter.cpp:1547
#5  0x00007ffff6a6e866 in clang::QualType::print (split=..., OS=..., policy=..., PlaceHolder=...) at /home/krf/devel/src/llvm/tools/clang/include/clang/AST/Type.h:880
#6  0x00007ffff6a6e800 in clang::QualType::print (this=0x7fffffffd440, OS=..., Policy=..., PlaceHolder=...) at /home/krf/devel/src/llvm/tools/clang/include/clang/AST/Type.h:876
#7  0x00007ffff6a6fdfa in clang_getTypeSpelling (CT=...) at /home/krf/devel/src/llvm/tools/clang/tools/libclang/CXType.cpp:230
#8  0x0000000000401734 in printCursor ()
#9  0x00000000004012f0 in visit ()
#10 0x00007ffff6a0be52 in clang::cxcursor::CursorVisitor::Visit (this=0x7fffffffd9d0, Cursor=..., CheckedRegionOfInterest=true) at /home/krf/devel/src/llvm/tools/clang/tools/libclang/CIndex.cpp:186
#11 0x00007ffff6a0d090 in clang::cxcursor::CursorVisitor::VisitChildren (this=0x7fffffffd9d0, Cursor=...) at /home/krf/devel/src/llvm/tools/clang/tools/libclang/CIndex.cpp:505
#12 0x00007ffff6a176d2 in clang_visitChildren (parent=..., visitor=0x401270 <visit>, client_data=0x7fffffffdba4) at /home/krf/devel/src/llvm/tools/clang/tools/libclang/CIndex.cpp:3142
#13 0x00000000004011a3 in main ()


More information about the cfe-dev mailing list