Skip to content

Commit

Permalink
[clang] trigger -Wcast-qual on functional casts
Browse files Browse the repository at this point in the history
-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 #62083
Differential Revision: https://reviews.llvm.org/D148276
  • Loading branch information
sousajo-cc authored and AaronBallman committed Apr 21, 2023
1 parent 5368c10 commit 7c00219
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Expand Up @@ -231,6 +231,8 @@ Improvements to Clang's diagnostics
- ``-Wformat`` now recognizes ``%lb`` for the ``printf``/``scanf`` family of
functions.
(`#62247: <https://github.com/llvm/llvm-project/issues/62247>`_).
- ``-Wcast-qual`` now triggers on function-style casts.
(`#62083 <https://github.com/llvm/llvm-project/issues/62083>`_)

Bug Fixes in This Version
-------------------------
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaCast.cpp
Expand Up @@ -3332,6 +3332,9 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr))
ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));

// -Wcast-qual
DiagnoseCastQual(Op.Self, Op.SrcExpr, Op.DestType);

return Op.complete(CXXFunctionalCastExpr::Create(
Context, Op.ResultType, Op.ValueKind, CastTypeInfo, Op.Kind,
Op.SrcExpr.get(), &Op.BasePath, CurFPFeatureOverrides(), LPLoc, RPLoc));
Expand Down
102 changes: 102 additions & 0 deletions clang/test/SemaCXX/warn-cast-qual.cpp
Expand Up @@ -34,6 +34,17 @@ void foo_0() {
const int &a6 = (int &)((int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
const int &a7 = (int &)((const int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
const int &a8 = (const int &)((int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}

using T = int&;
using T2 = const int&;
const int &a11 =T2(a); // no warning
int a22 = T(a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
const int &a33 = T(a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
int &a44 = T(T2(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
int &a55 = T(T(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
const int &a66 = T(T(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
int &a77 = T(T2(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
const int &a88 = T2(T(a)); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
}

void foo_1() {
Expand All @@ -49,6 +60,17 @@ void foo_1() {
volatile int &a6 = (int &)((int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
volatile int &a7 = (int &)((volatile int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
volatile int &a8 = (volatile int &)((int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}

using T = int&;
using T2 = volatile int&;
volatile int &a11 =T2(a); // no warning
int a22 = T(a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
volatile int &a33 = T(a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
int &a44 = T(T2(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
int &a55 = T(T(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
volatile int &a66 = T(T(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
int &a77 = T(T2(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
volatile int &a88 = T2(T(a)); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}}
}

void foo_2() {
Expand All @@ -64,6 +86,17 @@ void foo_2() {
const volatile int &a6 = (int &)((int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
const volatile int &a7 = (int &)((const volatile int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
const volatile int &a8 = (const volatile int &)((int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}

using T = int&;
using T2 = const volatile int&;
const volatile int &a11 =T2(a); // no warning
int a22 = T(a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
const volatile int &a33 = T(a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
int &a44 = T(T2(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
int &a55 = T(T(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
const volatile int &a66 = T(T(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
const volatile int &a77 = T(T2(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
const volatile int &a88 = T2(T(a)); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}}
}

void bar_0() {
Expand All @@ -78,6 +111,16 @@ void bar_0() {

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}}
const int **a5 = (const int **)((const int **)a); // no warning

using T = int**;
using T2 = const int**;

int **a00 = T(T2(a)) ; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
int **a11 = T(T(a)); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}

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}}
const int **a55 = T2(T2(a)); // no warning

}

void bar_1() {
Expand All @@ -92,6 +135,15 @@ void bar_1() {

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}}
const int *&a5 = (const int *&)((const int *&)a); // no warning

using T = int*&;
using T2 = const int*&;

int *&a00 = T(T2(a)); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
int *&a11 = T(T(a)); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}

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}}
const int *&a55 = T2(T2(a)); // no warning
}

void baz_0() {
Expand All @@ -108,6 +160,14 @@ void baz_0() {

((C *)&S)->B(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}}
((C *)&S)->A(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}}

using T = C&;
using T2 = C*;
T(S).B(); // expected-warning {{cast from 'const C' to 'C &' drops const qualifier}}
T(S).A(); // expected-warning {{cast from 'const C' to 'C &' drops const qualifier}}

T2(&S)->B(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}}
T2(&S)->A(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}}
}

void baz_1() {
Expand All @@ -127,6 +187,14 @@ void baz_1() {

*(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
*(int *)(&S.b) = 0; // no warning

using T = int&;
using T2 = int*;
T(S.a) = 0; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
T(S.b) = 0; // no warning

*T2(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
*T2(&S.b) = 0; // no warning
}
{
const C S;
Expand All @@ -136,5 +204,39 @@ void baz_1() {

*(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
*(int *)(&S.b) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}

using T = int&;
using T2 = int*;
T(S.a) = 0; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}
T(S.b) = 0; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}}

*T2(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
*T2(&S.b) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
}
}

void qux_0() {
const auto i = 42;
using T = int*;
auto p = T(&i); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}}

const auto i2 = 42;
using T2 = const int*;
auto p2 = T2(&i2);

volatile auto i3 = 42;
using T3= int*;
auto p3 = T3(&i3); // expected-warning {{cast from 'volatile int *' to 'int *' drops volatile qualifier}}

volatile auto i4 = 42;
using T4 = volatile int*;
auto p4 = T4(&i4);

const volatile auto i5 = 42;
using T5= int*;
auto p5 = T5(&i5); // expected-warning {{cast from 'const volatile int *' to 'int *' drops const and volatile qualifiers}}

const volatile auto i6 = 42;
using T6= const volatile int*;
auto p6 = T6(&i6);
}

0 comments on commit 7c00219

Please sign in to comment.