diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.def | 2 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 12 | ||||
-rw-r--r-- | clang/test/Sema/bitfield.c | 7 | ||||
-rw-r--r-- | clang/test/SemaCXX/class.cpp | 4 |
6 files changed, 56 insertions, 17 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.def b/clang/include/clang/Basic/DiagnosticSemaKinds.def index 4d711f72133..579a10fe352 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.def +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.def @@ -249,7 +249,7 @@ DIAG(err_not_bitfield_type, ERROR, DIAG(err_static_not_bitfield, ERROR, "static member %0 cannot be a bit-field") DIAG(err_not_integral_type_bitfield, ERROR, - "bit-field %0 with non-integral type") + "bit-field %0 has non-integral type") DIAG(err_member_initialization, ERROR, "%0 can only be initialized if it is a static const integral data member") DIAG(err_member_function_initialization, ERROR, diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index d7d80638d19..92bc0bc750e 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -361,6 +361,10 @@ public: llvm::SmallVectorImpl<DeclTy*> &Decls); virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart, Declarator &D, ExprTy *BitfieldWidth); + + FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart, + Declarator &D, Expr *BitfieldWidth); + virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, ExprTy *BitfieldWidth, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 97002ef02f0..f9c1691e853 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2575,7 +2575,8 @@ void Sema::RecursiveCalcJumpScopes(llvm::DenseMap<Stmt*, void*>& LabelScopeMap, } } if (isa<DeclStmt>(*i)) continue; - RecursiveCalcJumpScopes(LabelScopeMap, PopScopeMap, GotoScopeMap, ScopeStack, *i); + RecursiveCalcJumpScopes(LabelScopeMap, PopScopeMap, GotoScopeMap, + ScopeStack, *i); } while (ScopeStack.size() && PopScopeMap[ScopeStack.back()] == CurStmt) { @@ -3150,7 +3151,14 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) { bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, QualType FieldTy, const Expr *BitWidth) { - // FIXME: 6.7.2.1p4 - verify the field type. + // C99 6.7.2.1p4 - verify the field 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; + } llvm::APSInt Value; if (VerifyIntegerConstantExpression(BitWidth, &Value)) @@ -3177,15 +3185,19 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart, Declarator &D, ExprTy *BitfieldWidth) { + return HandleField(S, static_cast<RecordDecl*>(TagD), DeclStart, D, + static_cast<Expr*>(BitfieldWidth)); +} + +/// HandleField - Analyze a field of a C struct or a C++ data member. +/// +FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, + SourceLocation DeclStart, + Declarator &D, Expr *BitWidth) { IdentifierInfo *II = D.getIdentifier(); - Expr *BitWidth = (Expr*)BitfieldWidth; SourceLocation Loc = DeclStart; - RecordDecl *Record = (RecordDecl *)TagD; if (II) Loc = D.getIdentifierLoc(); - // FIXME: Unnamed fields can be handled in various different ways, for - // example, unnamed unions inject all members into the struct namespace! - QualType T = GetTypeForDeclarator(D, S); assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); bool InvalidDecl = false; @@ -3210,8 +3222,11 @@ Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD, } if (BitWidth) { - if (VerifyBitField(Loc, II, T, BitWidth)) + if (VerifyBitField(Loc, II, T, BitWidth)) { InvalidDecl = true; + DeleteExpr(BitWidth); + BitWidth = 0; + } } else { // Not a bitfield. @@ -3290,8 +3305,11 @@ Sema::DeclTy *Sema::ActOnIvar(Scope *S, if (BitWidth) { // 6.7.2.1p3, 6.7.2.1p4 - if (VerifyBitField(Loc, II, T, BitWidth)) + if (VerifyBitField(Loc, II, T, BitWidth)) { InvalidDecl = true; + DeleteExpr(BitWidth); + BitWidth = 0; + } } else { // Not a bitfield. @@ -3373,6 +3391,11 @@ void Sema::ActOnFields(Scope* S, // Remember all fields written by the user. RecFields.push_back(FD); } + + // If the field is already invalid for some reason, don't emit more + // diagnostics about it. + if (FD->isInvalidDecl()) + continue; // C99 6.7.2.1p2 - A field may not be a function type. if (FDTy->isFunctionType()) { @@ -3466,7 +3489,8 @@ void Sema::ActOnFields(Scope* S, IVE = ID->ivar_end(); IVI != IVE; ++IVI) { ObjCIvarDecl* Ivar = (*IVI); IdentifierInfo *II = Ivar->getIdentifier(); - ObjCIvarDecl* prevIvar = ID->getSuperClass()->lookupInstanceVariable(II); + ObjCIvarDecl* prevIvar = + ID->getSuperClass()->lookupInstanceVariable(II); if (prevIvar) { Diag(Ivar->getLocation(), diag::err_duplicate_member) << II; Diag(prevIvar->getLocation(), diag::note_previous_declaration); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 3e8ee5ed1f7..0e5adc46a2d 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -547,11 +547,15 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, Decl *Member; bool InvalidDecl = false; - if (isInstField) - Member = static_cast<Decl*>(ActOnField(S, cast<CXXRecordDecl>(CurContext), - Loc, D, BitWidth)); - else + if (isInstField) { + FieldDecl *FD = + HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth); + // Refresh our notion of bitwidth. + BitWidth = FD->getBitWidth(); + Member = FD; + } else { Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup)); + } if (!Member) return LastInGroup; diff --git a/clang/test/Sema/bitfield.c b/clang/test/Sema/bitfield.c index f3b285b12ed..2e4df476503 100644 --- a/clang/test/Sema/bitfield.c +++ b/clang/test/Sema/bitfield.c @@ -1,4 +1,5 @@ // RUN: clang %s -fsyntax-only -verify +enum e0; struct a { int a : -1; // expected-error{{bit-field 'a' has negative width}} @@ -11,4 +12,10 @@ struct a { // rdar://6138816 int e : 0; // expected-error {{bit-field 'e' has zero width}} + + float xx : 4; // expected-error {{bit-field 'xx' has non-integral type}} + + // PR3607 + enum e0 f : 1; // expected-error {{field has incomplete type 'enum e0'}} }; + diff --git a/clang/test/SemaCXX/class.cpp b/clang/test/SemaCXX/class.cpp index 02608faa0f6..08391c9ba1a 100644 --- a/clang/test/SemaCXX/class.cpp +++ b/clang/test/SemaCXX/class.cpp @@ -27,8 +27,8 @@ public: typedef int func(); func tm; func *ptm; - func btm : 1; // expected-error {{error: bit-field 'btm' with non-integral type}} - NestedC bc : 1; // expected-error {{error: bit-field 'bc' with non-integral type}} + func btm : 1; // expected-error {{error: bit-field 'btm' has non-integral type}} + NestedC bc : 1; // expected-error {{error: bit-field 'bc' has non-integral type}} enum E1 { en1, en2 }; |