r237383 - DR295: cv-qualifiers on function types are ignored in C++.

Richard Smith richard-llvm at metafoo.co.uk
Thu May 14 12:10:43 PDT 2015


Author: rsmith
Date: Thu May 14 14:10:42 2015
New Revision: 237383

URL: http://llvm.org/viewvc/llvm-project?rev=237383&view=rev
Log:
DR295: cv-qualifiers on function types are ignored in C++.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/CXX/drs/dr2xx.cpp
    cfe/trunk/www/cxx_dr_status.html

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=237383&r1=237382&r2=237383&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu May 14 14:10:42 2015
@@ -4155,8 +4155,11 @@ def err_typecheck_negative_array_size :
 def warn_typecheck_negative_array_new_size : Warning<"array size is negative">,
   // FIXME PR11644: ", will throw std::bad_array_new_length at runtime"
   InGroup<BadArrayNewLength>;
-def warn_typecheck_function_qualifiers : Warning<
-  "qualifier on function type %0 has unspecified behavior">;
+def warn_typecheck_function_qualifiers_ignored : Warning<
+  "'%0' qualifier on function type %1 has no effect">,
+  InGroup<IgnoredQualifiers>;
+def warn_typecheck_function_qualifiers_unspecified : Warning<
+  "'%0' qualifier on function type %1 has unspecified behavior">;
 def warn_typecheck_reference_qualifiers : Warning<
   "'%0' qualifier on reference type %1 has no effect">,
   InGroup<IgnoredQualifiers>;

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=237383&r1=237382&r2=237383&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu May 14 14:10:42 2015
@@ -688,6 +688,33 @@ static void maybeSynthesizeBlockSignatur
   state.setCurrentChunkIndex(declarator.getNumTypeObjects());
 }
 
+void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS,
+                                     unsigned &TypeQuals, QualType TypeSoFar,
+                                     unsigned RemoveTQs, unsigned DiagID) {
+  // If this occurs outside a template instantiation, warn the user about
+  // it; they probably didn't mean to specify a redundant qualifier.
+  typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
+  QualLoc Quals[] = {
+    QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
+    QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
+    QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())
+  };
+
+  for (unsigned I = 0, N = llvm::array_lengthof(Quals); I != N; ++I) {
+    if (!(RemoveTQs & Quals[I].first))
+      continue;
+
+    if (S.ActiveTemplateInstantiations.empty()) {
+      if (TypeQuals & Quals[I].first)
+        S.Diag(Quals[I].second, DiagID)
+          << DeclSpec::getSpecifierName(Quals[I].first) << TypeSoFar
+          << FixItHint::CreateRemoval(Quals[I].second);
+    }
+
+    TypeQuals &= ~Quals[I].first;
+  }
+}
+
 /// \brief Convert the specified declspec to the appropriate type
 /// object.
 /// \param state Specifies the declarator containing the declaration specifier
