]> granicus.if.org Git - clang/commitdiff
PR13110: Add a -Wignored-qualifiers warning when ignoring a const, volatile, or
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 19 Feb 2014 00:13:27 +0000 (00:13 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 19 Feb 2014 00:13:27 +0000 (00:13 +0000)
_Atomic qualifier applied to a reference type.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201620 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaType.cpp
test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp
test/CXX/drs/dr1xx.cpp
test/Parser/cxx-reference.cpp
test/Parser/cxx0x-rvalue-reference.cpp
test/SemaCXX/references.cpp

index af3445b16ff700716f3ffa6cc6957cbe503219ef..e4d0f941b726ed15106e225c60e3a963e6700310 100644 (file)
@@ -3787,6 +3787,9 @@ def warn_typecheck_negative_array_new_size : Warning<"array size is negative">,
   InGroup<BadArrayNewLength>;
 def warn_typecheck_function_qualifiers : Warning<
   "qualifier on function type %0 has unspecified behavior">;
+def warn_typecheck_reference_qualifiers : Warning<
+  "'%0' qualifier on reference type %1 has no effect">,
+  InGroup<IgnoredQualifiers>;
 def err_typecheck_invalid_restrict_not_pointer : Error<
   "restrict requires a pointer or reference (%0 is invalid)">;
 def err_typecheck_invalid_restrict_not_pointer_noarg : Error<
index a75327c9d17b0f7ae5eb9412d3b6cc525edd6967..f202af489b6d430bfe798f6f63b184af0773168b 100644 (file)
@@ -1117,17 +1117,32 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
       }
     }
 
-    // C++ [dcl.ref]p1:
+    // C++11 [dcl.ref]p1:
     //   Cv-qualified references are ill-formed except when the
-    //   cv-qualifiers are introduced through the use of a typedef
-    //   (7.1.3) or of a template type argument (14.3), in which
-    //   case the cv-qualifiers are ignored.
-    // FIXME: Shouldn't we be checking SCS_typedef here?
+    //   cv-qualifiers are introduced through the use of a typedef-name
+    //   or decltype-specifier, in which case the cv-qualifiers are ignored.
+    //
+    // 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()) {
-      TypeQuals &= ~DeclSpec::TQ_const;
-      TypeQuals &= ~DeclSpec::TQ_volatile;
-      TypeQuals &= ~DeclSpec::TQ_atomic;
+      // If this occurs outside a template instantiation, warn the user about
+      // it; they probably didn't mean to specify a redundant qualifier.
+      std::pair<DeclSpec::TQ, SourceLocation> Quals[] = {
+        { DeclSpec::TQ_const, DS.getConstSpecLoc() },
+        { DeclSpec::TQ_volatile, DS.getVolatileSpecLoc() },
+        { 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;
+      }
     }
 
     // C90 6.5.3 constraints: "The same type qualifier shall not appear more
index cd623df71e81bfad82600505354259e95380f07c..0f76e1f3c79b70786f09d746a57cc7e26bc69b79 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// expected-no-diagnostics
 
 template<typename T, typename U> 
 struct is_same {
@@ -20,8 +19,8 @@ typedef int& LRI;
 typedef int&& RRI;
 
 typedef LRI& r1; CHECK_EQUAL_TYPES(r1, int&);
-typedef const LRI& r2; CHECK_EQUAL_TYPES(r2, int&);
-typedef const LRI&& r3; CHECK_EQUAL_TYPES(r3, int&);
+typedef const LRI& r2; CHECK_EQUAL_TYPES(r2, int&); // expected-warning {{'const' qualifier on reference type 'LRI' (aka 'int &') has no effect}}
+typedef const LRI&& r3; CHECK_EQUAL_TYPES(r3, int&); // expected-warning {{'const' qualifier on reference type 'LRI' (aka 'int &') has no effect}}
 
 typedef RRI& r4; CHECK_EQUAL_TYPES(r4, int&);
 typedef RRI&& r5; CHECK_EQUAL_TYPES(r5, int&&);
index 21e8abc6832b6280e6a44633af89d15fba375446..576f64ee9c311d403a184c6a56cac03fab45272a 100644 (file)
@@ -40,13 +40,13 @@ namespace dr102 { // dr102: yes
 namespace dr106 { // dr106: sup 540
   typedef int &r1;
   typedef r1 &r1;
-  typedef const r1 r1;
-  typedef const r1 &r1;
+  typedef const r1 r1; // expected-warning {{has no effect}}
+  typedef const r1 &r1; // expected-warning {{has no effect}}
 
   typedef const int &r2;
   typedef r2 &r2;
-  typedef const r2 r2;
-  typedef const r2 &r2;
+  typedef const r2 r2; // expected-warning {{has no effect}}
+  typedef const r2 &r2; // expected-warning {{has no effect}}
 }
 
 namespace dr107 { // dr107: yes
index d21412cec0fc0a51696119308d57073a87558b17..b62638b1a4f92b22d41d8e1162e58f1e8a3247ca 100644 (file)
@@ -10,7 +10,7 @@ void foo(int &a) {
 
 typedef int & A;
 
-void g(const A aref) {
+void g(const A aref) { // expected-warning {{'const' qualifier on reference type 'A' (aka 'int &') has no effect}}
 }
 
 int & const X = val; // expected-error {{'const' qualifier may not be applied to a reference}}
index e57e6013e5e76fd1fa39b1f219c061e46805dca2..613b8289fdff74b0e6e51836777e0092de904d65 100644 (file)
@@ -3,7 +3,7 @@
 int && r1(int &&a);
 
 typedef int && R;
-void r2(const R a) {
+void r2(const R a) { // expected-warning {{'const' qualifier on reference type 'R' (aka 'int &&') has no effect}}
   int & &&ar = a; // expected-error{{'ar' declared as a reference to a reference}}
 }
 
index 37fc2a856fd97eda4e75bfeac73efedcc1ade560..cfe7dc1f428b86c96f525e864e399c08b5a22502 100644 (file)
@@ -85,9 +85,19 @@ void test8(int& const,// expected-error{{'const' qualifier may not be applied to
   typedef int& intref;
   typedef intref& intrefref; // C++ DR 106: reference collapsing
 
-  typedef intref const intref_c; // okay. FIXME: how do we verify that this is the same type as intref?
+  typedef intref const intref_c; // expected-warning {{'const' qualifier on reference type 'intref' (aka 'int &') has no effect}}
+  typedef intref_c intref; // ok, same type
+
+  typedef intref volatile intref; // expected-warning {{'volatile' qualifier on reference type 'intref' (aka 'int &') has no effect}}
+  typedef intref _Atomic intref; // expected-warning {{'_Atomic' qualifier on reference type 'intref' (aka 'int &') has no effect}}
+
+  void restrict_ref(__restrict intref); // ok
+  void restrict_ref(int &__restrict); // ok
 }
 
+template<typename T> int const_param(const T) {}
+int const_ref_param = const_param<int&>(const_ref_param); // no-warning
+
 
 class string {
   char *Data;