summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-09-28 20:38:10 +0000
committerDouglas Gregor <dgregor@apple.com>2010-09-28 20:38:10 +0000
commit9d5938ae8a117868a8258e6c2ca6f444e31274fd (patch)
tree3525fff120a6e19745c63aaf64a669396db6605b /clang/lib/AST/DeclCXX.cpp
parent750272d912f1233d12206782d75dabbc690770b2 (diff)
downloadbcm5719-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.cpp45
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);
OpenPOWER on IntegriCloud