r194559 - Warn on duplicate function specifier
Serge Pavlov
sepavloff at gmail.com
Tue Nov 12 22:57:53 PST 2013
Author: sepavloff
Date: Wed Nov 13 00:57:53 2013
New Revision: 194559
URL: http://llvm.org/viewvc/llvm-project?rev=194559&view=rev
Log:
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
Modified:
cfe/trunk/include/clang/Sema/DeclSpec.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Sema/DeclSpec.cpp
cfe/trunk/test/Parser/MicrosoftExtensions.c
cfe/trunk/test/Sema/declspec.c
cfe/trunk/test/SemaCXX/explicit.cpp
cfe/trunk/test/SemaCXX/virtuals.cpp
Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=194559&r1=194558&r2=194559&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Wed Nov 13 00:57:53 2013
@@ -337,6 +337,7 @@ private:
// function-specifier
unsigned FS_inline_specified : 1;
+ unsigned FS_forceinline_specified: 1;
unsigned FS_virtual_specified : 1;
unsigned FS_explicit_specified : 1;
unsigned FS_noreturn_specified : 1;
@@ -381,6 +382,7 @@ private:
SourceRange TypeofParensRange;
SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc;
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
+ SourceLocation FS_forceinlineLoc;
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
WrittenBuiltinSpecs writtenBS;
@@ -419,6 +421,7 @@ public:
TypeSpecOwned(false),
TypeQualifiers(TQ_unspecified),
FS_inline_specified(false),
+ FS_forceinline_specified(false),
FS_virtual_specified(false),
FS_explicit_specified(false),
FS_noreturn_specified(false),
@@ -532,8 +535,12 @@ public:
}
// function-specifier
- bool isInlineSpecified() const { return FS_inline_specified; }
- SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; }
+ bool isInlineSpecified() const {
+ return FS_inline_specified | FS_forceinline_specified;
+ }
+ SourceLocation getInlineSpecLoc() const {
+ return FS_inline_specified ? FS_inlineLoc : FS_forceinlineLoc;
+ }
bool isVirtualSpecified() const { return FS_virtual_specified; }
SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; }
@@ -547,6 +554,8 @@ public:
void ClearFunctionSpecs() {
FS_inline_specified = false;
FS_inlineLoc = SourceLocation();
+ FS_forceinline_specified = false;
+ FS_forceinlineLoc = SourceLocation();
FS_virtual_specified = false;
FS_virtualLoc = SourceLocation();
FS_explicit_specified = false;
@@ -634,10 +643,16 @@ public:
bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, const LangOptions &Lang);
- bool setFunctionSpecInline(SourceLocation Loc);
- bool setFunctionSpecVirtual(SourceLocation Loc);
- bool setFunctionSpecExplicit(SourceLocation Loc);
- bool setFunctionSpecNoreturn(SourceLocation Loc);
+ bool setFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecForceInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecNoreturn(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=194559&r1=194558&r2=194559&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Nov 13 00:57:53 2013
@@ -2730,7 +2730,7 @@ void Parser::ParseDeclarationSpecifiers(
// 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(
// 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
Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=194559&r1=194558&r2=194559&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Wed Nov 13 00:57:53 2013
@@ -349,7 +349,7 @@ unsigned DeclSpec::getParsedSpecifiers()
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, SourceL
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;
Modified: cfe/trunk/test/Parser/MicrosoftExtensions.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/MicrosoftExtensions.c?rev=194559&r1=194558&r2=194559&view=diff
==============================================================================
--- cfe/trunk/test/Parser/MicrosoftExtensions.c (original)
+++ cfe/trunk/test/Parser/MicrosoftExtensions.c Wed Nov 13 00:57:53 2013
@@ -30,6 +30,20 @@ void __forceinline InterlockedBitTestAnd
};
#endif
}
+
+// Both inline and __forceinline is OK.
+inline void __forceinline pr8264() {
+}
+__forceinline void inline pr8264_1() {
+}
+void inline __forceinline pr8264_2() {
+}
+void __forceinline inline pr8264_3() {
+}
+// But duplicate __forceinline causes warning.
+void __forceinline __forceinline pr8264_4() { // expected-warning{{duplicate '__forceinline' declaration specifier}}
+}
+
_inline int foo99() { return 99; }
void test_ms_alignof_alias() {
Modified: cfe/trunk/test/Sema/declspec.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/declspec.c?rev=194559&r1=194558&r2=194559&view=diff
==============================================================================
--- cfe/trunk/test/Sema/declspec.c (original)
+++ cfe/trunk/test/Sema/declspec.c Wed Nov 13 00:57:53 2013
@@ -36,3 +36,16 @@ void test2() {}
struct test3s {
} // expected-error {{expected ';' after struct}}
typedef int test3g;
+
+// PR8264
+const const int pr8264_1 = 0; // expected-warning {{duplicate 'const' declaration specifier}}
+volatile volatile int pr8264_2; // expected-warning {{duplicate 'volatile' declaration specifier}}
+char * restrict restrict pr8264_3; // expected-warning {{duplicate 'restrict' declaration specifier}}
+
+extern extern int pr8264_4; // expected-warning {{duplicate 'extern' declaration specifier}}
+void pr8264_5() {
+ register register int x; // expected-warning {{duplicate 'register' declaration specifier}}
+}
+
+inline inline void pr8264_6() {} // expected-warning {{duplicate 'inline' declaration specifier}}
+_Noreturn _Noreturn void pr8264_7(); // expected-warning {{duplicate '_Noreturn' declaration specifier}}
Modified: cfe/trunk/test/SemaCXX/explicit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/explicit.cpp?rev=194559&r1=194558&r2=194559&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/explicit.cpp (original)
+++ cfe/trunk/test/SemaCXX/explicit.cpp Wed Nov 13 00:57:53 2013
@@ -240,3 +240,9 @@ namespace Conversion {
nfp(1); // expected-error {{type 'NotFP' does not provide a call operator}}
}
}
+
+namespace pr8264 {
+ struct Test {
+ explicit explicit Test(int x); // expected-warning{{duplicate 'explicit' declaration specifier}}
+ };
+}
Modified: cfe/trunk/test/SemaCXX/virtuals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/virtuals.cpp?rev=194559&r1=194558&r2=194559&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/virtuals.cpp (original)
+++ cfe/trunk/test/SemaCXX/virtuals.cpp Wed Nov 13 00:57:53 2013
@@ -45,3 +45,9 @@ namespace rdar9670557 {
func *h = 0;
};
}
+
+namespace pr8264 {
+ struct Test {
+ virtual virtual void func(); // expected-warning {{duplicate 'virtual' declaration specifier}}
+ };
+}
More information about the cfe-commits
mailing list