]> granicus.if.org Git - clang/commitdiff
Diagnose unused exception parameters under a different warning group
authorDouglas Gregor <dgregor@apple.com>
Mon, 3 May 2010 18:51:14 +0000 (18:51 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 3 May 2010 18:51:14 +0000 (18:51 +0000)
(-Wunused-exception-parameter) than normal variables, since it's more
common to name and then ignore an exception parameter. This warning is
neither enabled by default nor by -Wall. Fixes <rdar://problem/7931045>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102931 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Frontend/PCHReaderDecl.cpp
lib/Frontend/PCHWriterDecl.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/catch-stmt.m
test/SemaObjC/warn-unused-exception-param.m [new file with mode: 0644]

index 3211ce8d45e4ca165329f3af605f6f4f4cd11459..834c9a0c563fd34a12490a223e06bbfc884703e4 100644 (file)
@@ -498,6 +498,10 @@ private:
   /// condition, e.g., if (int x = foo()) { ... }.
   bool DeclaredInCondition : 1;
 
+  /// \brief Whether this variable is the exception variable in a C++ catch
+  /// or an Objective-C @catch statement.
+  bool ExceptionVar : 1;
+  
   friend class StmtIteratorBase;
 protected:
   VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
@@ -505,7 +509,7 @@ protected:
           StorageClass SCAsWritten)
     : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
       ThreadSpecified(false), HasCXXDirectInit(false),
-      DeclaredInCondition(false) {
+      DeclaredInCondition(false), ExceptionVar(false) {
     SClass = SC;
     SClassAsWritten = SCAsWritten;
   }
@@ -841,6 +845,13 @@ public:
     DeclaredInCondition = InCondition;
   }
   
+  /// \brief Determine whether this variable is the exception variable in a
+  /// C++ catch statememt or an Objective-C @catch statement.
+  bool isExceptionVariable() const {
+    return ExceptionVar;
+  }
+  void setExceptionVariable(bool EV) { ExceptionVar = EV; }
+  
   /// \brief If this variable is an instantiated static data member of a
   /// class template specialization, returns the templated static data member
   /// from which it was instantiated.
index 1b2abfefd58c67adec2de49fd4494e646f8f572e..c74a48c445fe7c14f5fa063767f2d210698b91de 100644 (file)
@@ -108,6 +108,7 @@ def : DiagGroup<"type-limits">;
 def Uninitialized  : DiagGroup<"uninitialized">;
 def UnknownPragmas : DiagGroup<"unknown-pragmas">;
 def UnusedArgument : DiagGroup<"unused-argument">;
+def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
 def UnusedFunction : DiagGroup<"unused-function">;
 def UnusedLabel : DiagGroup<"unused-label">;
 def UnusedParameter : DiagGroup<"unused-parameter">;
index d654ed513dd3b5bba0bca45fd7fc0e81d0cb0f72..93ab858065404b419b496b6ad8122d2d34bc5ef9 100644 (file)
@@ -85,6 +85,8 @@ def warn_unused_parameter : Warning<"unused parameter %0">,
   InGroup<UnusedParameter>, DefaultIgnore;
 def warn_unused_variable : Warning<"unused variable %0">,
   InGroup<UnusedVariable>, DefaultIgnore;
+def warn_unused_exception_param : Warning<"unused exception parameter %0">,
+  InGroup<UnusedExceptionParameter>, DefaultIgnore;
 def warn_decl_in_param_list : Warning<
   "declaration of %0 will not be visible outside of this function">;
 def err_array_star_in_function_definition : Error<
index c215a5abba2c0bef755a4f31db245cb854d60e07..14dd2e927c41a11de9e47836004a24333df6010a 100644 (file)
@@ -410,6 +410,7 @@ void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
   VD->setThreadSpecified(Record[Idx++]);
   VD->setCXXDirectInitializer(Record[Idx++]);
   VD->setDeclaredInCondition(Record[Idx++]);
