[cfe-dev] Further AST spelunking

Peter Stirling peter at pjstirling.plus.com
Sun Mar 15 11:55:37 PDT 2015


Hi,

Still working on my SWIG replacement (slowly).

I re-wrote my walker this weekend to improve debugging and I've got a 
weirdness that I'd like explained:

The [first child of a [CXXRecordDecl that is not a forward declaration]] 
is (apparently always) a second (empty) CXXRecordDecl that uses the same 
identifier and source location.

For a file containing the following declarations:

class A {};
class B;

My trace output is:

walk CXXRecord A at 
/home/peter/Programming/llvm/ninja/../extra-dir/quaff/test.cc:23:1
   walk CXXRecord A::A at 
/home/peter/Programming/llvm/ninja/../extra-dir/quaff/test.cc:23:1
walk CXXRecord B at 
/home/peter/Programming/llvm/ninja/../extra-dir/quaff/test.cc:24:1

So, as a forward declaration, B has no children (as expected), but A has 
this strange child.

What purpose does this serve? Can I rely on it being that way into the 
future, and insert code that can automatically skip the first child (if 
there are any children)?


  On 11/10/14 21:27, Peter Stirling wrote:
> Never-mind, CompilerInstance::getSema()
>
> On 11/10/14 20:17, Peter Stirling wrote:
>> How do I get access to Sema, from a FrontendAction/ASTConsumer?
>>
>> On 09/10/14 21:40, Reid Kleckner wrote:
>>> On Thu, Oct 9, 2014 at 1:25 PM, Peter Stirling 
>>> <peter at pjstirling.plus.com <mailto:peter at pjstirling.plus.com>> wrote:
>>>
>>>>     I think you can compute this more directly with
>>>>     inType->isIncompleteType().
>>>
>>>     Thanks for the suggestion, I hadn't seen that either.
>>>     Unfortunately it doesn't work, for the same cases as
>>>     getDefinition(), these are (from my test data):
>>>
>>>       std::fpos<__mbstate_t >
>>>
>>>      ... snip ...
>>>
>>>     std::initializer_list<TagLib::String >
>>>
>>>
>>> I think these are just uninstantiated templates. We don't 
>>> instantiate templates when you declare a function that takes a 
>>> template specialization by value, for example, this code compiles:
>>> template <typename T> struct MyVec;
>>> void f(MyVec<int> v);
>>>
>>> ... but if you add a call to f, it will fail because it cannot 
>>> complete MyVec<int> by instantiation:
>>> void g(MyVec<int> &x) { f(x); }
>>>
>>> For your use case, you probably need to call RequireCompleteType at 
>>> the appropriate point. You may need to wait until the end of the TU 
>>> if there are some circular dependencies.
>>>
>>>>         I've also discovered that parsing code that calls a builtin
>>>>         function causes a no-argument, returns-int declaration to
>>>>         be inserted. It's been a while, but as I remember, in C
>>>>         this kind of declaration actually means that the function
>>>>         takes an unspecified number of arguments, but each one
>>>>         passed should be promoted to the size of an int (did they
>>>>         update this since pointers became much larger than ints?).
>>>>         In C++ it means something rather different. It seems a bit
>>>>         odd to me that builtin functions don't have the correct
>>>>         declaration inserted, since the compiler must have them on
>>>>         hand somewhere.
>>>>
>>>>
>>>>     Yes, in C, this is a no-prototype, implicit int return
>>>>     function. I'm not sure what kind of builtin function you're
>>>>     referring to. If the name starts with __builtin_, then the
>>>>     compiler knows the prototype. If it's a libc function like
>>>>     "fprintf()", then you will probably get a warning and the
>>>>     implicit declaration you describe. In C++, you shouldn't get
>>>>     these implicit declarations, it's just an error.
>>>
>>>     The functions that I've hit in my test data are:
>>>       __atomic_fetch_add();
>>>       __builtin_isfinite();
>>>       __builtin_isinf();
>>>       __builtin_isnan();
>>>       __builtin_isnormal();
>>>       __builtin_isgreater();
>>>       __builtin_isgreaterequal();
>>>       __builtin_isless();
>>>       __builtin_islessequal();
>>>       __builtin_islessgreater();
>>>
>>>     For all of the above FunctionDecl::getBuiltinID() returns non-zero.
>>>
>>>
>>> These are actually supposed to be variadic, according to the 
>>> builtins table:
>>> BUILTIN(__builtin_isunordered   , "i.", "nc")
>>>
>>> They have custom type checking:
>>> /// SemaBuiltinUnorderedCompare - Handle functions like 
>>> __builtin_isgreater and
>>> /// friends.  This is declared to take (...), so we have to check 
>>> everything.
>>> bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
>>
>>
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20150315/862b3853/attachment.html>


More information about the cfe-dev mailing list