summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-04-26 17:32:49 +0000
committerDouglas Gregor <dgregor@apple.com>2010-04-26 17:32:49 +0000
commitf356419bf57bd7cedb6b925d2eae619132f2e052 (patch)
tree5ad40a2e6819b5a077755ef3a0ae16f525a067c3
parent46a572b871de239cb8904bb124418a64edd6adcb (diff)
downloadbcm5719-llvm-f356419bf57bd7cedb6b925d2eae619132f2e052.tar.gz
bcm5719-llvm-f356419bf57bd7cedb6b925d2eae619132f2e052.zip
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
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td9
-rw-r--r--clang/include/clang/Parse/DeclSpec.h3
-rw-r--r--clang/lib/Sema/Sema.h8
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp92
-rw-r--r--clang/lib/Sema/SemaStmt.cpp22
-rw-r--r--clang/test/SemaObjC/stmts.m4
6 files changed, 114 insertions, 24 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 534b451d97d..7f2c4b5d84d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">;
diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h
index 6642e1b9f4f..9c19a674732 100644
--- a/clang/include/clang/Parse/DeclSpec.h
+++ b/clang/include/clang/Parse/DeclSpec.h
@@ -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,
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 8f3d737341c..5eb95714dcd 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -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);
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 8ee5d3292ee..b7ef8df1687 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -1707,10 +1707,92 @@ void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
}
}
+/// \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) {
- // FIXME: Perform checking on the declaration here.
- DeclPtrTy Dcl = ActOnParamDeclarator(S, D);
- if (Dcl.get())
- cast<VarDecl>(Dcl.getAs<Decl>())->setDeclContext(CurContext);
- return Dcl;
+ 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);
}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index a5292efea17..9d6132d050c 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -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>()));
}
diff --git a/clang/test/SemaObjC/stmts.m b/clang/test/SemaObjC/stmts.m
index 20a9f55b209..d1e2ad3612e 100644
--- a/clang/test/SemaObjC/stmts.m
+++ b/clang/test/SemaObjC/stmts.m
@@ -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 (...) {
}
}
OpenPOWER on IntegriCloud