Skip to content

Commit dd85c6c

Browse files
authored
[Sema] Add -Wc++11-narrowing-const-reference (#76094)
#75332 diagnosed narrowing involving const reference. Our depot has hundreds if not thousands of breakages (#75332 (comment)). Add a subgroup of -Wc++11-narrowing to help users gradually fix their issues without regressing the existing -Wc++11-narrowing diagnostics.
1 parent 4b69689 commit dd85c6c

File tree

5 files changed

+44
-15
lines changed

5 files changed

+44
-15
lines changed

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,8 @@ def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
348348
CXXPre20CompatPedantic,
349349
CXXPre23CompatPedantic]>;
350350

351-
def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
351+
def CXX11NarrowingConstReference : DiagGroup<"c++11-narrowing-const-reference">;
352+
def CXX11Narrowing : DiagGroup<"c++11-narrowing", [CXX11NarrowingConstReference]>;
352353

353354
def CXX11WarnInconsistentOverrideDestructor :
354355
DiagGroup<"inconsistent-missing-destructor-override">;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6158,12 +6158,24 @@ def err_illegal_initializer_type : Error<"illegal initializer type %0">;
61586158
def ext_init_list_type_narrowing : ExtWarn<
61596159
"type %0 cannot be narrowed to %1 in initializer list">,
61606160
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
6161+
// *_narrowing_const_reference diagnostics have the same messages, but are
6162+
// controlled by -Wc++11-narrowing-const-reference for narrowing involving a
6163+
// const reference.
6164+
def ext_init_list_type_narrowing_const_reference : ExtWarn<
6165+
"type %0 cannot be narrowed to %1 in initializer list">,
6166+
InGroup<CXX11NarrowingConstReference>, DefaultError, SFINAEFailure;
61616167
def ext_init_list_variable_narrowing : ExtWarn<
61626168
"non-constant-expression cannot be narrowed from type %0 to %1 in "
61636169
"initializer list">, InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
6170+
def ext_init_list_variable_narrowing_const_reference : ExtWarn<
6171+
"non-constant-expression cannot be narrowed from type %0 to %1 in "
6172+
"initializer list">, InGroup<CXX11NarrowingConstReference>, DefaultError, SFINAEFailure;
61646173
def ext_init_list_constant_narrowing : ExtWarn<
61656174
"constant expression evaluates to %0 which cannot be narrowed to type %1">,
61666175
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
6176+
def ext_init_list_constant_narrowing_const_reference : ExtWarn<
6177+
"constant expression evaluates to %0 which cannot be narrowed to type %1">,
6178+
InGroup<CXX11NarrowingConstReference>, DefaultError, SFINAEFailure;
61676179
def warn_init_list_type_narrowing : Warning<
61686180
"type %0 cannot be narrowed to %1 in initializer list in C++11">,
61696181
InGroup<CXX11Narrowing>, DefaultIgnore;

