forked from OSchip/llvm-project
Warn about unused declaration-specifiers on tag declarations.
llvm-svn: 128118
This commit is contained in:
parent
6149a34102
commit
aa01737782
|
@ -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">;
|
||||
|
|
|
@ -1765,11 +1765,6 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
|||
/// 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
|
||||
Decl *TagD = 0;
|
||||
TagDecl *Tag = 0;
|
||||
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
|
||||
|
@ -1804,6 +1799,10 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
|
|||
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;
|
||||
}
|
||||
|
||||
if (!DS.isMissingDeclaratorOk() &&
|
||||
DS.getTypeSpecType() != DeclSpec::TST_error) {
|
||||
// Skip all the checks below if we have a type error.
|
||||
if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue