[cfe-dev] [PATCH] PCH Support for C++ decls
Douglas Gregor
dgregor at apple.com
Wed Mar 3 08:44:08 PST 2010
Sent from my iPhone
On Mar 3, 2010, at 7:08 AM, Andrew Sutton <andrew.n.sutton at gmail.com>
wrote:
>
> > Since I noticed Doug commit PCH support for NamespaceDecl's the
> other day (week?), I thought I'd send an update to my last PCH
> patch. I've been sitting on this work for quite some time while I've
> been busy with other things.
> >
>
> Nifty.
>
> I've spent the morning addressing issues in the patch and had some
> questions, comments. I'm not sending up a new patch just yet, though.
>
> I think we really need better tests. Due to PCH's laziness, it is
> extremely annoying to debug when it breaks, so small tests for each
> kind of declaration/statement/expression are important for catching
> problems quickly.
>
> Yes... it is very annoying to debug :)
>
> We should keep the existing DECL_* constants in order, since each
> reshuffle is (unnecessary) breakage in backward-compatibility for
> the PCH format.
>
> I moved all of the constants down to the bottom (and reorganized a
> couple).
Thanks.
>
> I don't see why we should need this. We already have startDefinition
> ()/completeDefinition(), which takes care of allocating the
> DefinitionData and linking it in.
>
> Removed. I was concerned about side effects, but after looking I
> don't think there are any. I'm still having problems understanding
> which classes should be serialized. More below.
>
> Please store/load fields in the PCH record in the same order as they
> occur in the corresponding AST; it makes it easier to verify that
> everything is there. In this case, BaseOfClass and Virtual should be
> swapped (the same goes for the reader).
>
> I think I've addressed all instances that you've pointed out, but
> haven't checked every decl yet. I wish there was an easier way to do
> this. Maybe I could use clang to dump the order of members...
Well, Clang can clearly parse itself, which means that there is a fun
(but time-consuming) answer to this.
>
> Why const-qualify the NestedNameSpecifier? You're just
> const_cast'ing it away anyway.
>
> It's a non-modifying operation. I was only const-casting it away
> because getPrefix() returns a non-const ptr. It's probably easier
> just to remove the const in the function that try to make NNS more
> const-friendly.
A const getPrefix (which does a const_cast internally) would be fine.
NestedNameSpecifiers are logically immutable anyway.
>
> Why not push all of the NestedNameSpecifiers onto a stack and then
> emit them in reverse order? That would make it far easier for the
> reader to reconstruct them properly, since the prefix will come
> before the nested-name-specifier itself.
>
> This won't work with nested-name-specifiers that have prefixes,
> because we see the nested-name-specifier before its prefix, and end
> up trying to build the nested-name-specifier backwards. Use the
> stack I mentioned previously to address this problem, and you can
> then get rid of the NNS/P dance, since the last nested-name-
> specifier you build will be the complete one.
>
> For some reason, I thought that trying to write this without a stack
> would be a better solution. Other than that no real reason. I'll
> rewrite this in the next day or two.
SmallVector makes a good stack.
>
> FWIW, I've typically been ordering the Visit functions the same way
> as the Decl nodes are ordered in DeclNodes.def.
>
> Fair enough. Would it be worthwhile reordering all of the ObjC
> visitors too?
Not in this patch. We can tweak that later.
>
> Aside: anonymous namespaces are somewhat interesting for PCH,
> because we need to make sure that an anonymous namespace defined in
> the source file gets linked to an anonymous namespace defined in the
> PCH file, since they are effectively the same anonymous namespace.
> One fun way to test this is:
>
> // In PCH:
> namespace {
> class X;
> }
>
> // In source file (that includes PCH):
> namespace {
> class X;
> }
>
> I'll add this to the test tomorrow.
>
> +void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
> + VisitRecordDecl(D);
> + // Injected class names are, I think, actually empty.
>
> Yes, they are. Aside from making sure to get them into the right
> declaration context and link up their previous declaration chains,
> there shouldn't be much to serialize for them.
>
> isInjectedClassName() is the wrong check for this. Instead,
> PCHDeclWriter::VisitCXXRecordDecl should serialize all of the bits
> in the definition when D->getDefinition() == D, i.e., the
> declaration you're serializing is the definition.
>
> This is where I'm a little lost w.r.t. class decls, defs, and
> injected names... Here's my current understanding.
>
> class C; // call this CXXRecordDecl* decl;
> class C { }; // call this CXXRecordDecl* def;
> // call C::C (the injected name) CXXRecordDecl *inj;
>
> decl->getDefinition() == def
> def->getDefinition() == def
> decl in def->redeclarations() // pseduo python-ese
> inj->getDefinition() == def // ???
Yes
> decl->DefinitionData == def->DefinitionData == inj-
> >DefinitionData // ???
> decl->DefiniotinData->Definition == def // ???
Yes. An injected-class-name is just a redeclaration with a funny
scope. And getDefinition always points at the definition.
> And then for a slightly different case, if C isn't defined (so def
> == inj == 0), then:
> decl->getDefinition() == 0?
Yes.
> Is this about right or is there something I might be missing?
I think you have it correct.
> Also, w.r.t. class serialization. Should virtual bases be serialized
> the same way that regular bases are serialized? What b
They're all the same. Decls are serialized as a reference to somewhere
else in the PCH, so it doesn't matter how many times we reference that
decl.
> +void PCHDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
> + VisitCXXMethodDecl(D);
> + D->setExplicitSpecified(Record[Idx++]);
> + if (D->isThisDeclarationADefinition())
> + D->setImplicitlyDefined(Record[Idx++]);
> + // FIXME: Serialize member initializers?
> +}
>
> I suggest that the PCH reader/writer avoid cleverness, and serialize
> exactly what is in the AST (rather than doing the
> isThisDeclarationADefinition() check).
>
> This is a problem since isImplicitlyDefined and setImplicitlyDefined
> will assert if isThisDeclarationADefintion returns false. Would it
> be an acceptable workaround to add non-asserting accessors?
Oh, I missed the assert. In that case, please ignore my comment.
> Back to work...
>
> Andrew Sutton
> andrew.n.sutton at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20100303/eadfe5a6/attachment.html>
More information about the cfe-dev
mailing list