diff options
author | Serge Pavlov <sepavloff@gmail.com> | 2013-11-13 06:57:53 +0000 |
---|---|---|
committer | Serge Pavlov <sepavloff@gmail.com> | 2013-11-13 06:57:53 +0000 |
commit | 750db65bacfcdcc28e41fdc0be5153f258e0cf55 (patch) | |
tree | 6884828d1a07ab47b8bbeeaac463fda3c294b5ac /clang/lib | |
parent | b71b7baa2fa3890041a3a6ff8fa7e08719348964 (diff) | |
download | bcm5719-llvm-750db65bacfcdcc28e41fdc0be5153f258e0cf55.tar.gz bcm5719-llvm-750db65bacfcdcc28e41fdc0be5153f258e0cf55.zip |
Warn on duplicate function specifier
This patch fixes PR8264. Duplicate qualifiers already are diagnozed,
now the same diagnostics is issued for duplicate function specifiers.
Differential Revision: http://llvm-reviews.chandlerc.com/D2025
llvm-svn: 194559
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 68 |
2 files changed, 61 insertions, 17 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c5904933133..36d704d31a9 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2730,7 +2730,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Microsoft single token adornments. case tok::kw___forceinline: { - isInvalid = DS.setFunctionSpecInline(Loc); + isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID); IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = Tok.getLocation(); // FIXME: This does not work correctly if it is set to be a declspec @@ -2822,18 +2822,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // function-specifier case tok::kw_inline: - isInvalid = DS.setFunctionSpecInline(Loc); + isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID); break; case tok::kw_virtual: - isInvalid = DS.setFunctionSpecVirtual(Loc); + isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID); break; case tok::kw_explicit: - isInvalid = DS.setFunctionSpecExplicit(Loc); + isInvalid = DS.setFunctionSpecExplicit(Loc, PrevSpec, DiagID); break; case tok::kw__Noreturn: if (!getLangOpts().C11) Diag(Loc, diag::ext_c11_noreturn); - isInvalid = DS.setFunctionSpecNoreturn(Loc); + isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID); break; // alignment-specifier diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 46914f68040..538c16eeb25 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -349,7 +349,7 @@ unsigned DeclSpec::getParsedSpecifiers() const { Res |= PQ_TypeSpecifier; if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified || - FS_noreturn_specified) + FS_noreturn_specified || FS_forceinline_specified) Res |= PQ_FunctionSpecifier; return Res; } @@ -739,9 +739,10 @@ bool DeclSpec::SetTypeSpecError() { bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const LangOptions &Lang) { - // Duplicates are permitted in C99, but are not permitted in C++. However, - // since this is likely not what the user intended, we will always warn. We - // do not need to set the qualifier's location since we already have it. + // Duplicates are permitted in C99 onwards, but are not permitted in C89 or + // C++. However, since this is likely not what the user intended, we will + // always warn. We do not need to set the qualifier's location since we + // already have it. if (TypeQualifiers & T) { bool IsExtension = true; if (Lang.C99) @@ -761,29 +762,72 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, llvm_unreachable("Unknown type qualifier!"); } -bool DeclSpec::setFunctionSpecInline(SourceLocation Loc) { - // 'inline inline' is ok. +bool DeclSpec::setFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'inline inline' is ok. However, since this is likely not what the user + // intended, we will always warn, similar to duplicates of type qualifiers. + if (FS_inline_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "inline"; + return true; + } FS_inline_specified = true; FS_inlineLoc = Loc; return false; } -bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc) { - // 'virtual virtual' is ok. +bool DeclSpec::setFunctionSpecForceInline(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + if (FS_forceinline_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "__forceinline"; + return true; + } + FS_forceinline_specified = true; + FS_forceinlineLoc = Loc; + return false; +} + +bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + // 'virtual virtual' is ok, but warn as this is likely not what the user + // intended. + if (FS_virtual_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "virtual"; + return true; + } FS_virtual_specified = true; FS_virtualLoc = Loc; return false; } -bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc) { - // 'explicit explicit' is ok. +bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + // 'explicit explicit' is ok, but warn as this is likely not what the user + // intended. + if (FS_explicit_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "explicit"; + return true; + } FS_explicit_specified = true; FS_explicitLoc = Loc; return false; } -bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc) { - // '_Noreturn _Noreturn' is ok. +bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + // '_Noreturn _Noreturn' is ok, but warn as this is likely not what the user + // intended. + if (FS_noreturn_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "_Noreturn"; + return true; + } FS_noreturn_specified = true; FS_noreturnLoc = Loc; return false; |