+  VD->setExceptionVariable(Record[Idx++]);
   VD->setPreviousDeclaration(
                          cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
   if (Record[Idx++])
index c3831628eb3078432016de58013afc1c63d33cae..7b78062396042ec98b20584e88a6dabfc4f6ac79 100644 (file)
@@ -389,6 +389,7 @@ void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
   Record.push_back(D->isThreadSpecified());
   Record.push_back(D->hasCXXDirectInitializer());
   Record.push_back(D->isDeclaredInCondition());
+  Record.push_back(D->isExceptionVariable());
   Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
   Record.push_back(D->getInit()? 1 : 0);
   if (D->getInit())
@@ -429,6 +430,7 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
   assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
   assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
   assert(!D->isDeclaredInCondition() && "PARM_VAR_DECL can't be in condition");
+  assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
   assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl");
   assert(D->getInit() == 0 && "PARM_VAR_DECL never has init");
 }
@@ -501,6 +503,7 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(0));                       // isThreadSpecified
   Abv->Add(BitCodeAbbrevOp(0));                       // hasCXXDirectInitializer
   Abv->Add(BitCodeAbbrevOp(0));                       // isDeclaredInCondition
+  Abv->Add(BitCodeAbbrevOp(0));                       // isExceptionVariable
   Abv->Add(BitCodeAbbrevOp(0));                       // PrevDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // HasInit
   // ParmVarDecl
index eb91ec614724984e709259291f6eb600577551e7..0e839a9d2d69fa339fe34eb8dcf2603217008625 100644 (file)
@@ -585,9 +585,14 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
 
     // Diagnose unused variables in this scope.
     if (ShouldDiagnoseUnusedDecl(D) && 
-        S->getNumErrorsAtStart() == getDiagnostics().getNumErrors())
-      Diag(D->getLocation(), diag::warn_unused_variable) << D->getDeclName();
-    
+        S->getNumErrorsAtStart() == getDiagnostics().getNumErrors()) {
+      if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable())
+        Diag(D->getLocation(), diag::warn_unused_exception_param)
+          << D->getDeclName();
+      else
+        Diag(D->getLocation(), diag::warn_unused_variable) 
+          << D->getDeclName();
+    }
     // Remove this name from our lexical scope.
     IdResolver.RemoveDecl(D);
   }
index 58be7aecf0839ee95076117089a807fcb3992b93..c4467850c93b8acf04a996606f5413a07e386533 100644 (file)
@@ -5276,7 +5276,8 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
   VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc,
                                     Name, ExDeclType, TInfo, VarDecl::None,
                                     VarDecl::None);
-
+  ExDecl->setExceptionVariable(true);
+  
   if (!Invalid) {
     if (const RecordType *RecordTy = ExDeclType->getAs<RecordType>()) {
       // C++ [except.handle]p16:
index 8032030cf0d442df93fb0d9beaf6baeca9e98a0b..d446cc13da26d58fa07006487f62a269484a617e 100644 (file)
@@ -1738,7 +1738,9 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo,
   }
   
   VarDecl *New = VarDecl::Create(Context, CurContext, NameLoc, Name, T, TInfo,
-                                 VarDecl::None, VarDecl::None);  
+                                 VarDecl::None, VarDecl::None);
+  New->setExceptionVariable(true);
+  
   if (Invalid)
     New->setInvalidDecl();
   return New;
index 80c986ff54478285c1b815f29f6fd163a3555da4..ef1da377094cb9e97563174f89182601d57f2d0c 100644 (file)
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -verify %s
-
+@interface A @end
 @protocol P;
 
 void f() {
@@ -8,6 +8,6 @@ void f() {
   } @catch (int) { // expected-error{{@catch parameter is not a pointer to an interface type}}
   } @catch (int *b) { // expected-error{{@catch parameter is not a pointer to an interface type}}
   } @catch (id <P> c) { // expected-error{{illegal qualifiers on @catch parameter}}
-  }
+  } @catch(A* a) { }
 }
 
diff --git a/test/SemaObjC/warn-unused-exception-param.m b/test/SemaObjC/warn-unused-exception-param.m
new file mode 100644 (file)
index 0000000..f649f8c
--- /dev/null
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-exception-parameter %s
+void  f0() {
+  @try {} @catch(id a) {} // expected-warning{{unused exception parameter 'a'}}
+}