Submitted by:
Reviewed by:
- ParseMemberReferenceExpr wasn't operating on the canonical type. From
now on, I will make sure the prologue to each Parse/Check function has
both the qualified type and the canonical type.
- More refinements to ParseDeclarator. It was allowing variable declarations
to incomplete types (e.g. void, struct foo, where foo wasn't defined).

llvm-svn: 39371
This commit is contained in:
Steve Naroff 2007-04-01 01:41:35 +00:00
parent 95af013c77
commit ca8f71287f
5 changed files with 64 additions and 32 deletions

View File

@ -260,17 +260,28 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
TypeRef R = GetTypeForDeclarator(D, S);
if (R.isNull()) return 0;
ObjectDecl::StorageClass S;
ObjectDecl::StorageClass SC;
switch (D.getDeclSpec().getStorageClassSpec()) {
default: assert(0 && "Unknown storage class!");
case 0: S = ObjectDecl::None;
case DeclSpec::SCS_extern: S = ObjectDecl::Extern; break;
case DeclSpec::SCS_static: S = ObjectDecl::Static; break;
case DeclSpec::SCS_unspecified: SC = ObjectDecl::None; break;
case DeclSpec::SCS_extern: SC = ObjectDecl::Extern; break;
case DeclSpec::SCS_static: SC = ObjectDecl::Static; break;
// The following 2 should never be seen in this context.
case DeclSpec::SCS_auto: S = ObjectDecl::Auto; break;
case DeclSpec::SCS_register: S = ObjectDecl::Register; break;
case DeclSpec::SCS_auto: SC = ObjectDecl::Auto; break;
case DeclSpec::SCS_register: SC = ObjectDecl::Register; break;
}
VarDecl *NewVD = new VarDecl(D.getIdentifierLoc(), II, R, S);
// C99 6.9.2p3: If the declaration of an identifier for an object is a
// tentative definition and has internal linkage, the declared type shall
// not be an incomplete type.
if ((S->getParent() == 0 && !Init && SC == ObjectDecl::None) ||
SC == ObjectDecl::Static) {
// FIXME: need a check for internal linkage.
if (R->isIncompleteType()) {
Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type, R);
return 0;
}
}
VarDecl *NewVD = new VarDecl(D.getIdentifierLoc(), II, R, SC);
// Merge the decl with the existing one if appropriate.
if (PrevDecl) {

View File

@ -266,20 +266,24 @@ Action::ExprResult Sema::
ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
tok::TokenKind OpKind, SourceLocation MemberLoc,
IdentifierInfo &Member) {
TypeRef BT = ((Expr *)Base)->getTypeRef();
assert(!BT.isNull() && "no type for member expression");
TypeRef qualifiedType = ((Expr *)Base)->getTypeRef();
assert(!qualifiedType.isNull() && "no type for member expression");
Type *canonType = qualifiedType->getCanonicalType();
if (OpKind == tok::arrow) {
if (PointerType *PT = dyn_cast<PointerType>(BT))
BT = PT->getPointeeType();
else
if (PointerType *PT = dyn_cast<PointerType>(canonType)) {
qualifiedType = PT->getPointeeType();
canonType = qualifiedType->getCanonicalType();
} else
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow);
}
if (isa<RecordType>(BT)) { // get the struct/union definition from the type.
RecordDecl *RD = cast<RecordType>(BT)->getDecl();
if (isa<RecordType>(canonType)) {
// get the struct/union definition from the type.
RecordDecl *RD = cast<RecordType>(canonType)->getDecl();
if (BT->isIncompleteType())
if (canonType->isIncompleteType())
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RD->getName());
if (FieldDecl *MemberDecl = RD->getMember(&Member))

View File

@ -260,17 +260,28 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
TypeRef R = GetTypeForDeclarator(D, S);
if (R.isNull()) return 0;
ObjectDecl::StorageClass S;
ObjectDecl::StorageClass SC;
switch (D.getDeclSpec().getStorageClassSpec()) {
default: assert(0 && "Unknown storage class!");
case 0: S = ObjectDecl::None;
case DeclSpec::SCS_extern: S = ObjectDecl::Extern; break;
case DeclSpec::SCS_static: S = ObjectDecl::Static; break;
case DeclSpec::SCS_unspecified: SC = ObjectDecl::None; break;
case DeclSpec::SCS_extern: SC = ObjectDecl::Extern; break;
case DeclSpec::SCS_static: SC = ObjectDecl::Static; break;
// The following 2 should never be seen in this context.
case DeclSpec::SCS_auto: S = ObjectDecl::Auto; break;
case DeclSpec::SCS_register: S = ObjectDecl::Register; break;
case DeclSpec::SCS_auto: SC = ObjectDecl::Auto; break;
case DeclSpec::SCS_register: SC = ObjectDecl::Register; break;
}
VarDecl *NewVD = new VarDecl(D.getIdentifierLoc(), II, R, S);
// C99 6.9.2p3: If the declaration of an identifier for an object is a
// tentative definition and has internal linkage, the declared type shall
// not be an incomplete type.
if ((S->getParent() == 0 && !Init && SC == ObjectDecl::None) ||
SC == ObjectDecl::Static) {
// FIXME: need a check for internal linkage.
if (R->isIncompleteType()) {
Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type, R);
return 0;
}
}
VarDecl *NewVD = new VarDecl(D.getIdentifierLoc(), II, R, SC);
// Merge the decl with the existing one if appropriate.
if (PrevDecl) {

View File

@ -266,20 +266,24 @@ Action::ExprResult Sema::
ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
tok::TokenKind OpKind, SourceLocation MemberLoc,
IdentifierInfo &Member) {
TypeRef BT = ((Expr *)Base)->getTypeRef();
assert(!BT.isNull() && "no type for member expression");
TypeRef qualifiedType = ((Expr *)Base)->getTypeRef();
assert(!qualifiedType.isNull() && "no type for member expression");
Type *canonType = qualifiedType->getCanonicalType();
if (OpKind == tok::arrow) {
if (PointerType *PT = dyn_cast<PointerType>(BT))
BT = PT->getPointeeType();
else
if (PointerType *PT = dyn_cast<PointerType>(canonType)) {
qualifiedType = PT->getPointeeType();
canonType = qualifiedType->getCanonicalType();
} else
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow);
}
if (isa<RecordType>(BT)) { // get the struct/union definition from the type.
RecordDecl *RD = cast<RecordType>(BT)->getDecl();
if (isa<RecordType>(canonType)) {
// get the struct/union definition from the type.
RecordDecl *RD = cast<RecordType>(canonType)->getDecl();
if (BT->isIncompleteType())
if (canonType->isIncompleteType())
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RD->getName());
if (FieldDecl *MemberDecl = RD->getMember(&Member))

View File

@ -504,6 +504,8 @@ DIAG(err_typecheck_not_modifiable, ERROR,
"cannot modify read-only value of type '%s'")
DIAG(err_typecheck_arithmetic_incomplete_type, ERROR,
"arithmetic on pointer to incomplete type '%s'")
DIAG(err_typecheck_decl_incomplete_type, ERROR,
"variable has incomplete type '%s'")
// Statements.
DIAG(err_continue_not_in_loop, ERROR,