[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