[PATCH] Microsoft C++ Record Layout
Reid Kleckner
rnk at google.com
Sun Oct 6 10:41:29 PDT 2013
Here's some initial comments, I haven't actually gotten through everything. Travel and other stuff kept this off my plate.
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:58-60
@@ +57,5 @@
+ MicrosoftRecordLayoutBuilder(const ASTContext &Context) : Context(Context) {}
+ MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &)
+ LLVM_DELETED_FUNCTION;
+ void operator=(const MicrosoftRecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
+
----------------
The usual pattern is to make these private as well as deleted, so that you get a link error when they are used in C++98.
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:64
@@ +63,3 @@
+ void cxxLayout(const CXXRecordDecl *RD);
+ /// \brief Initializes size and alignemnt and honors some flags.
+ void initializeLayout(const RecordDecl *RD);
----------------
"alignment", you may want to hit the other comments with spellcheck.
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:89
@@ +88,3 @@
+
+ /// \brief Updates the alignment of the type. This function doesn't take any properties (such as packedness) into account. getAdjustedFieldInfo() adjustes for packedness.
+ void updateAlignment(CharUnits NewAlignment) {
----------------
Reflow
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:184
@@ +183,3 @@
+
+ // If we're not on win32 and using ms_struct the field alignment will be wrong
+ // for 64 bit types, so we fix that here.
----------------
We decided not to thread ms_struct through here, so let's kill this dead code.
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:1
@@ +1,2 @@
+//=== MicrosoftRecordLayoutBuilder.cpp - Microsoft record layout helpers ---==//
+//
----------------
I'd like to push to keep this in RecordLayoutBuilder.cpp, even though it doesn't share any code. I have a feeling that over the long term we may be able to factor these together in a way that we can share the bitfield layout code and split the C++ record layout code. If we split the files, we're raising the difficulty bar for any potential refactoring.
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:231-249
@@ +230,21 @@
+
+void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
+ initializeLayout(RD);
+ layoutFields(RD);
+ honorDeclspecAlign(RD);
+}
+
+void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
+ initializeLayout(RD);
+ initializeCXXLayout(RD);
+ layoutVFPtr(RD);
+ layoutNonVirtualBases(RD);
+ layoutVBPtr(RD);
+ layoutFields(RD);
+ DataSize = Size;
+ NonVirtualAlignment = Alignment;
+ layoutVirtualBases(RD);
+ finalizeCXXLayout(RD);
+ honorDeclspecAlign(RD);
+}
+
----------------
Nice!
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:322
@@ +321,3 @@
+ // MSVC potentially over-aligns the vf-table pointer by giving it
+ // the max alignment of all the non-virtual data in the class. The resulting layout is essentially { vftbl, { nvdata } }.
+ // This is completely unnecessary, but we're not here to pass
----------------
Reflow
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:550
@@ +549,3 @@
+ // The space consumed is in an Alignment sized/aligned block and the v-base
+ // is placed at its alignment offset into the chunck, unless its alignment
+ // is less than the size of a pointer, at which it is placed at pointer
----------------
"chunk"
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:620
@@ +619,3 @@
+}
+;
+
----------------
Loose ;
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:644
@@ +643,3 @@
+ // defined in
+ // in a virtual base's vtable, that virtual bases need a vtordisp. If Here we
+ // collect a list of classes
----------------
Stray "If"?
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:649
@@ +648,3 @@
+ // contain non-virtual
+ // bases that define functions we override also require vtorcisps, this case
+ // is checked explicitly below.
----------------
s/vtorcisps/vtordisps/
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:667-670
@@ +666,6 @@
+ else
+ do {
+ // The method lives in a base; add the overrides to our working set.
+ work.insert(*i);
+ } while (++i != e);
+ // We've finished processing this element, remove it from the working set.
----------------
Can this be work.insert(i, e)?
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:652
@@ +651,3 @@
+ if (RD->hasUserDeclaredConstructor() || RD->hasUserDeclaredDestructor()) {
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8> work;
+ // Seed the working set with our non-destructor virtual methods.
----------------
The convention is to use UpperCase local variables. Yeah, it's crazy, but it's the norm.
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:682
@@ +681,3 @@
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(i->getType()->castAs<RecordType>()->getDecl());
+ if (!HasVtordisp.count(BaseDecl) && RequiresVtordisp(HasVtordisp, BaseDecl))
----------------
This can probably be: i->getType()->getAsCXXRecordDecl()
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:604
@@ +603,3 @@
+static bool
+RequiresVtordisp(const llvm::SmallPtrSet<const CXXRecordDecl *, 2> &HasVtordisp,
+ const CXXRecordDecl *RD) {
----------------
As discussed in person, I think it will simplify things if we add a 'bool RequiresVtorDisp' to ASTRecordLayout::CXXRecordLayoutInfo.
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:654
@@ +653,3 @@
+ // Seed the working set with our non-destructor virtual methods.
+ for (clang::CXXRecordDecl::method_iterator i = RD->method_begin(),
+ e = RD->method_end();
----------------
We're in using namespace clang.
================
Comment at: lib/AST/MicrosoftRecordLayoutBuilder.cpp:676-677
@@ +675,4 @@
+
+ // Re-check all of our vbases for vtordisp requirements (in case their
+ // non-virtual bases have vtordisp requirements).
+ for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(),
----------------
In person we tried to come up with a cleaner way to do this, but I can't recall what it was.
http://llvm-reviews.chandlerc.com/D1026
More information about the cfe-commits
mailing list