[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cfe-dev
Subject:    Re: [cfe-dev] Tracing Typedef Chain
From:       Richard Smith via cfe-dev <cfe-dev () lists ! llvm ! org>
Date:       2015-11-30 22:15:28
Message-ID: CAOfiQqk+ZJbuh2ZVw+b4UiyxyCyB3XVZjPPx0ZE9RmysSUB3hQ () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


On Mon, Nov 30, 2015 at 12:48 PM, Daniel Dilts <diltsman@gmail.com> wrote:

> On Mon, Nov 30, 2015 at 11:12 AM, Richard Smith <richard@metafoo.co.uk>
> wrote:
>
>> On Mon, Nov 30, 2015 at 10:51 AM, Daniel Dilts via cfe-dev <
>> cfe-dev@lists.llvm.org> wrote:
>>
>>> I tried this with:
>>> auto t = type.getTypePtr();
>>> auto tt = dyn_cast<TypedefType>(t);
>>> while(tt) {
>>>   tt->getDecl()->dumpColor();
>>>   auto x = tt->getDecl()->getNameAsString();
>>>   tt = dyn_cast<TypedefType>(tt->desugar().getTypePtr());
>>> }
>>>
>>> It appeared to work fine when the typedef was at global scope, but when
>>> I put the typedef in a namespace the first dyn_cast returned nullptr.
>>>
>>
>> Right, in that case you will have an ElaboratedType representing the
>> nested name specifier written in the source, which desugars to the
>> TypedefType. Clang has a very rich modeling of type sugar, and you should
>> expect to see things other than TypedefTypes in your walk.
>>
>> Depending on what you're trying to do, you might want to consider
>> visiting the type with a RecursiveASTVisitor or repeatedly calling
>> getSingleStepDesugaredType to walk the desugarings of the type, or changing
>> your dyn_cast<TypedefType>(x) calls into x.getAs<TypedefType>() (which will
>> find the minimally-desugared typedef type in the single-step desugaring
>> sequence for x).
>>
>
> I tried using getSingleStepDesugaredType with this code:
> namespace Test
> {
>    typedef int X;
>    typedef X Y;
>    typedef Y Z;
> }
> Test::Z i;
>
>
> std::vector<std::string> names;
> names.push_back(type.getAsString());
> while(true)
>  {
>   type = type.getSingleStepDesugaredType(*result.Context);
>   names.push_back(type.getAsString());
> }
>
> getAsString() on the QualType returned this chain:
> Test::Z
> Z
> Y
> X
> int
>
> Ideally I would get this:
> Test::Z
> Test::Y
> Test::X
> int
>

You could check if each type is a TypedefType, grab its TypedefNameDecl,
and get the corresponding fully-qualified name. Clang's type sugar nodes
track how the type was written, and that's what you're seeing above.


> How would I use a RecursiveASTVisitor to walk just the type?  I can figure
> it out for an entire AST.
>

The same way, but start the recursion by calling TraverseType instead of
TraverseDecl. Note that this will recursively visit all of the AST "owned"
by that type, which may be more than you want.

[Attachment #5 (text/html)]

<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Nov 30, 2015 \
at 12:48 PM, Daniel Dilts <span dir="ltr">&lt;<a href="mailto:diltsman@gmail.com" \
target="_blank">diltsman@gmail.com</a>&gt;</span> wrote:<br><blockquote \
class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc \
solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div \
class="gmail_quote"><span class="">On Mon, Nov 30, 2015 at 11:12 AM, Richard Smith \
<span dir="ltr">&lt;<a href="mailto:richard@metafoo.co.uk" \
target="_blank">richard@metafoo.co.uk</a>&gt;</span> wrote:<br><blockquote \
class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid"><div \
dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span>On Mon, Nov 30, \
2015 at 10:51 AM, Daniel Dilts via cfe-dev <span dir="ltr">&lt;<a \
href="mailto:cfe-dev@lists.llvm.org" \
target="_blank">cfe-dev@lists.llvm.org</a>&gt;</span> wrote:<br><blockquote \
class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid"><div \
dir="ltr"><div>I tried this with:</div><div>auto t = \
type.getTypePtr();</div><div>auto tt = dyn_cast&lt;TypedefType&gt;(t);<br>while(tt) \
{</div><div>   tt-&gt;getDecl()-&gt;dumpColor();</div><div>   auto x = \
tt-&gt;getDecl()-&gt;getNameAsString();</div><div>   tt = \
dyn_cast&lt;TypedefType&gt;(tt-&gt;desugar().getTypePtr());</div><div>}</div><div><br></div><div>It \
appeared to work fine when the typedef was at global scope, but when I put the \
typedef in a namespace the first  dyn_cast returned \
nullptr.</div></div></blockquote><div><br></div></span><div>Right, in that case you \
will have an ElaboratedType representing the nested name specifier written in the \
source, which desugars to the TypedefType. Clang has a very rich modeling of type \
sugar, and you should expect to see things other than TypedefTypes in your \
walk.</div><div><br></div><div>Depending on what you&#39;re trying to do, you might \
want to consider visiting the type with a RecursiveASTVisitor or repeatedly calling \
getSingleStepDesugaredType to walk the desugarings of the type, or changing your \
dyn_cast&lt;TypedefType&gt;(x) calls into x.getAs&lt;TypedefType&gt;() (which will \
find the minimally-desugared typedef type in the single-step desugaring sequence for \
x).<br></div></div></div></div></blockquote><div><br></div></span><div>I tried using \
getSingleStepDesugaredType with this code:</div><div>namespace Test<br>{<span \
class=""><br>     typedef int X;<br>     typedef X Y;<br>     typedef Y \
Z;<br>}</span></div><div>Test::Z \
i;</div><div><br></div><div><br></div><div>std::vector&lt;std::string&gt; \
names;<br>names.push_back(type.getAsString());<br>while(true)<br>  {<br>   type = \
type.getSingleStepDesugaredType(*result.Context);<br>   \
names.push_back(type.getAsString());<br>}</div><div><br></div><div>getAsString() on \
the QualType returned this \
chain:</div><div>Test::Z</div><div>Z</div><div>Y</div><div>X</div><div>int</div><div><br></div><div>Ideally \
I would get this:</div><div>Test::Z</div><div>Test::Y</div><div>Test::X</div><div>int</div></div></div></div></blockquote><div><br></div><div>You \
could check if each type is a TypedefType, grab its TypedefNameDecl, and get the \
corresponding fully-qualified name. Clang&#39;s type sugar nodes track how the type \
was written, and that&#39;s what you&#39;re seeing above.</div><div>  \
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc \
solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div \
class="gmail_quote"><div>How would I use a RecursiveASTVisitor to walk just the type? \
I can figure it out for an entire AST.</div></div></div></div> \
</blockquote></div><br></div><div class="gmail_extra">The same way, but start the \
recursion by calling TraverseType instead of TraverseDecl. Note that this will \
recursively visit all of the AST &quot;owned&quot; by that type, which may be more \
than you want.</div></div>


[Attachment #6 (text/plain)]

_______________________________________________
cfe-dev mailing list
cfe-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic