Skip to content

Commit cd09f21

Browse files
[clang] Report narrowing conversions with const references (#75332)
Fixes #63151 --------- Co-authored-by: Erich Keane <[email protected]>
1 parent 1fea712 commit cd09f21

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,9 @@ Improvements to Clang's diagnostics
521521
| ~~~~~~~^~~~~
522522
523523
- Clang now diagnoses definitions of friend function specializations, e.g. ``friend void f<>(int) {}``.
524+
- Clang now diagnoses narrowing conversions involving const references.
525+
(`#63151: <https://github.com/llvm/llvm-project/issues/63151>`_).
526+
524527

525528
Improvements to Clang's time-trace
526529
----------------------------------

clang/lib/Sema/SemaInit.cpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4432,7 +4432,8 @@ static void TryReferenceInitializationCore(Sema &S,
44324432
Qualifiers T1Quals,
44334433
QualType cv2T2, QualType T2,
44344434
Qualifiers T2Quals,
4435-
InitializationSequence &Sequence);
4435+
InitializationSequence &Sequence,
4436+
bool TopLevelOfInitList);
44364437

44374438
static void TryValueInitialization(Sema &S,
44384439
const InitializedEntity &Entity,
@@ -4486,7 +4487,8 @@ static void TryReferenceListInitialization(Sema &S,
44864487
if (RefRelationship >= Sema::Ref_Related) {
44874488
// Try to bind the reference here.
44884489
TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1,
4489-
T1Quals, cv2T2, T2, T2Quals, Sequence);
4490+
T1Quals, cv2T2, T2, T2Quals, Sequence,
4491+
/*TopLevelOfInitList=*/true);
44904492
if (Sequence)
44914493
Sequence.RewrapReferenceInitList(cv1T1, InitList);
44924494
return;
@@ -4945,11 +4947,11 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
49454947
Expr *CurInitExpr);
49464948

49474949
/// Attempt reference initialization (C++0x [dcl.init.ref])
4948-
static void TryReferenceInitialization(Sema &S,
4949-
const InitializedEntity &Entity,
4950+
static void TryReferenceInitialization(Sema &S, const InitializedEntity &Entity,
49504951
const InitializationKind &Kind,
49514952
Expr *Initializer,
4952-
InitializationSequence &Sequence) {
4953+
InitializationSequence &Sequence,
4954+
bool TopLevelOfInitList) {
49534955
QualType DestType = Entity.getType();
49544956
QualType cv1T1 = DestType->castAs<ReferenceType>()->getPointeeType();
49554957
Qualifiers T1Quals;
@@ -4967,7 +4969,8 @@ static void TryReferenceInitialization(Sema &S,
49674969

49684970
// Delegate everything else to a subfunction.
49694971
TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1,
4970-
T1Quals, cv2T2, T2, T2Quals, Sequence);
4972+
T1Quals, cv2T2, T2, T2Quals, Sequence,
4973+
TopLevelOfInitList);
49714974
}
49724975

49734976
/// Determine whether an expression is a non-referenceable glvalue (one to
@@ -4990,7 +4993,8 @@ static void TryReferenceInitializationCore(Sema &S,
49904993
Qualifiers T1Quals,
49914994
QualType cv2T2, QualType T2,
49924995
Qualifiers T2Quals,
4993-
InitializationSequence &Sequence) {
4996+
InitializationSequence &Sequence,
4997+
bool TopLevelOfInitList) {
49944998
QualType DestType = Entity.getType();
49954999
SourceLocation DeclLoc = Initializer->getBeginLoc();
49965000

@@ -5264,7 +5268,8 @@ static void TryReferenceInitializationCore(Sema &S,
52645268
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
52655269
return;
52665270
} else {
5267-
Sequence.AddConversionSequenceStep(ICS, TempEntity.getType());
5271+
Sequence.AddConversionSequenceStep(ICS, TempEntity.getType(),
5272+
TopLevelOfInitList);
52685273
}
52695274

52705275
// [...] If T1 is reference-related to T2, cv1 must be the
@@ -6228,7 +6233,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
62286233
else if (isa<InitListExpr>(Args[0]))
62296234
SetFailed(FK_ParenthesizedListInitForReference);
62306235
else
6231-
TryReferenceInitialization(S, Entity, Kind, Args[0], *this);
6236+
TryReferenceInitialization(S, Entity, Kind, Args[0], *this,
6237+
TopLevelOfInitList);
62326238
return;
62336239
}
62346240

@@ -10431,7 +10437,7 @@ static void DiagnoseNarrowingInInitList(Sema &S,
1043110437
: diag::warn_init_list_type_narrowing)
1043210438
<< PostInit->getSourceRange()
1043310439
<< PreNarrowingType.getLocalUnqualifiedType()
10434-
<< EntityType.getLocalUnqualifiedType();
10440+
<< EntityType.getNonReferenceType().getLocalUnqualifiedType();
1043510441
break;
1043610442

1043710443
case NK_Constant_Narrowing:
@@ -10442,7 +10448,7 @@ static void DiagnoseNarrowingInInitList(Sema &S,
1044210448
: diag::warn_init_list_constant_narrowing)
1044310449
<< PostInit->getSourceRange()
1044410450
<< ConstantValue.getAsString(S.getASTContext(), ConstantType)
10445-
<< EntityType.getLocalUnqualifiedType();
10451+
<< EntityType.getNonReferenceType().getLocalUnqualifiedType();
1044610452
break;
1044710453

1044810454
case NK_Variable_Narrowing:
@@ -10453,7 +10459,7 @@ static void DiagnoseNarrowingInInitList(Sema &S,
1045310459
: diag::warn_init_list_variable_narrowing)
1045410460
<< PostInit->getSourceRange()
1045510461
<< PreNarrowingType.getLocalUnqualifiedType()
10456-
<< EntityType.getLocalUnqualifiedType();
10462+
<< EntityType.getNonReferenceType().getLocalUnqualifiedType();
1045710463
break;
1045810464
}
1045910465

clang/test/SemaCXX/GH63151.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
3+
4+
struct A { A(const unsigned &x) {} };
5+
6+
void foo(int p) {
7+
A a { -1 }; // expected-error {{constant expression evaluates to -1 which cannot be narrowed to type 'unsigned int'}}
8+
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}}
11+
// expected-warning@-1 {{implicit conversion from 'double' to 'unsigned int' changes value from 0.5 to 0}}
12+
}

0 commit comments

Comments
 (0)