@@ -1117,24 +1144,22 @@ static QualType ConvertDeclSpecToType(Ty
 
   // Apply const/volatile/restrict qualifiers to T.
   if (unsigned TypeQuals = DS.getTypeQualifiers()) {
-
-    // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
-    // of a function type includes any type qualifiers, the behavior is
-    // undefined."
-    if (Result->isFunctionType() && TypeQuals) {
-      if (TypeQuals & DeclSpec::TQ_const)
-        S.Diag(DS.getConstSpecLoc(), diag::warn_typecheck_function_qualifiers)
-          << Result << DS.getSourceRange();
-      else if (TypeQuals & DeclSpec::TQ_volatile)
-        S.Diag(DS.getVolatileSpecLoc(),
-               diag::warn_typecheck_function_qualifiers)
-            << Result << DS.getSourceRange();
-      else {
-        assert((TypeQuals & (DeclSpec::TQ_restrict | DeclSpec::TQ_atomic)) &&
-               "Has CVRA quals but not C, V, R, or A?");
-        // No diagnostic; we'll diagnose 'restrict' or '_Atomic' applied to a
-        // function type later, in BuildQualifiedType.
-      }
+    // Warn about CV qualifiers on function types.
+    // C99 6.7.3p8:
+    //   If the specification of a function type includes any type qualifiers,
+    //   the behavior is undefined.
+    // C++11 [dcl.fct]p7:
+    //   The effect of a cv-qualifier-seq in a function declarator is not the
+    //   same as adding cv-qualification on top of the function type. In the
+    //   latter case, the cv-qualifiers are ignored.
+    if (TypeQuals && Result->isFunctionType()) {
+      diagnoseAndRemoveTypeQualifiers(
+          S, DS, TypeQuals, Result, DeclSpec::TQ_const | DeclSpec::TQ_volatile,
+          S.getLangOpts().CPlusPlus
+              ? diag::warn_typecheck_function_qualifiers_ignored
+              : diag::warn_typecheck_function_qualifiers_unspecified);
+      // No diagnostic for 'restrict' or '_Atomic' applied to a
+      // function type; we'll diagnose those later, in BuildQualifiedType.
     }
 
     // C++11 [dcl.ref]p1:
@@ -1145,25 +1170,11 @@ static QualType ConvertDeclSpecToType(Ty
     // There don't appear to be any other contexts in which a cv-qualified
     // reference type could be formed, so the 'ill-formed' clause here appears
     // to never happen.
-    if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
-        TypeQuals && Result->isReferenceType()) {
-      // If this occurs outside a template instantiation, warn the user about
-      // it; they probably didn't mean to specify a redundant qualifier.
-      typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
-      QualLoc Quals[] = {
-        QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
-        QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
-        QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())
-      };
-      for (unsigned I = 0, N = llvm::array_lengthof(Quals); I != N; ++I) {
-        if (S.ActiveTemplateInstantiations.empty()) {
-          if (TypeQuals & Quals[I].first)
-            S.Diag(Quals[I].second, diag::warn_typecheck_reference_qualifiers)
-              << DeclSpec::getSpecifierName(Quals[I].first) << Result
-              << FixItHint::CreateRemoval(Quals[I].second);
-        }
-        TypeQuals &= ~Quals[I].first;
-      }
+    if (TypeQuals && Result->isReferenceType()) {
+      diagnoseAndRemoveTypeQualifiers(
+          S, DS, TypeQuals, Result,
+          DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic,
+          diag::warn_typecheck_reference_qualifiers);
     }
 
     // C90 6.5.3 constraints: "The same type qualifier shall not appear more

Modified: cfe/trunk/test/CXX/drs/dr2xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr2xx.cpp?rev=237383&r1=237382&r2=237383&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr2xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr2xx.cpp Thu May 14 14:10:42 2015
@@ -999,15 +999,20 @@ namespace dr294 { // dr294: no
   }
 }
 
-namespace dr295 { // dr295: no
+namespace dr295 { // dr295: 3.7
   typedef int f();
-  // FIXME: This warning is incorrect.
-  const f g; // expected-warning {{unspecified behavior}}
-  const f &r = g; // expected-warning {{unspecified behavior}}
+  const f g; // expected-warning {{'const' qualifier on function type 'f' (aka 'int ()') has no effect}}
+  f &r = g;
   template<typename T> struct X {
     const T &f;
   };
-  X<f> x = {g}; // FIXME: expected-error {{drops qualifiers}}
+  X<f> x = {g};
+
+  typedef int U();
+  typedef const U U; // expected-warning {{'const' qualifier on function type 'U' (aka 'int ()') has no effect}}
+
+  typedef int (*V)();
+  typedef volatile U *V; // expected-warning {{'volatile' qualifier on function type 'U' (aka 'int ()') has no effect}}
 }
 
 namespace dr296 { // dr296: yes

Modified: cfe/trunk/www/cxx_dr_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=237383&r1=237382&r2=237383&view=diff
==============================================================================
--- cfe/trunk/www/cxx_dr_status.html (original)
+++ cfe/trunk/www/cxx_dr_status.html Thu May 14 14:10:42 2015
@@ -1811,7 +1811,7 @@ of class templates</td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#295">295</a></td>
     <td>CD1</td>
     <td>cv-qualifiers on function types</td>
-    <td class="none" align="center">No</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr id="296">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#296">296</a></td>





More information about the cfe-commits mailing list