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:
parent
ba5ee4da1d
commit
edc138880d
|
@ -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">,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue