forked from OSchip/llvm-project
Refactor Objective-C @catch parameter checking by detangling it from
function-parameter checking and splitting it into the normal ActOn*/Build* pair in Sema. We now use VarDecl to represent the @catch parameter rather than the ill-fitting ParmVarDecl. llvm-svn: 102347
This commit is contained in:
parent
46a572b871
commit
f356419bf5
|
@ -2083,6 +2083,15 @@ def err_catch_param_not_objc_type : Error<
|
|||
"@catch parameter is not a pointer to an interface type">;
|
||||
def err_illegal_qualifiers_on_catch_parm : Error<
|
||||
"illegal qualifiers on @catch parameter">;
|
||||
def err_storage_spec_on_catch_parm : Error<
|
||||
"@catch parameter cannot have storage specifier %select{|'typedef'|'extern'|"
|
||||
"'static'|'auto'|'register'|'__private_extern__'|'mutable'}0">;
|
||||
def warn_register_objc_catch_parm : Warning<
|
||||
"'register' storage specifier on @catch parameter will be ignored">;
|
||||
def err_qualified_objc_catch_parm : Error<
|
||||
"@catch parameter declarator cannot be qualified">;
|
||||
|
||||
|
||||
def warn_setter_getter_impl_required : Warning<
|
||||
"property %0 requires method %1 to be defined - "
|
||||
"use @synthesize, @dynamic or provide a method implementation">;
|
||||
|
|
|
@ -82,8 +82,9 @@ public:
|
|||
class DeclSpec {
|
||||
public:
|
||||
// storage-class-specifier
|
||||
// Note: The order of these enumerators is important for diagnostics.
|
||||
enum SCS {
|
||||
SCS_unspecified,
|
||||
SCS_unspecified = 0,
|
||||
SCS_typedef,
|
||||
SCS_extern,
|
||||
SCS_static,
|
||||
|
|
|
@ -812,7 +812,6 @@ public:
|
|||
SourceLocation NameLoc,
|
||||
VarDecl::StorageClass StorageClass,
|
||||
VarDecl::StorageClass StorageClassAsWritten);
|
||||
virtual DeclPtrTy ActOnObjCExceptionDecl(Scope *S, Declarator &D);
|
||||
virtual void ActOnParamDefaultArgument(DeclPtrTy param,
|
||||
SourceLocation EqualLoc,
|
||||
ExprArg defarg);
|
||||
|
@ -1675,6 +1674,13 @@ public:
|
|||
SourceLocation RParenLoc,
|
||||
bool MSAsm = false);
|
||||
|
||||
|
||||
VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
|
||||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
bool Invalid = false);
|
||||
|
||||
virtual DeclPtrTy ActOnObjCExceptionDecl(Scope *S, Declarator &D);
|
||||
|
||||
virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
|
||||
SourceLocation RParen,
|
||||
DeclPtrTy Parm, StmtArg Body);
|
||||
|
|
|
@ -1707,10 +1707,92 @@ void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
|
|||
}
|
||||
}
|
||||
|
||||
Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
|
||||
// FIXME: Perform checking on the declaration here.
|
||||
DeclPtrTy Dcl = ActOnParamDeclarator(S, D);
|
||||
if (Dcl.get())
|
||||
cast<VarDecl>(Dcl.getAs<Decl>())->setDeclContext(CurContext);
|
||||
return Dcl;
|
||||
/// \brief Build a type-check a new Objective-C exception variable declaration.
|
||||
VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo,
|
||||
QualType T,
|
||||
IdentifierInfo *Name,
|
||||
SourceLocation NameLoc,
|
||||
bool Invalid) {
|
||||
// ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage
|
||||
// duration shall not be qualified by an address-space qualifier."
|
||||
// Since all parameters have automatic store duration, they can not have
|
||||
// an address space.
|
||||
if (T.getAddressSpace() != 0) {
|
||||
Diag(NameLoc, diag::err_arg_with_address_space);
|
||||
Invalid = true;
|
||||
}
|
||||
|
||||
// An @catch parameter must be an unqualified object pointer type;
|
||||
// FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"?
|
||||
if (Invalid) {
|
||||
// Don't do any further checking.
|
||||
} else if (!T->isObjCObjectPointerType()) {
|
||||
Invalid = true;
|
||||
Diag(NameLoc ,diag::err_catch_param_not_objc_type);
|
||||
} else if (T->isObjCQualifiedIdType()) {
|
||||
Invalid = true;
|
||||
Diag(NameLoc, diag::err_illegal_qualifiers_on_catch_parm);
|
||||
}
|
||||
|
||||
VarDecl *New = VarDecl::Create(Context, CurContext, NameLoc, Name, T, TInfo,
|
||||
VarDecl::None, VarDecl::None);
|
||||
if (Invalid)
|
||||
New->setInvalidDecl();
|
||||
return New;
|
||||
}
|
||||
|
||||
Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
|
||||
const DeclSpec &DS = D.getDeclSpec();
|
||||
|
||||
// We allow the "register" storage class on exception variables because
|
||||
// GCC did, but we drop it completely. Any other storage class is an error.
|
||||
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
|
||||
Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm)
|
||||
<< FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc()));
|
||||
} else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
|
||||
Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm)
|
||||
<< DS.getStorageClassSpec();
|
||||
}
|
||||
if (D.getDeclSpec().isThreadSpecified())
|
||||
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
|
||||
D.getMutableDeclSpec().ClearStorageClassSpecs();
|
||||
|
||||
DiagnoseFunctionSpecifiers(D);
|
||||
|
||||
// Check that there are no default arguments inside the type of this
|
||||
// exception object (C++ only).
|
||||
if (getLangOptions().CPlusPlus)
|
||||
CheckExtraCXXDefaultArguments(D);
|
||||
|
||||
TypeSourceInfo *TInfo = 0;
|
||||
TagDecl *OwnedDecl = 0;
|
||||
QualType ExceptionType = GetTypeForDeclarator(D, S, &TInfo, &OwnedDecl);
|
||||
|
||||
if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) {
|
||||
// Objective-C++: Types shall not be defined in exception types.
|
||||
Diag(OwnedDecl->getLocation(), diag::err_type_defined_in_param_type)
|
||||
<< Context.getTypeDeclType(OwnedDecl);
|
||||
}
|
||||
|
||||
VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, D.getIdentifier(),
|
||||
D.getIdentifierLoc(),
|
||||
D.isInvalidType());
|
||||
|
||||
// Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
|
||||
if (D.getCXXScopeSpec().isSet()) {
|
||||
Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm)
|
||||
<< D.getCXXScopeSpec().getRange();
|
||||
New->setInvalidDecl();
|
||||
}
|
||||
|
||||
// Add the parameter declaration into this scope.
|
||||
S->AddDecl(DeclPtrTy::make(New));
|
||||
if (D.getIdentifier())
|
||||
IdResolver.AddDecl(New);
|
||||
|
||||
ProcessDeclAttributes(S, New, D);
|
||||
|
||||
if (New->hasAttr<BlocksAttr>())
|
||||
Diag(New->getLocation(), diag::err_block_on_nonlocal);
|
||||
return DeclPtrTy::make(New);
|
||||
}
|
||||
|
|
|
@ -1527,23 +1527,11 @@ Action::OwningStmtResult
|
|||
Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
|
||||
SourceLocation RParen, DeclPtrTy Parm,
|
||||
StmtArg Body) {
|
||||
ParmVarDecl *PVD = cast_or_null<ParmVarDecl>(Parm.getAs<Decl>());
|
||||
|
||||
// PVD == 0 implies @catch(...).
|
||||
if (PVD) {
|
||||
// If we already know the decl is invalid, reject it.
|
||||
if (PVD->isInvalidDecl())
|
||||
return StmtError();
|
||||
|
||||
if (!PVD->getType()->isObjCObjectPointerType())
|
||||
return StmtError(Diag(PVD->getLocation(),
|
||||
diag::err_catch_param_not_objc_type));
|
||||
if (PVD->getType()->isObjCQualifiedIdType())
|
||||
return StmtError(Diag(PVD->getLocation(),
|
||||
diag::err_illegal_qualifiers_on_catch_parm));
|
||||
}
|
||||
|
||||
return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, PVD,
|
||||
VarDecl *Var = cast_or_null<VarDecl>(Parm.getAs<Decl>());
|
||||
if (Var && Var->isInvalidDecl())
|
||||
return StmtError();
|
||||
|
||||
return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var,
|
||||
Body.takeAs<Stmt>()));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
struct some_struct;
|
||||
|
||||
@interface NSObject
|
||||
@end
|
||||
|
||||
// Note: NSException is not declared.
|
||||
void f0(id x) {
|
||||
@try {
|
||||
} @catch (NSException *x) { // expected-error {{unknown type name 'NSException'}}
|
||||
} @catch (struct some_struct x) { // expected-error {{@catch parameter is not a pointer to an interface type}}
|
||||
} @catch (int x) { // expected-error {{@catch parameter is not a pointer to an interface type}}
|
||||
} @catch (static NSObject *y) { // expected-error {{@catch parameter cannot have storage specifier 'static'}}
|
||||
} @catch (...) {
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue