Quantcast

libclang: Spelling on typedefs lacks namespaces

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

libclang: Spelling on typedefs lacks namespaces

Philip Reames via cfe-dev
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

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: libclang: Spelling on typedefs lacks namespaces

Philip Reames via cfe-dev
Hi Michael,

Thanks for the detailed report! I believe you're correct, clang_getTypeSpelling should return the fully qualified name for the typedefs since it does so for the other types. 

It looks like you're on the right track with the diff that you've shown. I would encourage you to submit it as a patch (with tests) to cfe-commits, either by using Phabricator (http://llvm.org/docs/Phabricator.html) or by emailing the patch directly to the list.

Cheers,
Alex


On 10 February 2017 at 12:39, Michael via cfe-dev <[hidden email]> wrote:
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

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: libclang: Spelling on typedefs lacks namespaces

Philip Reames via cfe-dev
Cool, sounds good. It's a few more tests to fix than expected, but stay
tuned for a patch.

Thanks

Michael

On 02/10/2017 03:25 PM, Alex L wrote:

> Hi Michael,
>
> Thanks for the detailed report! I believe you're
> correct, clang_getTypeSpelling should return the fully qualified name
> for the typedefs since it does so for the other types.
>
> It looks like you're on the right track with the diff that you've shown.
> I would encourage you to submit it as a patch (with tests)
> to cfe-commits, either by using Phabricator
> (http://llvm.org/docs/Phabricator.html) or by emailing the patch
> directly to the list.
>
> Cheers,
> Alex
>
>
> On 10 February 2017 at 12:39, Michael via cfe-dev
> <[hidden email] <mailto:[hidden email]>> wrote:
>
>     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
>
>     _______________________________________________
>     cfe-dev mailing list
>     [hidden email] <mailto:[hidden email]>
>     http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>     <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev>
>
>

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: libclang: Spelling on typedefs lacks namespaces

Philip Reames via cfe-dev
Please see https://reviews.llvm.org/D29944

Thanks

Michael

On 02/13/2017 02:47 PM, Michael via cfe-dev wrote:

> Cool, sounds good. It's a few more tests to fix than expected, but
> stay tuned for a patch.
>
> Thanks
>
> Michael
>
> On 02/10/2017 03:25 PM, Alex L wrote:
>> Hi Michael,
>>
>> Thanks for the detailed report! I believe you're
>> correct, clang_getTypeSpelling should return the fully qualified name
>> for the typedefs since it does so for the other types.
>>
>> It looks like you're on the right track with the diff that you've shown.
>> I would encourage you to submit it as a patch (with tests)
>> to cfe-commits, either by using Phabricator
>> (http://llvm.org/docs/Phabricator.html) or by emailing the patch
>> directly to the list.
>>
>> Cheers,
>> Alex
>>
>>
>> On 10 February 2017 at 12:39, Michael via cfe-dev
>> <[hidden email] <mailto:[hidden email]>> wrote:
>>
>>     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
>>
>>     _______________________________________________
>>     cfe-dev mailing list
>>     [hidden email] <mailto:[hidden email]>
>>     http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>> <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev>
>>
>>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Loading...