]> granicus.if.org Git - clang/commit
Completely re-implement the core logic behind the __is_standard_layout
authorChandler Carruth <chandlerc@gmail.com>
Sat, 30 Apr 2011 09:17:45 +0000 (09:17 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sat, 30 Apr 2011 09:17:45 +0000 (09:17 +0000)
commita8225449421e8c1e996a7c48300521028946482a
tree2351b1ca2ff393d595562f3d8838a917f6c97254
parent6e35b651cddbc69b2e8b95a32cfeb64cd2da13bf
Completely re-implement the core logic behind the __is_standard_layout
type trait. The previous implementation suffered from several problems:

1) It implemented all of the logic in RecordType by walking over every
   base and field in a CXXRecordDecl and validating the constraints of
   the standard. This made for very straightforward code, but is
   extremely inefficient. It also is conceptually wrong, the logic tied
   to the C++ definition of standard-layout classes should be in
   CXXRecordDecl, not RecordType.
2) To address the performance problems with #1, a cache bit was added to
   CXXRecordDecl, and at the completion of every C++ class, the
   RecordType was queried to determine if it was a standard layout
   class, and that state was cached. Two things went very very wrong
   with this. First, the caching version of the query *was never
   called*. Even within the recursive steps of the walk over all fields
   and bases the caching variant was not called, making each query
   a full *recursive* walk. Second, despite the cache not being used, it
   was computed for every class declared, even when the trait was never
   used in the program. This probably significantly regressed compile
   time performance for edge-case files.
3) An ASTContext was required merely to query the type trait because
   querying it performed the actual computations.
4) The caching bit wasn't managed correctly (uninitialized).

The new implementation follows the system for all the other traits on
C++ classes by encoding all the state needed in the definition data and
building up the trait incrementally as each base and member are added to
the definition of the class.

The idiosyncracies of the specification of standard-layout classes
requires more state than I would like; currently 5 bits. I could
eliminate one of the bits easily at the expense of both clarity and
resilience of the code. I might be able to eliminate one of the other
bits by computing its state in terms of other state bits in the
definition. I've already done that in one place where there was a fairly
simple way to achieve it.

It's possible some of the bits could be moved out of the definition data
and into some other structure which isn't serialized if the serialized
bloat is a problem. That would preclude serialization of a partial class
declaration, but that's likely already precluded.

Comments on any of these issues welcome.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130601 91177308-0d34-0410-b5e6-96231b3b80d8
include/clang/AST/DeclCXX.h
include/clang/AST/Type.h
lib/AST/DeclCXX.cpp
lib/AST/Type.cpp
lib/Sema/SemaExprCXX.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp