diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 1 |
6 files changed, 46 insertions, 13 deletions
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 454dc14b6c8..006f69890ab 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -223,6 +223,12 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const { if (const RecordType *RT = QueriedType->getAs<RecordType>()) return cast<CXXRecordDecl>(RT->getDecl())->isAbstract(); return false; + case UTT_IsEmpty: + if (const RecordType *Record = QueriedType->getAs<RecordType>()) { + return !Record->getDecl()->isUnion() + && cast<CXXRecordDecl>(Record->getDecl())->isEmpty(); + } + return false; case UTT_HasTrivialConstructor: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: // If __is_pod (type) is true then the trait is true, else if type is diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 6e7deef95dc..57604a8dc9f 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -815,6 +815,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___is_class: case tok::kw___is_enum: case tok::kw___is_union: + case tok::kw___is_empty: case tok::kw___is_polymorphic: case tok::kw___is_abstract: case tok::kw___has_trivial_constructor: diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index ddd6d7b5712..98fa698a8df 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -3324,8 +3324,10 @@ public: /// VerifyBitField - verifies that a bit field expression is an ICE and has /// the correct width, and that the field type is valid. /// Returns false on success. + /// Can optionally return whether the bit-field is of width 0 bool VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, const Expr *BitWidth); + QualType FieldTy, const Expr *BitWidth, + bool *ZeroWidth = 0); //===--------------------------------------------------------------------===// // Extra semantic analysis beyond the C type system diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index d75f322aa55..bf1dd91f74b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2536,6 +2536,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, CXXRecordDecl *CurClass = cast<CXXRecordDecl>(DC); CurClass->setAggregate(false); CurClass->setPOD(false); + CurClass->setEmpty(false); CurClass->setPolymorphic(true); CurClass->setHasTrivialConstructor(false); CurClass->setHasTrivialCopyConstructor(false); @@ -4331,8 +4332,12 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, // Note that FieldName may be null for anonymous bitfields. bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, const Expr *BitWidth) { - + QualType FieldTy, const Expr *BitWidth, + bool *ZeroWidth) { + // Default to true; that shouldn't confuse checks for emptiness + if (ZeroWidth) + *ZeroWidth = true; + // C99 6.7.2.1p4 - verify the field type. // C++ 9.6p3: A bit-field shall have integral or enumeration type. if (!FieldTy->isDependentType() && !FieldTy->isIntegralType()) { @@ -4355,6 +4360,9 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, if (VerifyIntegerConstantExpression(BitWidth, &Value)) return true; + if (Value != 0 && ZeroWidth) + *ZeroWidth = false; + // Zero-width bitfield is ok for anonymous field. if (Value == 0 && FieldName) return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName; @@ -4490,11 +4498,13 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, AbstractFieldType)) InvalidDecl = true; + bool ZeroWidth = false; // If this is declared as a bit-field, check the bit-field. - if (BitWidth && VerifyBitField(Loc, II, T, BitWidth)) { + if (BitWidth && VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) { InvalidDecl = true; DeleteExpr(BitWidth); BitWidth = 0; + ZeroWidth = false; } FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, BitWidth, @@ -4511,17 +4521,24 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (getLangOptions().CPlusPlus) { QualType EltTy = Context.getBaseElementType(T); + CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record); + + if (!T->isPODType()) + CXXRecord->setPOD(false); + if (!ZeroWidth) + CXXRecord->setEmpty(false); + if (const RecordType *RT = EltTy->getAs<RecordType>()) { CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl()); if (!RDecl->hasTrivialConstructor()) - cast<CXXRecordDecl>(Record)->setHasTrivialConstructor(false); + CXXRecord->setHasTrivialConstructor(false); if (!RDecl->hasTrivialCopyConstructor()) - cast<CXXRecordDecl>(Record)->setHasTrivialCopyConstructor(false); + CXXRecord->setHasTrivialCopyConstructor(false); if (!RDecl->hasTrivialCopyAssignment()) - cast<CXXRecordDecl>(Record)->setHasTrivialCopyAssignment(false); + CXXRecord->setHasTrivialCopyAssignment(false); if (!RDecl->hasTrivialDestructor()) - cast<CXXRecordDecl>(Record)->setHasTrivialDestructor(false); + CXXRecord->setHasTrivialDestructor(false); // C++ 9.5p1: An object of a class with a non-trivial // constructor, a non-trivial copy constructor, a non-trivial @@ -4557,9 +4574,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } } - if (getLangOptions().CPlusPlus && !T->isPODType()) - cast<CXXRecordDecl>(Record)->setPOD(false); - // FIXME: We need to pass in the attributes given an AST // representation, not a parser representation. if (D) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index a8afa4f1de2..889d5c91caa 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -383,12 +383,16 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, SpecifierRange)) return 0; - // If the base class is polymorphic, the new one is, too. + // If the base class is polymorphic or isn't empty, the new one is/isn't, too. RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl(); assert(BaseDecl && "Record type has no declaration"); BaseDecl = BaseDecl->getDefinition(Context); assert(BaseDecl && "Base type is not incomplete, but has no definition"); - if (cast<CXXRecordDecl>(BaseDecl)->isPolymorphic()) + CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl); + assert(CXXBaseDecl && "Base type is not a C++ type"); + if (!CXXBaseDecl->isEmpty()) + Class->setEmpty(false); + if (CXXBaseDecl->isPolymorphic()) Class->setPolymorphic(true); // C++ [dcl.init.aggr]p1: @@ -409,6 +413,11 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // 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 diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 32129231945..b216ec18bfc 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -749,6 +749,7 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, New->setVirtualAsWritten(true); Record->setAggregate(false); Record->setPOD(false); + Record->setEmpty(false); Record->setPolymorphic(true); } if (Tmpl->isPure()) { |