[cfe-dev] libclang: Spelling on typedefs lacks namespaces

Michael via cfe-dev cfe-dev at lists.llvm.org
Fri Feb 10 04:39:43 PST 2017


Hi

I'm using libclang to parse header files and generate code from them. I 
found that clang_getTypeSpelling() usually includes the namespace(s) a 
type was declared in. However with the exception being typedefs (and 
same for "using A = B"). Not sure if this is a bug or intended behavior, 
but it seems at least inconsistent. I also couldn't really find a good 
workaround for this. I'd have to manually figure out all typedefs (not 
just pure typedefs, they could also be nested template arguments or 
whatever) and then their originating namespaces. This is a bit 
cumbersome and not really straight forward. Getting the canonical type 
is also not really a solution as I would like to keep the typedefs.

Minimal example:

namespace foo {
class Bar {
};
typedef Bar BarDef;
}

clang_getTypeSpelling on "Bar" (kind "Record") gives: "foo::Bar"
clang_getTypeSpelling on "BarDef" (kind "Typedef") gives: "BarDef" (<== 
missing "foo::")


I had a look into the clang sources. It seems this little patch would 
fix the problem. This was pure guess work, I don't know what deeper 
consequences this might have.

Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp     (revision 294732)
+++ lib/AST/TypePrinter.cpp     (working copy)
@@ -96,7 +96,7 @@

      static bool canPrefixQualifiers(const Type *T, bool 
&NeedARCStrongQualifier);
      void spaceBeforePlaceHolder(raw_ostream &OS);
-    void printTypeSpec(const NamedDecl *D, raw_ostream &OS);
+    void printTypeSpec(NamedDecl *D, raw_ostream &OS);

      void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
      void printBefore(QualType T, raw_ostream &OS);
@@ -798,7 +798,14 @@
    printAfter(T->getReturnType(), OS);
  }

-void TypePrinter::printTypeSpec(const NamedDecl *D, raw_ostream &OS) {
+void TypePrinter::printTypeSpec(NamedDecl *D, raw_ostream &OS) {
+
+  // Compute the full nested-name-specifier for this type.
+  // In C, this will always be empty except when the type
+  // being printed is anonymous within other Record.
+  if (!Policy.SuppressScope)
+    AppendScope(D->getDeclContext(), OS);
+
    IdentifierInfo *II = D->getIdentifier();
    OS << II->getName();
    spaceBeforePlaceHolder(OS);

(I would of course also fix the unit tests if needed)

Please let me know what you think.

Thanks

Michael




More information about the cfe-dev mailing list