Warn about unused declaration-specifiers on tag declarations.

llvm-svn: 128118
This commit is contained in:
John McCall 2011-03-22 23:00:04 +00:00
parent 6149a34102
commit aa01737782
3 changed files with 53 additions and 9 deletions

View File

@ -2535,6 +2535,7 @@ def err_typecheck_sclass_fscope : Error<
"illegal storage class on file-scoped variable">;
def err_unsupported_global_register : Error<
"global register variables are not supported">;
def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">;
def err_typecheck_sclass_func : Error<"illegal storage class on function">;
def err_static_block_func : Error<
"function declared in block scope cannot have 'static' storage class">;

View File

@ -1764,12 +1764,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed.
Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DeclSpec &DS) {
// FIXME: Error on inline/virtual/explicit
// FIXME: Warn on useless __thread
// FIXME: Warn on useless const/volatile
// FIXME: Warn on useless static/extern/typedef/private_extern/mutable
// FIXME: Warn on useless attributes
DeclSpec &DS) {
Decl *TagD = 0;
TagDecl *Tag = 0;
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
@ -1803,6 +1798,10 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return 0;
return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0));
}
// Track whether we warned about the fact that there aren't any
// declarators.
bool emittedWarning = false;
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
ProcessDeclAttributeList(S, Record, DS.getAttributes().getList());
@ -1815,6 +1814,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators)
<< DS.getSourceRange();
emittedWarning = true;
}
}
@ -1840,12 +1840,16 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DS.getStorageClassSpec() != DeclSpec::SCS_typedef)
if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag))
if (Enum->enumerator_begin() == Enum->enumerator_end() &&
!Enum->getIdentifier() && !Enum->isInvalidDecl())
!Enum->getIdentifier() && !Enum->isInvalidDecl()) {
Diag(Enum->getLocation(), diag::ext_no_declarators)
<< DS.getSourceRange();
emittedWarning = true;
}
// Skip all the checks below if we have a type error.
if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD;
if (!DS.isMissingDeclaratorOk() &&
DS.getTypeSpecType() != DeclSpec::TST_error) {
if (!DS.isMissingDeclaratorOk()) {
// Warn about typedefs of enums without names, since this is an
// extension in both Microsoft and GNU.
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef &&
@ -1857,8 +1861,36 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators)
<< DS.getSourceRange();
emittedWarning = true;
}
// We're going to complain about a bunch of spurious specifiers;
// only do this if we're declaring a tag, because otherwise we
// should be getting diag::ext_no_declarators.
if (emittedWarning || (TagD && TagD->isInvalidDecl()))
return TagD;
if (DeclSpec::SCS scs = DS.getStorageClassSpec())
Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier)
<< DeclSpec::getSpecifierName(scs);
if (DS.isThreadSpecified())
Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread";
if (DS.getTypeQualifiers()) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const";
if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile";
// Restrict is covered above.
}
if (DS.isInlineSpecified())
Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline";
if (DS.isVirtualSpecified())
Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual";
if (DS.isExplicitSpecified())
Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit";
// FIXME: Warn on useless attributes
return TagD;
}

View File

@ -46,3 +46,14 @@ struct s0 f0(void) {}
struct x0 {
unsigned int x1;
};
// rdar://problem/9150338
static struct test1 { // expected-warning {{'static' ignored on this declaration}}
int x;
};
const struct test2 { // expected-warning {{'const' ignored on this declaration}}
int x;
};
inline struct test3 { // expected-warning {{'inline' ignored on this declaration}}
int x;
};