diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -210,6 +210,10 @@ - ``-Wenum-conversion`` now warns on converting a signed enum of one type to an unsigned enum of a different type (or vice versa) rather than ``-Wsign-conversion``. +- Added the ``-Wunreachable-code-generic-assoc`` diagnostic flag (grouped under + the ``-Wunreachable-code`` flag) which is enabled by default and warns the + user about ``_Generic`` selection associations which are unreachable because + the type specified is an array type or a qualified type. Non-comprehensive list of changes in this release ------------------------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -843,9 +843,11 @@ // def UnreachableCodeLoopIncrement : DiagGroup<"unreachable-code-loop-increment">; def UnreachableCodeFallthrough : DiagGroup<"unreachable-code-fallthrough">; +def UnreachableCodeGenericAssoc : DiagGroup<"unreachable-code-generic-assoc">; def UnreachableCode : DiagGroup<"unreachable-code", [UnreachableCodeLoopIncrement, - UnreachableCodeFallthrough]>; + UnreachableCodeFallthrough, + UnreachableCodeGenericAssoc]>; def UnreachableCodeBreak : DiagGroup<"unreachable-code-break">; def UnreachableCodeReturn : DiagGroup<"unreachable-code-return">; def UnreachableCodeAggressive : DiagGroup<"unreachable-code-aggressive", diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -693,6 +693,10 @@ InGroup, DefaultIgnore; def note_unreachable_silence : Note< "silence by adding parentheses to mark code as explicitly dead">; +def warn_unreachable_association : Warning< + "due to lvalue conversion of the controlling expression, association of type " + "%0 will never be selected because it is %select{of array type|qualified}1">, + InGroup; /// Built-in functions. def ext_implicit_lib_function_decl : ExtWarn< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1685,6 +1685,25 @@ D = diag::err_assoc_type_nonobject; else if (Types[i]->getType()->isVariablyModifiedType()) D = diag::err_assoc_type_variably_modified; + else { + // Because the controlling expression undergoes lvalue conversion, + // array conversion, and function conversion, an association which is + // of array type, function type, or is qualified can never be + // reached. We will warn about this so users are less surprised by + // the unreachable association. However, we don't have to handle + // function types; that's not an object type, so it's handled above. + unsigned Reason = 0; + QualType QT = Types[i]->getType(); + if (QT->isArrayType()) + Reason = 1; + else if (QT.hasQualifiers()) + Reason = 2; + + if (Reason) + Diag(Types[i]->getTypeLoc().getBeginLoc(), + diag::warn_unreachable_association) + << QT << (Reason - 1); + } if (D != 0) { Diag(Types[i]->getTypeLoc().getBeginLoc(), D) diff --git a/clang/test/Sema/generic-selection.c b/clang/test/Sema/generic-selection.c --- a/clang/test/Sema/generic-selection.c +++ b/clang/test/Sema/generic-selection.c @@ -57,3 +57,14 @@ _Generic(n++, int : 0) // expected-error {{cannot increment value of type 'int ()'}} ext-warning {{'_Generic' is a C11 extension}} ), int : 0); } + +void unreachable_associations(const int i) { + _Static_assert( // ext-warning {{'_Static_assert' is a C11 extension}} + _Generic(i, // ext-warning {{'_Generic' is a C11 extension}} + const int : 1, // expected-warning {{due to lvalue conversion of the controlling expression, association of type 'const int' will never be selected because it is qualified}} + volatile int : 2, // expected-warning {{due to lvalue conversion of the controlling expression, association of type 'volatile int' will never be selected because it is qualified}} + int[12] : 3, // expected-warning {{due to lvalue conversion of the controlling expression, association of type 'int[12]' will never be selected because it is of array type}} + int : 4, + default : 5 + ) == 4, "we had better pick int!"); +}