Skip to content

Commit 7c00219

Browse files
sousajo-ccAaronBallman
authored andcommitted
[clang] trigger -Wcast-qual on functional casts
-Wcast-qual does not trigger on the following code in Clang, but does in GCC. const auto i = 42; using T = int*; auto p = T(&i); The expected behavior is that a functional cast should trigger the warning the same as the equivalent C cast because the meaning is the same, and nothing about the functional cast makes it easier to recognize that a const_cast is occurring. Fixes llvm#62083 Differential Revision: https://reviews.llvm.org/D148276
1 parent 5368c10 commit 7c00219

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ Improvements to Clang's diagnostics
231231
- ``-Wformat`` now recognizes ``%lb`` for the ``printf``/``scanf`` family of
232232
functions.
233233
(`#62247: <https://github.com/llvm/llvm-project/issues/62247>`_).
234+
- ``-Wcast-qual`` now triggers on function-style casts.
235+
(`#62083 <https://github.com/llvm/llvm-project/issues/62083>`_)
234236

235237
Bug Fixes in This Version
236238
-------------------------

clang/lib/Sema/SemaCast.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3332,6 +3332,9 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
33323332
if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr))
33333333
ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));
33343334

3335+
// -Wcast-qual
3336+
DiagnoseCastQual(Op.Self, Op.SrcExpr, Op.DestType);
3337+
33353338
return Op.complete(CXXFunctionalCastExpr::Create(
33363339
Context, Op.ResultType, Op.ValueKind, CastTypeInfo, Op.Kind,
33373340
Op.SrcExpr.get(), &Op.BasePath, CurFPFeatureOverrides(), LPLoc, RPLoc));

clang/test/SemaCXX/warn-cast-qual.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ void foo_0() {
3434
const int &a6 = (int &)((int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
3535
const int &a7 = (int &)((const int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
3636
const int &a8 = (const int &)((int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
37+
38+
using T = int&;
39+
using T2 = const int&;
40+
const int &a11 =T2(a); // no warning
41+
int a22 = T(a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
42+
const int &a33 = T(a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
43+
int &a44 = T(T2(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
44+
int &a55 = T(T(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
45+
const int &a66 = T(T(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
46+
int &a77 = T(T2(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
47+
const int &a88 = T2(T(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
3748
}
3849

3950
void foo_1() {
@@ -49,6 +60,17 @@ void foo_1() {
4960
volatile int &a6 = (int &)((int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
5061
volatile int &a7 = (int &)((volatile int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
5162
volatile int &a8 = (volatile int &)((int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
63+
64+
using T = int&;
65+
using T2 = volatile int&;
66+
volatile int &a11 =T2(a); // no warning
67+
int a22 = T(a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
68+
volatile int &a33 = T(a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
69+
int &a44 = T(T2(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
70+
int &a55 = T(T(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
71+
volatile int &a66 = T(T(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
72+
int &a77 = T(T2(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
73+
volatile int &a88 = T2(T(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
5274
}
5375

5476
void foo_2() {
@@ -64,6 +86,17 @@ void foo_2() {
6486
const volatile int &a6 = (int &)((int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
6587
const volatile int &a7 = (int &)((const volatile int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
6688
const volatile int &a8 = (const volatile int &)((int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
89+
90+
using T = int&;
91+
using T2 = const volatile int&;
92+
const volatile int &a11 =T2(a); // no warning
93+
int a22 = T(a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
94+
const volatile int &a33 = T(a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
95+
int &a44 = T(T2(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
96+
int &a55 = T(T(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
97+
const volatile int &a66 = T(T(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
98+
const volatile int &a77 = T(T2(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
99+
const volatile int &a88 = T2(T(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
67100
}
68101

69102
void bar_0() {
@@ -78,6 +111,16 @@ void bar_0() {
78111

79112
const int **a4 = (const int **)((int **)a); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} expected-warning {{cast from 'int **' to 'const int **' must have all intermediate pointers const qualified to be safe}}
80113
const int **a5 = (const int **)((const int **)a); // no warning
114+
115+
using T = int**;
116+
using T2 = const int**;
117+
118+
int **a00 = T(T2(a)) ; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
119+
int **a11 = T(T(a)); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
120+
121+
const int **a44 = T2(T(a)); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} expected-warning {{cast from 'T' (aka 'int **') to 'T2' (aka 'const int **') must have all intermediate pointers const qualified to be safe}}
122+
const int **a55 = T2(T2(a)); // no warning
123+
81124
}
82125

83126
void bar_1() {
@@ -92,6 +135,15 @@ void bar_1() {
92135

93136
const int *&a4 = (const int *&)((int *&)a); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} expected-warning {{cast from 'int *' to 'const int *&' must have all intermediate pointers const qualified to be safe}}
94137
const int *&a5 = (const int *&)((const int *&)a); // no warning
138+
139+
using T = int*&;
140+
using T2 = const int*&;
141+
142+
int *&a00 = T(T2(a)); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
143+
int *&a11 = T(T(a)); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
144+
145+
const int *&a44 = T2(T(a)); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} expected-warning {{cast from 'int *' to 'T2' (aka 'const int *&') must have all intermediate pointers const qualified to be safe}}
146+
const int *&a55 = T2(T2(a)); // no warning
95147
}
96148

97149
void baz_0() {
@@ -108,6 +160,14 @@ void baz_0() {
108160

109161
((C *)&S)->B(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}}
110162
((C *)&S)->A(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}}
163+
164+
using T = C&;
165+
using T2 = C*;
166+
T(S).B(); // expected-warning {{cast from 'const C' to 'C &' drops const qualifier}}
167+
T(S).A(); // expected-warning {{cast from 'const C' to 'C &' drops const qualifier}}
168+
169+
T2(&S)->B(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}}
170+
T2(&S)->A(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}}
111171
}
112172

113173
void baz_1() {
@@ -127,6 +187,14 @@ void baz_1() {
127187

128188
*(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
129189
*(int *)(&S.b) = 0; // no warning
190+
191+
using T = int&;
192+
using T2 = int*;
193+
T(S.a) = 0; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
194+
T(S.b) = 0; // no warning
195+
196+
*T2(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
197+
*T2(&S.b) = 0; // no warning
130198
}
131199
{
132200
const C S;
@@ -136,5 +204,39 @@ void baz_1() {
136204

137205
*(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
138206
*(int *)(&S.b) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
207+
208+
using T = int&;
209+
using T2 = int*;
210+
T(S.a) = 0; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
211+
T(S.b) = 0; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
212+
213+
*T2(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
214+
*T2(&S.b) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
139215
}
140216
}
217+
218+
void qux_0() {
219+
const auto i = 42;
220+
using T = int*;
221+
auto p = T(&i); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
222+
223+
const auto i2 = 42;
224+
using T2 = const int*;
225+
auto p2 = T2(&i2);
226+
227+
volatile auto i3 = 42;
228+
using T3= int*;
229+
auto p3 = T3(&i3); // expected-warning {{cast from 'volatile int *' to 'int *' drops volatile qualifier}}
230+
231+
volatile auto i4 = 42;
232+
using T4 = volatile int*;
233+
auto p4 = T4(&i4);
234+
235+
const volatile auto i5 = 42;
236+
using T5= int*;
237+
auto p5 = T5(&i5); // expected-warning {{cast from 'const volatile int *' to 'int *' drops const and volatile qualifiers}}
238+
239+
const volatile auto i6 = 42;
240+
using T6= const volatile int*;
241+
auto p6 = T6(&i6);
242+
}

0 commit comments

Comments
 (0)