From edc138880d8543d60de08be2698b695821888752 Mon Sep 17 00:00:00 2001 From: Lubos Lunak Date: Sat, 20 Jul 2013 15:05:36 +0000 Subject: [PATCH] add type attribute warn_unused, for -Wunused-variable warnings (pr#14253) The functionality is equivalent to the GCC attribute. Variables of tagged types will be warned about as unused if they are not used in any way except for possible (even non-trivial) ctors/dtors called. Useful for tagging classes like std::string (which is not part of this commit). llvm-svn: 186765 --- clang/include/clang/Basic/Attr.td | 5 +++++ clang/lib/Sema/SemaDecl.cpp | 4 ++-- clang/lib/Sema/SemaDeclAttr.cpp | 14 ++++++++++++++ clang/test/SemaCXX/warn-unused-attribute.cpp | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 clang/test/SemaCXX/warn-unused-attribute.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 8c820a0..eea99eb 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -749,6 +749,11 @@ def VecReturn : InheritableAttr { let Subjects = [CXXRecord]; } +def WarnUnused : InheritableAttr { + let Spellings = [GNU<"warn_unused">, CXX11<"gnu", "warn_unused">]; + let Subjects = [Record]; +} + def WarnUnusedResult : InheritableAttr { let Spellings = [GNU<"warn_unused_result">, CXX11<"clang", "warn_unused_result">, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2291fc2..53303e7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1320,7 +1320,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return false; if (const CXXRecordDecl *RD = dyn_cast(Tag)) { - if (!RD->hasTrivialDestructor()) + if (!RD->hasTrivialDestructor() && !RD->hasAttr()) return false; if (const Expr *Init = VD->getInit()) { @@ -1330,7 +1330,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { dyn_cast(Init); if (Construct && !Construct->isElidable()) { CXXConstructorDecl *CD = Construct->getConstructor(); - if (!CD->isTrivial()) + if (!CD->isTrivial() && !RD->hasAttr()) return false; } } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index ef401c3..a3e05e6 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2668,6 +2668,17 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } +static void handleWarnUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (RecordDecl *RD = dyn_cast(D)) + RD->addAttr(::new (S.Context) WarnUnusedAttr(Attr.getRange(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (!checkAttributeNumArgs(S, Attr, 0)) @@ -4892,6 +4903,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_TypeVisibility: handleVisibilityAttr(S, D, Attr, true); break; + case AttributeList::AT_WarnUnused: + handleWarnUnusedAttr(S, D, Attr); + break; case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr); break; case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break; diff --git a/clang/test/SemaCXX/warn-unused-attribute.cpp b/clang/test/SemaCXX/warn-unused-attribute.cpp new file mode 100644 index 0000000..72f96ee --- /dev/null +++ b/clang/test/SemaCXX/warn-unused-attribute.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -verify %s +struct __attribute__((warn_unused)) Test +{ + Test(); + ~Test(); + void use(); +}; + +struct TestNormal +{ + TestNormal(); +}; + +int main() +{ + Test unused; // expected-warning {{unused variable 'unused'}} + Test used; + TestNormal normal; + used.use(); +} -- 2.7.4