From: Chris Lattner Date: Thu, 5 Mar 2009 23:01:03 +0000 (+0000) Subject: refactor C++ bitfield checking a bit (haha) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8b963ef99be6235f1e9fe866180fff7dbbe5e85b;p=clang refactor C++ bitfield checking a bit (haha) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66213 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index 579a10fe35..beefc02ef5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -244,10 +244,10 @@ DIAG(err_mutable_nonmember, ERROR, "'mutable' can only be applied to member variables") DIAG(err_virtual_non_function, ERROR, "'virtual' can only appear on non-static member functions") -DIAG(err_not_bitfield_type, ERROR, - "cannot declare %0 to be a bit-field type") DIAG(err_static_not_bitfield, ERROR, "static member %0 cannot be a bit-field") +DIAG(err_typedef_not_bitfield, ERROR, + "typedef member %0 cannot be a bit-field") DIAG(err_not_integral_type_bitfield, ERROR, "bit-field %0 has non-integral type") DIAG(err_member_initialization, ERROR, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f9c1691e85..953e39f92d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3152,12 +3152,14 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) { bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, QualType FieldTy, const Expr *BitWidth) { // C99 6.7.2.1p4 - verify the field type. - + // C++ 9.6p3: A bit-field shall have integral or enumeration type. if (!FieldTy->isIntegralType()) { // Handle incomplete types with specific error. if (FieldTy->isIncompleteType()) - return Diag(FieldLoc, diag::err_field_incomplete) << FieldTy; - return Diag(FieldLoc, diag::err_not_integral_type_bitfield) << FieldName; + return Diag(FieldLoc, diag::err_field_incomplete) + << FieldTy << BitWidth->getSourceRange(); + return Diag(FieldLoc, diag::err_not_integral_type_bitfield) + << FieldName << BitWidth->getSourceRange(); } llvm::APSInt Value; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 0e5adc46a2..178853e5cc 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -545,8 +545,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, !isFunc); Decl *Member; - bool InvalidDecl = false; - if (isInstField) { FieldDecl *FD = HandleField(S, cast(CurContext), Loc, D, BitWidth); @@ -555,6 +553,31 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, Member = FD; } else { Member = static_cast(ActOnDeclarator(S, D, LastInGroup)); + + // Non-instance-fields can't have a bitfield. + if (BitWidth) { + if (Member->isInvalidDecl()) { + // don't emit another diagnostic. + } else if (isa(Member)) { + // C++ 9.6p3: A bit-field shall not be a static member. + // "static member 'A' cannot be a bit-field" + Diag(Loc, diag::err_static_not_bitfield) + << Name << BitWidth->getSourceRange(); + } else if (isa(Member)) { + // "typedef member 'x' cannot be a bit-field" + Diag(Loc, diag::err_typedef_not_bitfield) + << Name << BitWidth->getSourceRange(); + } else { + // A function typedef ("typedef int f(); f a;"). + // C++ 9.6p3: A bit-field shall have integral or enumeration type. + Diag(Loc, diag::err_not_integral_type_bitfield) + << Name << BitWidth->getSourceRange(); + } + + DeleteExpr(BitWidth); + BitWidth = 0; + Member->setInvalidDecl(); + } } if (!Member) return LastInGroup; @@ -579,7 +602,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (DS.isVirtualSpecified()) { if (!isFunc || DS.getStorageClassSpec() == DeclSpec::SCS_static) { Diag(DS.getVirtualSpecLoc(), diag::err_virtual_non_function); - InvalidDecl = true; + Member->setInvalidDecl(); } else { cast(Member)->setVirtual(); CXXRecordDecl *CurClass = cast(CurContext); @@ -593,50 +616,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // also virtual if it overrides an already virtual function. This is important // to do here because it decides the validity of a pure specifier. - if (BitWidth) { - // C++ 9.6p2: Only when declaring an unnamed bit-field may the - // constant-expression be a value equal to zero. - // FIXME: Check this. - - if (D.isFunctionDeclarator()) { - // FIXME: Emit diagnostic about only constructors taking base initializers - // or something similar, when constructor support is in place. - Diag(Loc, diag::err_not_bitfield_type) - << Name << BitWidth->getSourceRange(); - InvalidDecl = true; - - } else if (isInstField) { - // C++ 9.6p3: A bit-field shall have integral or enumeration type. - if (!cast(Member)->getType()->isIntegralType()) { - Diag(Loc, diag::err_not_integral_type_bitfield) - << Name << BitWidth->getSourceRange(); - InvalidDecl = true; - } - - } else if (isa(Member)) { - // A function typedef ("typedef int f(); f a;"). - // C++ 9.6p3: A bit-field shall have integral or enumeration type. - Diag(Loc, diag::err_not_integral_type_bitfield) - << Name << BitWidth->getSourceRange(); - InvalidDecl = true; - - } else if (isa(Member)) { - // "cannot declare 'A' to be a bit-field type" - Diag(Loc, diag::err_not_bitfield_type) - << Name << BitWidth->getSourceRange(); - InvalidDecl = true; - - } else { - assert(isa(Member) && - "Didn't we cover all member kinds?"); - // C++ 9.6p3: A bit-field shall not be a static member. - // "static member 'A' cannot be a bit-field" - Diag(Loc, diag::err_static_not_bitfield) - << Name << BitWidth->getSourceRange(); - InvalidDecl = true; - } - } - if (Init) { // C++ 9.2p4: A member-declarator can contain a constant-initializer only // if it declares a static member of const integral or const enumeration @@ -649,13 +628,13 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, CVD->getType()->isIntegralType()) { // constant-initializer if (CheckForConstantInitializer(Init, CVD->getType())) - InvalidDecl = true; + Member->setInvalidDecl(); } else { // not const integral. Diag(Loc, diag::err_member_initialization) << Name << Init->getSourceRange(); - InvalidDecl = true; + Member->setInvalidDecl(); } } else { @@ -672,24 +651,21 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, else { Diag(Loc, diag::err_non_virtual_pure) << Name << Init->getSourceRange(); - InvalidDecl = true; + Member->setInvalidDecl(); } } else { Diag(Loc, diag::err_member_function_initialization) << Name << Init->getSourceRange(); - InvalidDecl = true; + Member->setInvalidDecl(); } } else { Diag(Loc, diag::err_member_initialization) << Name << Init->getSourceRange(); - InvalidDecl = true; + Member->setInvalidDecl(); } } } - if (InvalidDecl) - Member->setInvalidDecl(); - if (isInstField) { FieldCollector->Add(cast(Member)); return LastInGroup; diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp index 08391c9ba1..44ec70f07c 100644 --- a/test/SemaCXX/class.cpp +++ b/test/SemaCXX/class.cpp @@ -20,7 +20,7 @@ public: int b : 1, w : 2; int : 1, : 2; - typedef int E : 1; // expected-error {{error: cannot declare 'E' to be a bit-field type}} + typedef int E : 1; // expected-error {{typedef member 'E' cannot be a bit-field}} static int sb : 1; // expected-error {{error: static member 'sb' cannot be a bit-field}} static int vs;