From: Douglas Gregor Date: Tue, 28 Sep 2010 00:00:00 +0000 (+0000) Subject: Centralize the management of CXXRecordDecl::DefinitionData's X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e10288c1e9e06dbd715f47bfaa22ce5d65fdf096;p=clang Centralize the management of CXXRecordDecl::DefinitionData's HasTrivialConstructor, HasTrivialCopyConstructor, HasTrivialCopyAssignment, and HasTrivialDestructor bits in CXXRecordDecl's methods. This completes all but the Abstract bit and the set of conversion functions, both of which will require a bit of extra work. The majority of is now implemented (but not all of it). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114929 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 53bd720c97..786393cc31 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -688,10 +688,6 @@ public: /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1). bool isAggregate() const { return data().Aggregate; } - /// setMethodAsVirtual - Make input method virtual and set the necesssary - /// special function bits and other bits accordingly. - void setMethodAsVirtual(FunctionDecl *Method); - /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class /// that is an aggregate that has no non-static non-POD data members, no /// reference data members, no user-defined copy assignment operator and no @@ -719,42 +715,22 @@ public: // (C++ [class.ctor]p5) bool hasTrivialConstructor() const { return data().HasTrivialConstructor; } - // setHasTrivialConstructor - Set whether this class has a trivial constructor - // (C++ [class.ctor]p5) - void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; } - // hasTrivialCopyConstructor - Whether this class has a trivial copy // constructor (C++ [class.copy]p6) bool hasTrivialCopyConstructor() const { return data().HasTrivialCopyConstructor; } - // setHasTrivialCopyConstructor - Set whether this class has a trivial - // copy constructor (C++ [class.copy]p6) - void setHasTrivialCopyConstructor(bool TC) { - data().HasTrivialCopyConstructor = TC; - } - // hasTrivialCopyAssignment - Whether this class has a trivial copy // assignment operator (C++ [class.copy]p11) bool hasTrivialCopyAssignment() const { return data().HasTrivialCopyAssignment; } - // setHasTrivialCopyAssignment - Set whether this class has a - // trivial copy assignment operator (C++ [class.copy]p11) - void setHasTrivialCopyAssignment(bool TC) { - data().HasTrivialCopyAssignment = TC; - } - // hasTrivialDestructor - Whether this class has a trivial destructor // (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } - // setHasTrivialDestructor - Set whether this class has a trivial destructor - // (C++ [class.dtor]p3) - void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; } - /// \brief If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5d8ead37dc..5445c1b755 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2584,13 +2584,6 @@ public: bool Virtual, AccessSpecifier Access, TypeSourceInfo *TInfo); - /// SetClassDeclAttributesFromBase - Copies class decl traits - /// (such as whether the class has a trivial constructor, - /// trivial destructor etc) from the given base class. - void SetClassDeclAttributesFromBase(CXXRecordDecl *Class, - const CXXRecordDecl *BaseClass, - bool BaseIsVirtual); - BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 151d333afc..3e6d8b379f 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -134,7 +134,45 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // T is a class type, but not a union type, with ... no virtual base // classes data().Empty = false; + + // C++ [class.ctor]p5: + // A constructor is trivial if its class has no virtual base classes. + data().HasTrivialConstructor = false; + + // C++ [class.copy]p6: + // A copy constructor is trivial if its class has no virtual base + // classes. + data().HasTrivialCopyConstructor = false; + + // C++ [class.copy]p11: + // A copy assignment operator is trivial if its class has no virtual + // base classes. + data().HasTrivialCopyAssignment = false; + } else { + // C++ [class.ctor]p5: + // A constructor is trivial if all the direct base classes of its + // class have trivial constructors. + if (!BaseClassDecl->hasTrivialConstructor()) + data().HasTrivialConstructor = false; + + // C++ [class.copy]p6: + // A copy constructor is trivial if all the direct base classes of its + // class have trivial copy constructors. + if (!BaseClassDecl->hasTrivialCopyConstructor()) + data().HasTrivialCopyConstructor = false; + + // C++ [class.copy]p11: + // A copy assignment operator is trivial if all the direct base classes + // of its class have trivial copy assignment operators. + if (!BaseClassDecl->hasTrivialCopyAssignment()) + data().HasTrivialCopyAssignment = false; } + + // C++ [class.ctor]p3: + // A destructor is trivial if all the direct base classes of its class + // have trivial destructors. + if (!BaseClassDecl->hasTrivialDestructor()) + data().HasTrivialDestructor = false; } if (VBases.empty()) @@ -309,6 +347,12 @@ CXXRecordDecl::addedMember(Decl *D) { // A class that declares or inherits a virtual function is called a // polymorphic class. data().Polymorphic = true; + + // None of the special member functions are trivial. + data().HasTrivialConstructor = false; + data().HasTrivialCopyConstructor = false; + data().HasTrivialCopyAssignment = false; + // FIXME: Destructor? } } @@ -384,6 +428,13 @@ CXXRecordDecl::addedMember(Decl *D) { // destructor. data().PlainOldData = false; + // C++ [class.dtor]p3: + // A destructor is trivial if it is an implicitly-declared destructor and + // [...]. + // + // FIXME: C++0x: don't do this for "= default" destructors + data().HasTrivialDestructor = false; + return; } @@ -453,6 +504,22 @@ CXXRecordDecl::addedMember(Decl *D) { QualType T = Context.getBaseElementType(Field->getType()); if (!T->isPODType()) data().PlainOldData = false; + if (T->isReferenceType()) + data().HasTrivialConstructor = false; + + if (const RecordType *RecordTy = T->getAs()) { + CXXRecordDecl* FieldRec = cast(RecordTy->getDecl()); + if (FieldRec->getDefinition()) { + if (!FieldRec->hasTrivialConstructor()) + data().HasTrivialConstructor = false; + if (!FieldRec->hasTrivialCopyConstructor()) + data().HasTrivialCopyConstructor = false; + if (!FieldRec->hasTrivialCopyAssignment()) + data().HasTrivialCopyAssignment = false; + if (!FieldRec->hasTrivialDestructor()) + data().HasTrivialDestructor = false; + } + } // If this is not a zero-length bit-field, then the class is not empty. if (data().Empty) { @@ -649,13 +716,6 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { llvm_unreachable("conversion not found in set!"); } -void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) { - Method->setVirtualAsWritten(true); - setHasTrivialConstructor(false); - setHasTrivialCopyConstructor(false); - setHasTrivialCopyAssignment(false); -} - CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) return cast(MSInfo->getInstantiatedFrom()); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e6e4420f23..c189bce8eb 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3425,8 +3425,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc()); } else { // Okay: Add virtual to the method. - CXXRecordDecl *CurClass = cast(DC); - CurClass->setMethodAsVirtual(NewFD); + NewFD->setVirtualAsWritten(true); } } @@ -3927,11 +3926,6 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, return NewFD->setInvalidDecl(); } } - - // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly- - // declared destructor. - // FIXME: C++0x: don't do this for "= default" destructors - Record->setHasTrivialDestructor(false); } else if (CXXConversionDecl *Conversion = dyn_cast(NewFD)) { ActOnConversionDeclarator(Conversion); @@ -6185,23 +6179,9 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } if (!InvalidDecl && getLangOptions().CPlusPlus) { - CXXRecordDecl* CXXRecord = cast(Record); - - if (T->isReferenceType()) - CXXRecord->setHasTrivialConstructor(false); - if (const RecordType *RT = EltTy->getAs()) { CXXRecordDecl* RDecl = cast(RT->getDecl()); if (RDecl->getDefinition()) { - if (!RDecl->hasTrivialConstructor()) - CXXRecord->setHasTrivialConstructor(false); - if (!RDecl->hasTrivialCopyConstructor()) - CXXRecord->setHasTrivialCopyConstructor(false); - if (!RDecl->hasTrivialCopyAssignment()) - CXXRecord->setHasTrivialCopyAssignment(false); - if (!RDecl->hasTrivialDestructor()) - CXXRecord->setHasTrivialDestructor(false); - // C++ 9.5p1: An object of a class with a non-trivial // constructor, a non-trivial copy constructor, a non-trivial // destructor, or a non-trivial copy assignment operator diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index ebf467fe7a..63acb095a6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -502,8 +502,6 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, return 0; } - SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual); - if (BaseDecl->isInvalidDecl()) Class->setInvalidDecl(); @@ -513,49 +511,6 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access, TInfo); } -void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class, - const CXXRecordDecl *BaseClass, - bool BaseIsVirtual) { - if (BaseIsVirtual) { - // C++ [class.ctor]p5: - // A constructor is trivial if its class has no virtual base classes. - Class->setHasTrivialConstructor(false); - - // C++ [class.copy]p6: - // A copy constructor is trivial if its class has no virtual base classes. - Class->setHasTrivialCopyConstructor(false); - - // C++ [class.copy]p11: - // A copy assignment operator is trivial if its class has no virtual - // base classes. - Class->setHasTrivialCopyAssignment(false); - } else { - // C++ [class.ctor]p5: - // A constructor is trivial if all the direct base classes of its - // class have trivial constructors. - if (!BaseClass->hasTrivialConstructor()) - Class->setHasTrivialConstructor(false); - - // C++ [class.copy]p6: - // A copy constructor is trivial if all the direct base classes of its - // class have trivial copy constructors. - if (!BaseClass->hasTrivialCopyConstructor()) - Class->setHasTrivialCopyConstructor(false); - - // C++ [class.copy]p11: - // A copy assignment operator is trivial if all the direct base classes - // of its class have trivial copy assignment operators. - if (!BaseClass->hasTrivialCopyAssignment()) - Class->setHasTrivialCopyAssignment(false); - } - - // C++ [class.ctor]p3: - // A destructor is trivial if all the direct base classes of its class - // have trivial destructors. - if (!BaseClass->hasTrivialDestructor()) - Class->setHasTrivialDestructor(false); -} - /// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is /// one entry in the base class list of a class specifier, for /// example: diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 5520f64044..a2c3df653b 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1091,13 +1091,6 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end(); Base != BaseEnd; ++Base) { if (!Base->getType()->isDependentType()) { - const CXXRecordDecl *BaseDecl = - cast(Base->getType()->getAs()->getDecl()); - - // Make sure to set the attributes from the base. - SetClassDeclAttributesFromBase(Instantiation, BaseDecl, - Base->isVirtual()); - InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base)); continue; } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index f9ff20463a..d87629151e 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1996,10 +1996,9 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, if (InitFunctionInstantiation(New, Tmpl)) return true; - CXXRecordDecl *Record = cast(Owner); New->setAccess(Tmpl->getAccess()); if (Tmpl->isVirtualAsWritten()) - Record->setMethodAsVirtual(New); + New->setVirtualAsWritten(true); // FIXME: attributes // FIXME: New needs a pointer to Tmpl