Crash in TagType::getAsString()

I have the following input:

int main(void)
{
  struct X { int a, b; };
  struct X x;
  x;
  return 0;
}

Which becomes:

(CompoundStmt 0x1c087c0
  (DeclStmt 0x1c086f0
    0x1c08580 "struct X;"
  (DeclStmt 0x1c08740
    0x1c08710 "struct X x"
  (DeclRefExpr 0x1c08770 'struct X' Var='x' 0x1c08710)
  (ReturnStmt 0x1c087b0
    (IntegerLiteral 0x1c08790 'int' 0)))

Now when I take the DeclRefExpr and call getType().getAsString(), I get a crash:

clang::TagType::getAsStringInternal (this=0x1c0a080,
InnerString=@0xbffff62c) at Type.cpp:1148

It seems that "getDecl()->getIdentifier()->getName()" on TagType
returns something invalid.

Interestingly, the dump shows "struct X" just fine, so perhaps it's
another user error on my part... though this time I am retaining the
AST and I am getting correct results with other inputs...

-Alexei

As a side note:

(CompoundStmt 0x1c087c0
(DeclStmt 0x1c086f0
   0x1c08580 "struct X;"
(DeclStmt 0x1c08740
   0x1c08710 "struct X x"
(DeclRefExpr 0x1c08770 'struct X' Var='x' 0x1c08710)
(ReturnStmt 0x1c087b0
   (IntegerLiteral 0x1c08790 'int' 0)))

... doesn't seem to have balanced parentheses.

Ok I figured out my problem.

Turns out the Preprocessor owns the IdentifierTable and I wasn't
keeping the Preprocessor around.

Are there any docs on what parts of the AST are owned by what? Also,
is there any way to get at the objects allocated by ParseAST if the
FreeMemory argument is false, so that I can delete them when I am done
with them?

Is there a reason that there isn't a self-contained AST object that
contains and owns everything necessary, rather than having different
parts of it owned by different classes?

It seems weird to me that the Preprocessor would retain ownership to
something used by the AST. To me, the name Preprocessor suggests that
its purpose it to preprocess the code, and I shouldn't need to keep it
around after that's done (but evidently that's not the case).

Sorry if there is a good reason to keep it this way, and I am just missing it.

-Alexei

Hi Alexei,

Some brief comments...

Ok I figured out my problem.

Turns out the Preprocessor owns the IdentifierTable and I wasn't
keeping the Preprocessor around.

Are there any docs on what parts of the AST are owned by what? Also,
is there any way to get at the objects allocated by ParseAST if the
FreeMemory argument is false, so that I can delete them when I am done
with them?

Nope. It looks like ASTContext and TranslationUnit should be passed into ParseAST.

This would give the client much more flexibility (and enable us to remove the "FreeMemory" argument).

Is there a reason that there isn't a self-contained AST object that
contains and owns everything necessary, rather than having different
parts of it owned by different classes?

It seems weird to me that the Preprocessor would retain ownership to
something used by the AST. To me, the name Preprocessor suggests that
its purpose it to preprocess the code, and I shouldn't need to keep it
around after that's done (but evidently that's not the case).

It is weird (and needs to be refined). The good news is core objects (like ASTContext) don't depend on having a Preprocessor object. So fixing this should be straightforward/localized.

snaroff