summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/Sema.h3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp37
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp7
3 files changed, 30 insertions, 17 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 24480fe81a0..3bea485c8fb 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -1761,7 +1761,8 @@ public:
/// DiagnoseUnusedExprResult - If the statement passed in is an expression
/// whose result is unused, warn.
void DiagnoseUnusedExprResult(const Stmt *S);
-
+ void DiagnoseUnusedDecl(const NamedDecl *ND);
+
ParsingDeclStackState PushParsingDeclaration();
void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D);
void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index bf3c1724836..40ba8ffc195 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -544,9 +544,9 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
return false;
}
- // If we failed to complete the type for some reason, don't
- // diagnose the variable.
- if (Ty->isIncompleteType())
+ // If we failed to complete the type for some reason, or if the type is
+ // dependent, don't diagnose the variable.
+ if (Ty->isIncompleteType() || Ty->isDependentType())
return false;
if (const TagType *TT = Ty->getAs<TagType>()) {
@@ -555,9 +555,10 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
return false;
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) {
- if (!RD->hasTrivialConstructor())
- return false;
- if (!RD->hasTrivialDestructor())
+ // FIXME: Checking for the presence of a user-declared constructor
+ // isn't completely accurate; we'd prefer to check that the initializer
+ // has no side effects.
+ if (RD->hasUserDeclaredConstructor() || !RD->hasTrivialDestructor())
return false;
}
}
@@ -568,6 +569,18 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
return true;
}
+void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
+ if (!ShouldDiagnoseUnusedDecl(D))
+ return;
+
+ 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();
+}
+
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (S->decl_empty()) return;
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
@@ -584,15 +597,9 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (!D->getDeclName()) continue;
// Diagnose unused variables in this scope.
- if (ShouldDiagnoseUnusedDecl(D) &&
- 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();
- }
+ if (S->getNumErrorsAtStart() == getDiagnostics().getNumErrors())
+ DiagnoseUnusedDecl(D);
+
// Remove this name from our lexical scope.
IdResolver.RemoveDecl(D);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a32c0e1ac32..d3d6c2209f5 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -351,7 +351,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
Var->setLexicalDeclContext(D->getLexicalDeclContext());
Var->setAccess(D->getAccess());
-
+ Var->setUsed(D->isUsed());
+
// FIXME: In theory, we could have a previous declaration for variables that
// are not static data members.
bool Redeclaration = false;
@@ -419,6 +420,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
} else if (!Var->isStaticDataMember() || Var->isOutOfLine())
SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
+ // Diagnose unused local variables.
+ if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed())
+ SemaRef.DiagnoseUnusedDecl(Var);
+
return Var;
}
OpenPOWER on IntegriCloud