<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Oct 8, 2014 at 6:02 AM, Peter Stirling <span dir="ltr"><<a href="mailto:peter@pjstirling.plus.com" target="_blank">peter@pjstirling.plus.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi again,<br>
<br>
I'm still plodding away at my SWIG alternative. As I said in my previous email, typedefs that are declared within templates but which do not depend on any of the template arguments are held in the AST as children of a CXXRecordDecl ignorant of the fact that it should be a template and what its arguments should be. This is a problem for me because it means that I can't print a properly scoped name to identify the type for c++ code. I have managed to work around this by adding a check for whether a typedef is a child of a CXXRecordDecl but should really be a child of a template. The code I'm using appears to work, but I'd like to double-check that it is appropriate:<br>
<br>
bool shouldBeTemplate(clang::<u></u>DeclContext const* context) {<br>
  if(context->getDeclKind() == clang::Decl::CXXRecord) {<br>
    auto record = llvm::cast<clang::<u></u>CXXRecordDecl>(context);<br>
    auto dname = record->getDeclName();<br>
    // there will always be a parent<br>
    auto cursor = context->getParent()->lookup(<u></u>dname);<br>
    for(auto named : cursor) {<br>
      if(llvm::isa<clang::<u></u>ClassTemplateDecl>(named)) {<br>
        return true;<br>
      }<br>
    }<br>
  }<br>
  return false;<br>
}<br></blockquote><div><br></div><div>I think what you are trying to compute is equivalent to context->isDependentContext(), which returns true if this context is nested inside any template, class or function.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Another issue is that, while it is safe to handle values that are pointers to incomplete structure types, it is illegal to call a function that takes an argument value or returns a result value that is an incomplete type. My first attempt was to check for RecordTypes and call CXXRecordDecl::getDefinition()<u></u>, but for some (but confusingly to me, not all) template types getDefinition() returns NULL even though the type isn't incomplete, is this expected? The code that I'm using is below, I also wonder whether getCanonicalDecl() is overkill here:<br>
<br>
bool isIncompleteType(clang::<u></u>QualType inType) {<br>
  if(inType->isRecordType()) {<br>
    auto realType = inType->getAs<clang::<u></u>RecordType>();`<br>
    auto decl = realType->getDecl()-><u></u>getCanonicalDecl();<br>
    if(decl->getDefinition() ||<br>
llvm::isa<clang::<u></u>ClassTemplateSpecializationDec<u></u>l>(decl)) {<br>
      return false;<br>
    }<br>
    else {<br>
      return true;<br>
    }<br>
  }<br>
  return false;<br>
}<br></blockquote><div><br></div><div>I think you can compute this more directly with inType->isIncompleteType().</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
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.<br></blockquote><div><br></div><div>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.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Finally, I need to generate the list of base classes that a derived class can be implicitly converted to. I have an intuitive understanding of when it should work, but when I try to think of an algorithm to sort out arbitrarily-evil trees combining virtual and normal inheritance I go a bit cross-eyed. Can anyone point me at something that will help me figure this out?</blockquote><div><br></div><div>The inheritance hierarchy is always a directed acyclic graph, so you can walk it recursively as long as you remember what you've already seen. If you have a class with multiple base subobjects of the same type and you don't care about which one an implicit conversion would pick, then you can do depth-first search and throw everything into a set:</div><div>  // Result is the set BasesSeen.</div><div>  void doit(BasesSeen, RD)</div><div>    if (RD in BasesSeen)</div><div>      return</div><div>    BasesSeen.insert(RD)</div><div>    for (Base in RD.bases())</div><div>      doit(BasesSeen, Base)</div><div><br></div><div>Hope that helps!</div></div></div></div>