From: Douglas Gregor Date: Mon, 3 May 2010 18:51:14 +0000 (+0000) Subject: Diagnose unused exception parameters under a different warning group X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=324b54d3f60d92a82815512119791ce1c285b63e;p=clang Diagnose unused exception parameters under a different warning group (-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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102931 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 3211ce8d45..834c9a0c56 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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. diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 1b2abfefd5..c74a48c445 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -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">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d654ed513d..93ab858065 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -85,6 +85,8 @@ def warn_unused_parameter : Warning<"unused parameter %0">, InGroup, DefaultIgnore; def warn_unused_variable : Warning<"unused variable %0">, InGroup, DefaultIgnore; +def warn_unused_exception_param : Warning<"unused exception parameter %0">, + InGroup, 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< diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index c215a5abba..14dd2e927c 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -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(Reader.GetDecl(Record[Idx++]))); if (Record[Idx++]) diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index c3831628eb..7b78062396 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -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 diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index eb91ec6147..0e839a9d2d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(D) && cast(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); } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 58be7aecf0..c4467850c9 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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()) { // C++ [except.handle]p16: diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 8032030cf0..d446cc13da 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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; diff --git a/test/SemaObjC/catch-stmt.m b/test/SemaObjC/catch-stmt.m index 80c986ff54..ef1da37709 100644 --- a/test/SemaObjC/catch-stmt.m +++ b/test/SemaObjC/catch-stmt.m @@ -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

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 index 0000000000..f649f8c812 --- /dev/null +++ b/test/SemaObjC/warn-unused-exception-param.m @@ -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'}} +}