clang/lib/Sema/SemaInit.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10411,40 +10411,53 @@ static void DiagnoseNarrowingInInitList(Sema &S,
1041110411
// No narrowing occurred.
1041210412
return;
1041310413

10414-
case NK_Type_Narrowing:
10414+
case NK_Type_Narrowing: {
1041510415
// This was a floating-to-integer conversion, which is always considered a
1041610416
// narrowing conversion even if the value is a constant and can be
1041710417
// represented exactly as an integer.
10418-
S.Diag(PostInit->getBeginLoc(), NarrowingErrs(S.getLangOpts())
10419-
? diag::ext_init_list_type_narrowing
10420-
: diag::warn_init_list_type_narrowing)
10418+
QualType T = EntityType.getNonReferenceType();
10419+
S.Diag(PostInit->getBeginLoc(),
10420+
NarrowingErrs(S.getLangOpts())
10421+
? (T == EntityType
10422+
? diag::ext_init_list_type_narrowing
10423+
: diag::ext_init_list_type_narrowing_const_reference)
10424+
: diag::warn_init_list_type_narrowing)
1042110425
<< PostInit->getSourceRange()
1042210426
<< PreNarrowingType.getLocalUnqualifiedType()
10423-
<< EntityType.getNonReferenceType().getLocalUnqualifiedType();
10427+
<< T.getLocalUnqualifiedType();
1042410428
break;
10429+
}
1042510430

10426-
case NK_Constant_Narrowing:
10431+
case NK_Constant_Narrowing: {
1042710432
// A constant value was narrowed.
10433+
QualType T = EntityType.getNonReferenceType();
1042810434
S.Diag(PostInit->getBeginLoc(),
1042910435
NarrowingErrs(S.getLangOpts())
10430-
? diag::ext_init_list_constant_narrowing
10436+
? (T == EntityType
10437+
? diag::ext_init_list_constant_narrowing
10438+
: diag::ext_init_list_constant_narrowing_const_reference)
1043110439
: diag::warn_init_list_constant_narrowing)
1043210440
<< PostInit->getSourceRange()
1043310441
<< ConstantValue.getAsString(S.getASTContext(), ConstantType)
1043410442
<< EntityType.getNonReferenceType().getLocalUnqualifiedType();
1043510443
break;
10444+
}
1043610445

10437-
case NK_Variable_Narrowing:
10446+
case NK_Variable_Narrowing: {
1043810447
// A variable's value may have been narrowed.
10448+
QualType T = EntityType.getNonReferenceType();
1043910449
S.Diag(PostInit->getBeginLoc(),
1044010450
NarrowingErrs(S.getLangOpts())
10441-
? diag::ext_init_list_variable_narrowing
10451+
? (T == EntityType
10452+
? diag::ext_init_list_variable_narrowing
10453+
: diag::ext_init_list_variable_narrowing_const_reference)
1044210454
: diag::warn_init_list_variable_narrowing)
1044310455
<< PostInit->getSourceRange()
1044410456
<< PreNarrowingType.getLocalUnqualifiedType()
1044510457
<< EntityType.getNonReferenceType().getLocalUnqualifiedType();
1044610458
break;
1044710459
}
10460+
}
1044810461

1044910462
SmallString<128> StaticCast;
1045010463
llvm::raw_svector_ostream OS(StaticCast);

clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -triple x86_64-apple-macosx10.6.7 -verify %s
2+
// The following narrowing does not involve const references, so
3+
// -Wno-c++11-narrowing-const-reference does not suppress the errors.
4+
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -triple x86_64-apple-macosx10.6.7 -Wno-c++11-narrowing-const-reference -verify %s
25

36
// Verify that narrowing conversions in initializer lists cause errors in C++0x
47
// mode.

clang/test/SemaCXX/GH63151.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify %s
2-
1+
// RUN: %clang_cc1 -fsyntax-only -verify=expected,narrowing %s
2+
// RUN: %clang_cc1 -fsyntax-only -Wno-c++11-narrowing-const-reference -verify %s
33

44
struct A { A(const unsigned &x) {} };
55

66
void foo(int p) {
7-
A a { -1 }; // expected-error {{constant expression evaluates to -1 which cannot be narrowed to type 'unsigned int'}}
7+
A a { -1 }; // narrowing-error {{constant expression evaluates to -1 which cannot be narrowed to type 'unsigned int'}}
88
A b { 0 };
9-
A c { p }; // expected-error {{non-constant-expression cannot be narrowed from type 'int' to 'unsigned int' in initializer list}}
10-
A d { 0.5 }; // expected-error {{type 'double' cannot be narrowed to 'unsigned int' in initializer list}}
9+
A c { p }; // narrowing-error {{non-constant-expression cannot be narrowed from type 'int' to 'unsigned int' in initializer list}}
10+
A d { 0.5 }; // narrowing-error {{type 'double' cannot be narrowed to 'unsigned int' in initializer list}}
1111
// expected-warning@-1 {{implicit conversion from 'double' to 'unsigned int' changes value from 0.5 to 0}}
1212
}

0 commit comments

Comments
 (0)