[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