[cfe-commits] r102347 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/DeclSpec.h lib/Sema/Sema.h lib/Sema/SemaDeclObjC.cpp lib/Sema/SemaStmt.cpp test/SemaObjC/stmts.m
Douglas Gregor
dgregor at apple.com
Mon Apr 26 10:32:49 PDT 2010
Author: dgregor
Date: Mon Apr 26 12:32:49 2010
New Revision: 102347
URL: http://llvm.org/viewvc/llvm-project?rev=102347&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Parse/DeclSpec.h
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/test/SemaObjC/stmts.m
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=102347&r1=102346&r2=102347&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr 26 12:32:49 2010
@@ -2083,6 +2083,15 @@
"@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">;
Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=102347&r1=102346&r2=102347&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Mon Apr 26 12:32:49 2010
@@ -82,8 +82,9 @@
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,
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=102347&r1=102346&r2=102347&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Apr 26 12:32:49 2010
@@ -812,7 +812,6 @@
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 @@
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);
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=102347&r1=102346&r2=102347&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Apr 26 12:32:49 2010
@@ -1707,10 +1707,92 @@
}
}
+/// \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);
}
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=102347&r1=102346&r2=102347&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Mon Apr 26 12:32:49 2010
@@ -1527,23 +1527,11 @@
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>()));
}
Modified: cfe/trunk/test/SemaObjC/stmts.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/stmts.m?rev=102347&r1=102346&r2=102347&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/stmts.m (original)
+++ cfe/trunk/test/SemaObjC/stmts.m Mon Apr 26 12:32:49 2010
@@ -2,12 +2,16 @@
struct some_struct;
+ at interface NSObject
+ at 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 (...) {
}
}
More information about the cfe-commits
mailing list