[cfe-dev] Printing "readably"

Peter Stirling peter at pjstirling.plus.com
Mon Sep 1 20:18:08 PDT 2014


Hi,

At the risk of over-promising, I'm working on a replacement for SWIG 
using clang. The basic idea is very simple: create a wrapper for each 
public function and method that is reachable from the source spec 
(ideally a system header to make it as friction free as possible). These 
wrappers will substitute pointers instead of references, objects with 
constructors, etc.

Obviously, clang makes it easy to get the list of functions and methods, 
and massaging "dangerous" types to pointers isn't that hard (as an 
aside, the documentation for PointerType would benefit from a sentence 
directing you to ASTContext for getting your hands on instances 
programmatically).
I have been using QualType.print(), but it has a couple of problems:

a) TypedefTypes aren't printed with their appropriate scope, and when I 
started using QualType.getCanonicalType() before printing (to eliminate 
typedefs),
b) NullPtrType is printed as "nullptr_t" rather than "std::nullptr_t" 
(or even "decltype(nullptr)")

Upon deciding to get my hands dirty, I investigated TypePrinter.cpp, and 
indeed printTypedefBefore() made no attempt to provide the scope of a 
typedef (even when PrintingPolicy.SuppressScope is false). I tried 
copying the relevant part of printTag(), which works for most cases, but 
now I get more subtle errors:

dummy.cc.cc:12176:102: error: 'new_allocator' is not a class, namespace, 
or scoped enumeration
__gnu_cxx::new_allocator::size_type

__gnu_cxx::new_allocator is a template, but in this case size_type 
doesn't depend on a template parameter (the source uses std::size_t 
unconditionally), from what I can gather from the source, the 
TypedefDecl is given the context of the CXXRecord, (and not the 
ClassTemplateSpecializationDecl) so it doesn't know that it should be 
giving template arguments.

If that is correct (is it correct?) then I don't know how I can safely 
output TypedefTypes without convincing the compiler to parse it 
differently, which puts me back to using getCanonicalType().

For ElaboratedTypes I need to ignore printing the NestedNameSpecifier, 
and then NOT enable PrintingPolicy::SuppressScope (which is done by the 
ElaboratedTypePolicyRAII). My current diff for the method uses 
SuppressScope to decide whether to print the full scope, which is 
(obviously) a potentially breaking change. Arguably instead of 
SuppressScope there should be a tri-state enum AsSource/Suppress/Force 
but I don't know whether you would be interested in making such a change.




More information about the cfe-dev mailing list