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
This commit is contained in:
Lubos Lunak 2013-07-20 15:05:36 +00:00
parent ba5ee4da1d
commit edc138880d
4 changed files with 41 additions and 2 deletions

View File

@ -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">,

View File

@ -1320,7 +1320,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
return false;
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) {
if (!RD->hasTrivialDestructor())
if (!RD->hasTrivialDestructor() && !RD->hasAttr<WarnUnusedAttr>())
return false;
if (const Expr *Init = VD->getInit()) {
@ -1330,7 +1330,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
dyn_cast<CXXConstructExpr>(Init);
if (Construct && !Construct->isElidable()) {
CXXConstructorDecl *CD = Construct->getConstructor();
if (!CD->isTrivial())
if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>())
return false;
}
}

View File

@ -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<RecordDecl>(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;

View File

@ -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();
}