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

llvm-svn: 237383
This commit is contained in:
Richard Smith 2015-05-14 19:10:42 +00:00
parent 2d5814c2d4
commit a462b4c9ac
4 changed files with 64 additions and 45 deletions

View File

@ -4155,8 +4155,11 @@ def err_typecheck_negative_array_size : Error<"array size is negative">;
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>;

View File

@ -688,6 +688,33 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
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(TypeProcessingState &state) {
// 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(TypeProcessingState &state) {
// 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

View File

@ -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

View File

@ -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>