[cfe-commits] r114980 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/ASTContext.cpp lib/AST/DeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/type-traits.cpp
Douglas Gregor
dgregor at apple.com
Tue Sep 28 13:38:10 PDT 2010
Author: dgregor
Date: Tue Sep 28 15:38:10 2010
New Revision: 114980
URL: http://llvm.org/viewvc/llvm-project?rev=114980&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/SemaCXX/type-traits.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=114980&r1=114979&r2=114980&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Sep 28 15:38:10 2010
@@ -704,9 +704,6 @@
/// a check for union-ness.
bool isEmpty() const { return data().Empty; }
- /// Set whether this class is empty (C++0x [meta.unary.prop])
- void setEmpty(bool Emp) { data().Empty = Emp; }
-
/// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
/// which means that the class contains or inherits a virtual function.
bool isPolymorphic() const { return data().Polymorphic; }
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=114980&r1=114979&r2=114980&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Sep 28 15:38:10 2010
@@ -3138,10 +3138,6 @@
Field->setAccess(AS_public);
ObjCFastEnumerationStateTypeDecl->addDecl(Field);
}
- if (getLangOptions().CPlusPlus)
- if (CXXRecordDecl *CXXRD =
- dyn_cast<CXXRecordDecl>(ObjCFastEnumerationStateTypeDecl))
- CXXRD->setEmpty(false);
ObjCFastEnumerationStateTypeDecl->completeDefinition();
}
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=114980&r1=114979&r2=114980&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Sep 28 15:38:10 2010
@@ -105,6 +105,11 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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::setMethodAsVirtual(FunctionDecl *Method) {
Method->setVirtualAsWritten(true);
- setEmpty(false);
setPolymorphic(true);
setHasTrivialConstructor(false);
setHasTrivialCopyConstructor(false);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=114980&r1=114979&r2=114980&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Sep 28 15:38:10 2010
@@ -1958,11 +1958,8 @@
TInfo,
/*BitWidth=*/0, /*Mutable=*/false);
Anon->setAccess(AS);
- if (getLangOptions().CPlusPlus) {
+ if (getLangOptions().CPlusPlus)
FieldCollector->Add(cast<FieldDecl>(Anon));
- if (!cast<CXXRecordDecl>(Record)->isEmpty())
- cast<CXXRecordDecl>(OwningClass)->setEmpty(false);
- }
} else {
DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
assert(SCSpec != DeclSpec::SCS_typedef &&
@@ -6190,8 +6187,6 @@
if (!InvalidDecl && getLangOptions().CPlusPlus) {
CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
- if (!ZeroWidth)
- CXXRecord->setEmpty(false);
if (T->isReferenceType())
CXXRecord->setHasTrivialConstructor(false);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=114980&r1=114979&r2=114980&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Sep 28 15:38:10 2010
@@ -516,11 +516,6 @@
void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
const CXXRecordDecl *BaseClass,
bool BaseIsVirtual) {
- // A class with a non-empty base class is not empty.
- // FIXME: Standard ref?
- if (!BaseClass->isEmpty())
- Class->setEmpty(false);
-
// C++ [class.virtual]p1:
// A class that [...] inherits a virtual function is called a polymorphic
// class.
@@ -540,11 +535,6 @@
// A copy assignment operator is trivial if its class has no virtual
// base classes.
Class->setHasTrivialCopyAssignment(false);
-
- // C++0x [meta.unary.prop] is_empty:
- // T is a class type, but not a union type, with ... no virtual base
- // classes
- Class->setEmpty(false);
} else {
// C++ [class.ctor]p5:
// A constructor is trivial if all the direct base classes of its
Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=114980&r1=114979&r2=114980&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Tue Sep 28 15:38:10 2010
@@ -20,6 +20,13 @@
struct HasConv { operator int(); };
struct HasAssign { void operator =(int); };
+struct HasAnonymousUnion {
+ union {
+ int i;
+ float f;
+ };
+};
+
// Not PODs
typedef const void cvoid;
struct Derives : POD {};
@@ -84,6 +91,7 @@
int t12[T(__is_pod(HasConv))];
int t13[T(__is_pod(HasAssign))];
int t14[T(__is_pod(IntArNB))];
+ int t15[T(__is_pod(HasAnonymousUnion))];
int t21[F(__is_pod(Derives))];
int t22[F(__is_pod(HasCons))];
@@ -131,6 +139,7 @@
int t27[F(__is_empty(BitOnly))];
int t28[F(__is_empty(void))];
int t29[F(__is_empty(IntArNB))];
+ int t30[F(__is_empty(HasAnonymousUnion))];
// int t27[F(__is_empty(DerivesVirt))];
}
@@ -141,6 +150,7 @@
int t01[T(__is_class(Derives))];
int t02[T(__is_class(HasPriv))];
int t03[T(__is_class(ClassType))];
+ int t04[T(__is_class(HasAnonymousUnion))];
int t11[F(__is_class(int))];
int t12[F(__is_class(Enum))];
@@ -167,6 +177,7 @@
int t15[F(__is_union(UnionAr))];
int t16[F(__is_union(cvoid))];
int t17[F(__is_union(IntArNB))];
+ int t18[F(__is_union(HasAnonymousUnion))];
}
typedef Enum EnumType;
@@ -185,6 +196,7 @@
int t17[F(__is_enum(ClassType))];
int t18[F(__is_enum(cvoid))];
int t19[F(__is_enum(IntArNB))];
+ int t20[F(__is_enum(HasAnonymousUnion))];
}
typedef HasVirt Polymorph;
More information about the cfe-commits
mailing list