aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
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
commit2cf9d656f6283f2a8be0549da110d7cfbb1ea4b2 (patch)
treecbcb070593bb170ec3e7aae8bc617367ecb6e5e3 /lib/AST
parentb3737e4fcddbf1c3126eb853c0e3b366b35ceaba (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114980 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTContext.cpp4
-rw-r--r--lib/AST/DeclCXX.cpp45
2 files changed, 38 insertions, 11 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index fdeac1ebf8..57780ef981 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3138,10 +3138,6 @@ QualType ASTContext::getObjCFastEnumerationStateType() {
Field->setAccess(AS_public);
ObjCFastEnumerationStateTypeDecl->addDecl(Field);
}
- if (getLangOptions().CPlusPlus)
- if (CXXRecordDecl *CXXRD =
- dyn_cast<CXXRecordDecl>(ObjCFastEnumerationStateTypeDecl))
- CXXRD->setEmpty(false);
ObjCFastEnumerationStateTypeDecl->completeDefinition();
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 440eaddb7c..0e37bc7801 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/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);