зеркало из https://github.com/microsoft/clang-1.git
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 <rdar://problem/7931045>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102931 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
4d9e7388cc
Коммит
324b54d3f6
|
@ -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.
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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++])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) { }
|
||||
}
|
||||
|
||||
|
|
|
@ -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'}}
|
||||
}
|
Загрузка…
Ссылка в новой задаче