[PATCH] Warn on duplicate function specifier

Serge Pavlov sepavloff at gmail.com
Fri Oct 25 08:45:06 PDT 2013


sepavloff added you to the CC list for the revision "Warn on duplicate function specifier".

This patch fixes PR8264. Duplicate qualifiers already are diagnozed,
now the same diagnostics is issued for duplicate function specifiers.

Please review. 
Thank you.

http://llvm-reviews.chandlerc.com/D2025

Files:
  include/clang/Sema/DeclSpec.h
  lib/Parse/ParseDecl.cpp
  lib/Sema/DeclSpec.cpp
  test/Sema/declspec.c
  test/SemaCXX/explicit.cpp
  test/SemaCXX/virtuals.cpp

Index: include/clang/Sema/DeclSpec.h
===================================================================
--- include/clang/Sema/DeclSpec.h
+++ include/clang/Sema/DeclSpec.h
@@ -634,10 +634,14 @@
   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 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);
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -2767,7 +2767,7 @@
 
     // Microsoft single token adornments.
     case tok::kw___forceinline: {
-      isInvalid = DS.setFunctionSpecInline(Loc);
+      isInvalid = DS.setFunctionSpecInline(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
@@ -2859,18 +2859,18 @@
 
     // 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
Index: lib/Sema/DeclSpec.cpp
===================================================================
--- lib/Sema/DeclSpec.cpp
+++ lib/Sema/DeclSpec.cpp
@@ -739,12 +739,13 @@
 
 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 and C11, 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)
+    if (Lang.C99 || Lang.C11)
       IsExtension = false;
     return BadSpecifier(T, T, PrevSpec, DiagID, IsExtension);
   }
@@ -761,29 +762,60 @@
   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::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;
Index: test/Sema/declspec.c
===================================================================
--- test/Sema/declspec.c
+++ test/Sema/declspec.c
@@ -36,3 +36,16 @@
 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}}
Index: test/SemaCXX/explicit.cpp
===================================================================
--- test/SemaCXX/explicit.cpp
+++ test/SemaCXX/explicit.cpp
@@ -240,3 +240,9 @@
     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}}
+  };
+}
Index: test/SemaCXX/virtuals.cpp
===================================================================
--- test/SemaCXX/virtuals.cpp
+++ test/SemaCXX/virtuals.cpp
@@ -45,3 +45,9 @@
     func *h = 0;
   };
 }
+
+namespace pr8264 {
+  struct Test {
+    virtual virtual void func();  // expected-warning {{duplicate 'virtual' declaration specifier}}
+  };
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2025.1.patch
Type: text/x-patch
Size: 7688 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131025/169143a3/attachment.bin>


More information about the cfe-commits mailing list