diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-09-28 20:38:10 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-09-28 20:38:10 +0000 |
| commit | 9d5938ae8a117868a8258e6c2ca6f444e31274fd (patch) | |
| tree | 3525fff120a6e19745c63aaf64a669396db6605b /clang/lib/AST/DeclCXX.cpp | |
| parent | 750272d912f1233d12206782d75dabbc690770b2 (diff) | |
| download | bcm5719-llvm-9d5938ae8a117868a8258e6c2ca6f444e31274fd.tar.gz bcm5719-llvm-9d5938ae8a117868a8258e6c2ca6f444e31274fd.zip | |
Centralize the management of CXXRecordDecl::DefinitionData's Empty bit
in CXXRecordDecl itself. Yes, this is also part of <rdar://problem/8459981>.
This reinstates r114924, with one crucial bug fix: we were ignoring
the implicit fields created by anonymous structs/unions when updating
the bits in CXXRecordDecl, which means that a class/struct containing
only an anonymous class/struct would be considered "empty". Hilarity
follows.
llvm-svn: 114980
Diffstat (limited to 'clang/lib/AST/DeclCXX.cpp')
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 440eaddb7c1..0e37bc7801c 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -105,6 +105,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // A POD-struct is an aggregate class... data().PlainOldData = false; + // A class with a non-empty base class is not empty. + // FIXME: Standard ref? + if (!BaseClassDecl->isEmpty()) + data().Empty = false; + // Now go through all virtual bases of this base and add them. for (CXXRecordDecl::base_class_iterator VBase = BaseClassDecl->vbases_begin(), @@ -118,8 +123,12 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // Add this base if it's not already in the list. if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType))) VBases.push_back(Base); + + // C++0x [meta.unary.prop] is_empty: + // T is a class type, but not a union type, with ... no virtual base + // classes + data().Empty = false; } - } if (VBases.empty()) @@ -285,6 +294,10 @@ CXXRecordDecl::addedMember(Decl *D) { // C++ [class]p4: // A POD-struct is an aggregate class... data().PlainOldData = false; + + // Virtual functions make the class non-empty. + // FIXME: Standard ref? + data().Empty = false; } } @@ -298,18 +311,24 @@ CXXRecordDecl::addedMember(Decl *D) { // declared it. else if (Constructor->isCopyConstructor()) data().DeclaredCopyConstructor = true; - } else if (isa<CXXDestructorDecl>(D)) { + return; + } + + if (isa<CXXDestructorDecl>(D)) { data().DeclaredDestructor = true; - } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { + return; + } + + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { // If this is the implicit copy constructor, note that we have now // declared it. // FIXME: Move constructors if (Method->getOverloadedOperator() == OO_Equal) data().DeclaredCopyAssignment = true; + return; } - - // Nothing else to do for implicitly-declared members. - return; + + // Any other implicit declarations are handled like normal declarations. } // Handle (user-declared) constructors. @@ -429,6 +448,19 @@ CXXRecordDecl::addedMember(Decl *D) { QualType T = Context.getBaseElementType(Field->getType()); if (!T->isPODType()) data().PlainOldData = false; + + // If this is not a zero-length bit-field, then the class is not empty. + if (data().Empty) { + if (!Field->getBitWidth()) + data().Empty = false; + else if (!Field->getBitWidth()->isTypeDependent() && + !Field->getBitWidth()->isValueDependent()) { + llvm::APSInt Bits; + if (Field->getBitWidth()->isIntegerConstantExpr(Bits, Context)) + if (!!Bits) + data().Empty = false; + } + } } } @@ -614,7 +646,6 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) { Method->setVirtualAsWritten(true); - setEmpty(false); setPolymorphic(true); setHasTrivialConstructor(false); setHasTrivialCopyConstructor(false); |

