forked from OSchip/llvm-project
fix PR3607 and a fixme, by checking bitfield constraints
more consistently. llvm-svn: 66210
This commit is contained in:
parent
c559f3f175
commit
73bf7b42b6
|
@ -249,7 +249,7 @@ DIAG(err_not_bitfield_type, ERROR,
|
||||||
DIAG(err_static_not_bitfield, ERROR,
|
DIAG(err_static_not_bitfield, ERROR,
|
||||||
"static member %0 cannot be a bit-field")
|
"static member %0 cannot be a bit-field")
|
||||||
DIAG(err_not_integral_type_bitfield, ERROR,
|
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,
|
DIAG(err_member_initialization, ERROR,
|
||||||
"%0 can only be initialized if it is a static const integral data member")
|
"%0 can only be initialized if it is a static const integral data member")
|
||||||
DIAG(err_member_function_initialization, ERROR,
|
DIAG(err_member_function_initialization, ERROR,
|
||||||
|
|
|
@ -361,6 +361,10 @@ public:
|
||||||
llvm::SmallVectorImpl<DeclTy*> &Decls);
|
llvm::SmallVectorImpl<DeclTy*> &Decls);
|
||||||
virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
|
virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
|
||||||
Declarator &D, ExprTy *BitfieldWidth);
|
Declarator &D, ExprTy *BitfieldWidth);
|
||||||
|
|
||||||
|
FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
|
||||||
|
Declarator &D, Expr *BitfieldWidth);
|
||||||
|
|
||||||
|
|
||||||
virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart,
|
virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart,
|
||||||
Declarator &D, ExprTy *BitfieldWidth,
|
Declarator &D, ExprTy *BitfieldWidth,
|
||||||
|
|
|
@ -2575,7 +2575,8 @@ void Sema::RecursiveCalcJumpScopes(llvm::DenseMap<Stmt*, void*>& LabelScopeMap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isa<DeclStmt>(*i)) continue;
|
if (isa<DeclStmt>(*i)) continue;
|
||||||
RecursiveCalcJumpScopes(LabelScopeMap, PopScopeMap, GotoScopeMap, ScopeStack, *i);
|
RecursiveCalcJumpScopes(LabelScopeMap, PopScopeMap, GotoScopeMap,
|
||||||
|
ScopeStack, *i);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ScopeStack.size() && PopScopeMap[ScopeStack.back()] == CurStmt) {
|
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,
|
bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
|
||||||
QualType FieldTy, const Expr *BitWidth) {
|
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;
|
llvm::APSInt Value;
|
||||||
if (VerifyIntegerConstantExpression(BitWidth, &Value))
|
if (VerifyIntegerConstantExpression(BitWidth, &Value))
|
||||||
|
@ -3177,15 +3185,19 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
|
||||||
Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
|
Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
|
||||||
SourceLocation DeclStart,
|
SourceLocation DeclStart,
|
||||||
Declarator &D, ExprTy *BitfieldWidth) {
|
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();
|
IdentifierInfo *II = D.getIdentifier();
|
||||||
Expr *BitWidth = (Expr*)BitfieldWidth;
|
|
||||||
SourceLocation Loc = DeclStart;
|
SourceLocation Loc = DeclStart;
|
||||||
RecordDecl *Record = (RecordDecl *)TagD;
|
|
||||||
if (II) Loc = D.getIdentifierLoc();
|
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);
|
QualType T = GetTypeForDeclarator(D, S);
|
||||||
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
|
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
|
||||||
bool InvalidDecl = false;
|
bool InvalidDecl = false;
|
||||||
|
@ -3210,8 +3222,11 @@ Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BitWidth) {
|
if (BitWidth) {
|
||||||
if (VerifyBitField(Loc, II, T, BitWidth))
|
if (VerifyBitField(Loc, II, T, BitWidth)) {
|
||||||
InvalidDecl = true;
|
InvalidDecl = true;
|
||||||
|
DeleteExpr(BitWidth);
|
||||||
|
BitWidth = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not a bitfield.
|
// Not a bitfield.
|
||||||
|
|
||||||
|
@ -3290,8 +3305,11 @@ Sema::DeclTy *Sema::ActOnIvar(Scope *S,
|
||||||
|
|
||||||
if (BitWidth) {
|
if (BitWidth) {
|
||||||
// 6.7.2.1p3, 6.7.2.1p4
|
// 6.7.2.1p3, 6.7.2.1p4
|
||||||
if (VerifyBitField(Loc, II, T, BitWidth))
|
if (VerifyBitField(Loc, II, T, BitWidth)) {
|
||||||
InvalidDecl = true;
|
InvalidDecl = true;
|
||||||
|
DeleteExpr(BitWidth);
|
||||||
|
BitWidth = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not a bitfield.
|
// Not a bitfield.
|
||||||
|
|
||||||
|
@ -3373,6 +3391,11 @@ void Sema::ActOnFields(Scope* S,
|
||||||
// Remember all fields written by the user.
|
// Remember all fields written by the user.
|
||||||
RecFields.push_back(FD);
|
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.
|
// C99 6.7.2.1p2 - A field may not be a function type.
|
||||||
if (FDTy->isFunctionType()) {
|
if (FDTy->isFunctionType()) {
|
||||||
|
@ -3466,7 +3489,8 @@ void Sema::ActOnFields(Scope* S,
|
||||||
IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
|
IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
|
||||||
ObjCIvarDecl* Ivar = (*IVI);
|
ObjCIvarDecl* Ivar = (*IVI);
|
||||||
IdentifierInfo *II = Ivar->getIdentifier();
|
IdentifierInfo *II = Ivar->getIdentifier();
|
||||||
ObjCIvarDecl* prevIvar = ID->getSuperClass()->lookupInstanceVariable(II);
|
ObjCIvarDecl* prevIvar =
|
||||||
|
ID->getSuperClass()->lookupInstanceVariable(II);
|
||||||
if (prevIvar) {
|
if (prevIvar) {
|
||||||
Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;
|
Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;
|
||||||
Diag(prevIvar->getLocation(), diag::note_previous_declaration);
|
Diag(prevIvar->getLocation(), diag::note_previous_declaration);
|
||||||
|
|
|
@ -547,11 +547,15 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
||||||
Decl *Member;
|
Decl *Member;
|
||||||
bool InvalidDecl = false;
|
bool InvalidDecl = false;
|
||||||
|
|
||||||
if (isInstField)
|
if (isInstField) {
|
||||||
Member = static_cast<Decl*>(ActOnField(S, cast<CXXRecordDecl>(CurContext),
|
FieldDecl *FD =
|
||||||
Loc, D, BitWidth));
|
HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth);
|
||||||
else
|
// Refresh our notion of bitwidth.
|
||||||
|
BitWidth = FD->getBitWidth();
|
||||||
|
Member = FD;
|
||||||
|
} else {
|
||||||
Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup));
|
Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup));
|
||||||
|
}
|
||||||
|
|
||||||
if (!Member) return LastInGroup;
|
if (!Member) return LastInGroup;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// RUN: clang %s -fsyntax-only -verify
|
// RUN: clang %s -fsyntax-only -verify
|
||||||
|
enum e0;
|
||||||
|
|
||||||
struct a {
|
struct a {
|
||||||
int a : -1; // expected-error{{bit-field 'a' has negative width}}
|
int a : -1; // expected-error{{bit-field 'a' has negative width}}
|
||||||
|
@ -11,4 +12,10 @@ struct a {
|
||||||
|
|
||||||
// rdar://6138816
|
// rdar://6138816
|
||||||
int e : 0; // expected-error {{bit-field 'e' has zero width}}
|
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'}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ public:
|
||||||
typedef int func();
|
typedef int func();
|
||||||
func tm;
|
func tm;
|
||||||
func *ptm;
|
func *ptm;
|
||||||
func btm : 1; // expected-error {{error: bit-field 'btm' 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' with non-integral type}}
|
NestedC bc : 1; // expected-error {{error: bit-field 'bc' has non-integral type}}
|
||||||
|
|
||||||
enum E1 { en1, en2 };
|
enum E1 { en1, en2 };
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue