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 | |
| 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')
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 45 | 
2 files changed, 38 insertions, 11 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index fdeac1ebf87..57780ef981c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/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/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);  | 

