From: Richard Smith Date: Wed, 19 Feb 2014 00:13:27 +0000 (+0000) Subject: PR13110: Add a -Wignored-qualifiers warning when ignoring a const, volatile, or X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d970a31d7c57aa3a28e2400d547126fbe44e8958;p=clang PR13110: Add a -Wignored-qualifiers warning when ignoring a const, volatile, or _Atomic qualifier applied to a reference type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201620 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index af3445b16f..e4d0f941b7 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3787,6 +3787,9 @@ def warn_typecheck_negative_array_new_size : Warning<"array size is negative">, InGroup; 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; 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< diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index a75327c9d1..f202af489b 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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 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 diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp index cd623df71e..0f76e1f3c7 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -// expected-no-diagnostics template 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&&); diff --git a/test/CXX/drs/dr1xx.cpp b/test/CXX/drs/dr1xx.cpp index 21e8abc683..576f64ee9c 100644 --- a/test/CXX/drs/dr1xx.cpp +++ b/test/CXX/drs/dr1xx.cpp @@ -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 diff --git a/test/Parser/cxx-reference.cpp b/test/Parser/cxx-reference.cpp index d21412cec0..b62638b1a4 100644 --- a/test/Parser/cxx-reference.cpp +++ b/test/Parser/cxx-reference.cpp @@ -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}} diff --git a/test/Parser/cxx0x-rvalue-reference.cpp b/test/Parser/cxx0x-rvalue-reference.cpp index e57e6013e5..613b8289fd 100644 --- a/test/Parser/cxx0x-rvalue-reference.cpp +++ b/test/Parser/cxx0x-rvalue-reference.cpp @@ -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}} } diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp index 37fc2a856f..cfe7dc1f42 100644 --- a/test/SemaCXX/references.cpp +++ b/test/SemaCXX/references.cpp @@ -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 int const_param(const T) {} +int const_ref_param = const_param(const_ref_param); // no-warning + class string { char *Data;