This way, the behavior of that warning flag is more closely resembles that of GCC.
Fixes PR4802.
Testing:
ninja check-clang-sema check-clang-semacxx
Do note that there is at least one false-negative (see FIXME in tests).
Differential D33102
[clang] Implement -Wcast-qual for C++ lebedev.ri on May 11 2017, 8:49 AM. Authored by
Details
This way, the behavior of that warning flag is more closely resembles that of GCC. Fixes PR4802. Testing: ninja check-clang-sema check-clang-semacxx Do note that there is at least one false-negative (see FIXME in tests).
Diff Detail
Event TimelineComment Actions Add C++-specific tests, handle C++ `*_cast<>()`'s too. FIXME: c++ reference handling. Comment Actions Looks good, do you need someone to commit this? You might also consider requesting commit access: http://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access
Comment Actions No, it's not. First, it still contains "WIP" in the subject. (i shouldn't have even opened this revision until it's ready, but only i have opened it, i have thought about the c++ references/etc)
Comment Actions Do not diagnose const_cast<>(), I think this is it, at least i'm not sure what else to test. @ EVERYONE: please do note that this essentially implements entirely new warning for C++ ! Comment Actions That seems like way more tests than would be ideal - perhaps it can be reduced substantially by considering equivalence classes? (for example, I wouldn't expect more than one test case for C++ const_casts - if the code simply says "if this is a const_cast, don't do anything" then the test should be pretty similar in that regard - if there were more nuance in the selection of which const_casts to warn on, I'd expect more granularity in the testing there - but no need to test all the variations of const_cast that don't warn because you're testing those same variations of c-style cast)
Comment Actions Do not check that we are in C++ before checking that dest type is a lvalue reference.
Comment Actions Still seems like an awful lot more testing than I'd expect for this warning. (eg: testing all the many variations of C++ const_cast - when they all provide basically the same coverage I think, that all const_casts don't warn)
Comment Actions Ok, i removed a bit more of const_cast checks, but unless you insist, i'd think all the rest of the test are needed :) Comment Actions I still feel like that's more testing than would be ideal (does the context of the cast matter? Wether it's dereferenced, a struct member access, assigned, initialized, etc - it doesn't look like it from the code, etc). But sure. Could you also (manually, I guess) confirm that this matches GCC's cast-qual behavior (insofar as the warning fires in the same situations). If there are any deviations, let's chat about them. Comment Actions Looking at the CastsAwayConstness() function in lib/Sema/SemaCast.cpp: https://github.com/llvm-mirror/clang/blob/432ed0e4a6d58f7dda8992a167aad43bc91f76c6/lib/Sema/SemaCast.cpp#L505-L510
Sure.
$ pwd llvm/tools/clang/test $ grep -o "expected-warning" Sema/warn-cast-qual.c | wc -l 14 $ gcc -x c -fsyntax-only -Wcast-qual -c Sema/warn-cast-qual.c 2>&1 | grep ": warning: " | wc -l 14 $ gcc -x c++ -fsyntax-only -Wcast-qual -c Sema/warn-cast-qual.c 2>&1 | grep ": warning: " | wc -l 14 $ grep -o "expected-warning" SemaCXX/warn-cast-qual.cpp | wc -l 39 $ gcc -x c++ -fsyntax-only -Wcast-qual -c SemaCXX/warn-cast-qual.cpp 2>&1 | grep ": warning: " | wc -l 39
2.1. $ gcc -x c -fsyntax-only -Wcast-qual -c Sema/warn-cast-qual.c Sema/warn-cast-qual.c: In function ‘foo’: Sema/warn-cast-qual.c:9:13: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] char *y = (char *)ptr; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}} ^ Sema/warn-cast-qual.c:10:15: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] char **y1 = (char **)ptrptr; // expected-warning {{cast from 'const char *const' to 'char *' drops const qualifier}} ^ Sema/warn-cast-qual.c:11:21: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] const char **y2 = (const char **)ptrptr; // expected-warning {{cast from 'const char *const *' to 'const char **' drops const qualifier}} ^ Sema/warn-cast-qual.c:14:14: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] char *z1 = (char *)(const void *)ptr; // expected-warning {{cast from 'const void *' to 'char *' drops const qualifier}} ^ Sema/warn-cast-qual.c:17:16: warning: cast discards ‘volatile’ qualifier from pointer target type [-Wcast-qual] char *vol2 = (char *)vol; // expected-warning {{cast from 'volatile char *' to 'char *' drops volatile qualifier}} ^ Sema/warn-cast-qual.c:19:17: warning: cast discards ‘const volatile’ qualifier from pointer target type [-Wcast-qual] char *volc2 = (char *)volc; // expected-warning {{cast from 'const volatile char *' to 'char *' drops const and volatile qualifiers}} ^ Sema/warn-cast-qual.c:22:28: warning: to be safe all intermediate pointers in cast from ‘int **’ to ‘const int **’ must be ‘const’ qualified [-Wcast-qual] const int **intptrptrc = (const int **)intptrptr; // expected-warning {{cast from 'int **' to 'const int **' must have all intermediate pointers const qualified}} ^ Sema/warn-cast-qual.c:23:31: warning: to be safe all intermediate pointers in cast from ‘int **’ to ‘volatile int **’ must be ‘const’ qualified [-Wcast-qual] volatile int **intptrptrv = (volatile int **)intptrptr; // expected-warning {{cast from 'int **' to 'volatile int **' must have all intermediate pointers const qualified}} ^ Sema/warn-cast-qual.c:29:23: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] char **charptrptr = (char **)charptrptrc; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}} ^ Sema/warn-cast-qual.c:32:19: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] char *charptr = (char *)constcharptr; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}} ^ Sema/warn-cast-qual.c:33:31: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] const char *constcharptr2 = (char *)constcharptr; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}} ^ Sema/warn-cast-qual.c: In function ‘bar_0’: Sema/warn-cast-qual.c:45:4: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] *(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ Sema/warn-cast-qual.c:46:4: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] *(int *)(&S.b) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ Sema/warn-cast-qual.c: In function ‘bar_1’: Sema/warn-cast-qual.c:58:4: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual] *(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ One thing to note: Sema/warn-cast-qual.c:23:31: warning: to be safe all intermediate pointers in cast from ‘int **’ to ‘volatile int **’ must be ‘const’ qualified [-Wcast-qual] volatile int **intptrptrv = (volatile int **)intptrptr; // expected-warning {{cast from 'int **' to 'volatile int **' must have all intermediate pointers const qualified}} ^ ^ both compilers talk about const qualified, even though the volatile is dropped. $ gcc -x c++ -fsyntax-only -Wcast-qual -c Sema/warn-cast-qual.c Sema/warn-cast-qual.c: In function ‘void foo()’: Sema/warn-cast-qual.c:9:21: warning: cast from type ‘const char* const’ to type ‘char*’ casts away qualifiers [-Wcast-qual] char *y = (char *)ptr; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}} ^~~ Sema/warn-cast-qual.c:10:24: warning: cast from type ‘const char* const*’ to type ‘char**’ casts away qualifiers [-Wcast-qual] char **y1 = (char **)ptrptr; // expected-warning {{cast from 'const char *const' to 'char *' drops const qualifier}} ^~~~~~ Sema/warn-cast-qual.c:11:36: warning: cast from type ‘const char* const*’ to type ‘const char**’ casts away qualifiers [-Wcast-qual] const char **y2 = (const char **)ptrptr; // expected-warning {{cast from 'const char *const *' to 'const char **' drops const qualifier}} ^~~~~~ Sema/warn-cast-qual.c:14:36: warning: cast from type ‘const void*’ to type ‘char*’ casts away qualifiers [-Wcast-qual] char *z1 = (char *)(const void *)ptr; // expected-warning {{cast from 'const void *' to 'char *' drops const qualifier}} ^~~ Sema/warn-cast-qual.c:17:24: warning: cast from type ‘volatile char*’ to type ‘char*’ casts away qualifiers [-Wcast-qual] char *vol2 = (char *)vol; // expected-warning {{cast from 'volatile char *' to 'char *' drops volatile qualifier}} ^~~ Sema/warn-cast-qual.c:19:25: warning: cast from type ‘const volatile char*’ to type ‘char*’ casts away qualifiers [-Wcast-qual] char *volc2 = (char *)volc; // expected-warning {{cast from 'const volatile char *' to 'char *' drops const and volatile qualifiers}} ^~~~ Sema/warn-cast-qual.c:22:42: warning: cast from type ‘int**’ to type ‘const int**’ casts away qualifiers [-Wcast-qual] const int **intptrptrc = (const int **)intptrptr; // expected-warning {{cast from 'int **' to 'const int **' must have all intermediate pointers const qualified}} ^~~~~~~~~ Sema/warn-cast-qual.c:23:48: warning: cast from type ‘int**’ to type ‘volatile int**’ casts away qualifiers [-Wcast-qual] volatile int **intptrptrv = (volatile int **)intptrptr; // expected-warning {{cast from 'int **' to 'volatile int **' must have all intermediate pointers const qualified}} ^~~~~~~~~ Sema/warn-cast-qual.c:29:32: warning: cast from type ‘const char**’ to type ‘char**’ casts away qualifiers [-Wcast-qual] char **charptrptr = (char **)charptrptrc; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}} ^~~~~~~~~~~ Sema/warn-cast-qual.c:32:27: warning: cast from type ‘const char*’ to type ‘char*’ casts away qualifiers [-Wcast-qual] char *charptr = (char *)constcharptr; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}} ^~~~~~~~~~~~ Sema/warn-cast-qual.c:33:39: warning: cast from type ‘const char*’ to type ‘char*’ casts away qualifiers [-Wcast-qual] const char *constcharptr2 = (char *)constcharptr; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}} ^~~~~~~~~~~~ Sema/warn-cast-qual.c: In function ‘void bar_0()’: Sema/warn-cast-qual.c:45:16: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] *(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ Sema/warn-cast-qual.c:46:16: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] *(int *)(&S.b) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ Sema/warn-cast-qual.c: In function ‘void bar_1()’: Sema/warn-cast-qual.c:58:16: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] *(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ 2.3. $ gcc -x c++ -fsyntax-only -Wcast-qual -c SemaCXX/warn-cast-qual.cpp SemaCXX/warn-cast-qual.cpp: In function ‘void foo_0()’: SemaCXX/warn-cast-qual.cpp:24:20: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] int &a2 = (int &)a; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:25:26: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] const int &a3 = (int &)a; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:26:35: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] int &a4 = (int &)((const int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:27:28: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] int &a5 = (int &)((int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:28:34: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] const int &a6 = (int &)((int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:29:41: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] const int &a7 = (int &)((const int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:30:40: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] const int &a8 = (const int &)((int &)a); // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp: In function ‘void foo_1()’: SemaCXX/warn-cast-qual.cpp:39:20: warning: cast from type ‘volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] int &a2 = (int &)a; // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}} ^ SemaCXX/warn-cast-qual.cpp:40:29: warning: cast from type ‘volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] volatile int &a3 = (int &)a; // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}} ^ SemaCXX/warn-cast-qual.cpp:41:38: warning: cast from type ‘volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] int &a4 = (int &)((volatile int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}} ^ SemaCXX/warn-cast-qual.cpp:42:28: warning: cast from type ‘volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] int &a5 = (int &)((int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}} ^ SemaCXX/warn-cast-qual.cpp:43:37: warning: cast from type ‘volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] volatile int &a6 = (int &)((int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}} ^ SemaCXX/warn-cast-qual.cpp:44:47: warning: cast from type ‘volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] volatile int &a7 = (int &)((volatile int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}} ^ SemaCXX/warn-cast-qual.cpp:45:46: warning: cast from type ‘volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] volatile int &a8 = (volatile int &)((int &)a); // expected-warning {{cast from 'volatile int' to 'int &' drops volatile qualifier}} ^ SemaCXX/warn-cast-qual.cpp: In function ‘void foo_2()’: SemaCXX/warn-cast-qual.cpp:54:20: warning: cast from type ‘const volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] int &a2 = (int &)a; // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}} ^ SemaCXX/warn-cast-qual.cpp:55:35: warning: cast from type ‘const volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] const volatile int &a3 = (int &)a; // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}} ^ SemaCXX/warn-cast-qual.cpp:56:44: warning: cast from type ‘const volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] int &a4 = (int &)((const volatile int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}} ^ SemaCXX/warn-cast-qual.cpp:57:28: warning: cast from type ‘const volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] int &a5 = (int &)((int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}} ^ SemaCXX/warn-cast-qual.cpp:58:43: warning: cast from type ‘const volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] const volatile int &a6 = (int &)((int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}} ^ SemaCXX/warn-cast-qual.cpp:59:59: warning: cast from type ‘const volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] const volatile int &a7 = (int &)((const volatile int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}} ^ SemaCXX/warn-cast-qual.cpp:60:58: warning: cast from type ‘const volatile int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] const volatile int &a8 = (const volatile int &)((int &)a); // expected-warning {{cast from 'const volatile int' to 'int &' drops const and volatile qualifiers}} ^ SemaCXX/warn-cast-qual.cpp: In function ‘void bar_0()’: SemaCXX/warn-cast-qual.cpp:67:38: warning: cast from type ‘const int**’ to type ‘int**’ casts away qualifiers [-Wcast-qual] int **a0 = (int **)((const int **)a); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:68:31: warning: cast from type ‘const int**’ to type ‘int**’ casts away qualifiers [-Wcast-qual] int **a1 = (int **)((int **)a); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:73:43: warning: cast from type ‘const int**’ to type ‘int**’ casts away qualifiers [-Wcast-qual] 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}} ^ SemaCXX/warn-cast-qual.cpp:73:44: warning: cast from type ‘int**’ to type ‘const int**’ casts away qualifiers [-Wcast-qual] 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}} ^ SemaCXX/warn-cast-qual.cpp: In function ‘void bar_1()’: SemaCXX/warn-cast-qual.cpp:81:38: warning: cast from type ‘const int**’ to type ‘int**’ casts away qualifiers [-Wcast-qual] int *&a0 = (int *&)((const int *&)a); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:82:31: warning: cast from type ‘const int**’ to type ‘int**’ casts away qualifiers [-Wcast-qual] int *&a1 = (int *&)((int *&)a); // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:87:43: warning: cast from type ‘const int**’ to type ‘int**’ casts away qualifiers [-Wcast-qual] 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}} ^ SemaCXX/warn-cast-qual.cpp:87:44: warning: cast from type ‘int**’ to type ‘const int**’ casts away qualifiers [-Wcast-qual] 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}} ^ SemaCXX/warn-cast-qual.cpp: In function ‘void baz_0()’: SemaCXX/warn-cast-qual.cpp:100:9: warning: cast from type ‘const baz_0()::C*’ to type ‘baz_0()::C*’ casts away qualifiers [-Wcast-qual] ((C &)S).B(); // expected-warning {{cast from 'const C' to 'C &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:101:9: warning: cast from type ‘const baz_0()::C*’ to type ‘baz_0()::C*’ casts away qualifiers [-Wcast-qual] ((C &)S).A(); // expected-warning {{cast from 'const C' to 'C &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:103:10: warning: cast from type ‘const baz_0()::C*’ to type ‘baz_0()::C*’ casts away qualifiers [-Wcast-qual] ((C *)&S)->B(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:104:10: warning: cast from type ‘const baz_0()::C*’ to type ‘baz_0()::C*’ casts away qualifiers [-Wcast-qual] ((C *)&S)->A(); // expected-warning {{cast from 'const C *' to 'C *' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp: In function ‘void baz_1()’: SemaCXX/warn-cast-qual.cpp:119:16: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] (int &)(S.a) = 0; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:122:18: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] *(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:128:16: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] (int &)(S.a) = 0; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:129:16: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] (int &)(S.b) = 0; // expected-warning {{cast from 'const int' to 'int &' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:131:18: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] *(int *)(&S.a) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ SemaCXX/warn-cast-qual.cpp:132:18: warning: cast from type ‘const int*’ to type ‘int*’ casts away qualifiers [-Wcast-qual] *(int *)(&S.b) = 0; // expected-warning {{cast from 'const int *' to 'int *' drops const qualifier}} ^ So to me it seems that for our clang's testcases, both compilers produce the compatible set of warnings... Comment Actions Great, you were right :) $ cat /tmp/tst.c int main() { void* p1 = (void*)"txt"; char* p2 = (char*)"txt"; } $ gcc -x c -Wcast-qual /tmp/tst.c $ gcc -x c++ -Wcast-qual /tmp/tst.c /tmp/tst.c: In function ‘int main()’: /tmp/tst.c:2:21: warning: cast from type ‘const char*’ to type ‘void*’ casts away qualifiers [-Wcast-qual] void* p1 = (void*)"txt"; ^~~~~ /tmp/tst.c:3:21: warning: cast from type ‘const char*’ to type ‘char*’ casts away qualifiers [-Wcast-qual] char* p2 = (char*)"txt"; ^~~~~ $ ./bin/clang -x c -Wcast-qual /tmp/tst.c $ ./bin/clang -x c++ -Wcast-qual /tmp/tst.c /tmp/tst.c:3:21: warning: cast from 'const char *' to 'char *' drops const qualifier [-Wcast-qual] char* p2 = (char*)"txt"; ^ 1 warning generated. So at least, in C++ mode, it should warn on both lines. Comment Actions After further mail exchange, i will proceed to commit this as-is. Comment Actions So i'm trying to analyze that stage2 warning. void test_nop() { unsigned char **ptr1 = 0; void **ptr2 = (void **)ptr1; } void test_bad() { unsigned char **ptr1 = 0; const void **ptr2 = (const void **)ptr1; // expected-warning {{cast from 'unsigned char **' to 'const void **' must have all intermediate pointers const qualified to be safe}} } void test_good0() { unsigned char **ptr1 = 0; void *const *ptr2 = (void *const *)ptr1; } void test_good1() { unsigned char **ptr1 = 0; const void *const *ptr2 = (const void *const *)ptr1; } void test_good2() { unsigned char *const *ptr1 = 0; void *const *ptr2 = (void *const *)ptr1; } void test_good3() { unsigned char *const *ptr1 = 0; const void *const *ptr2 = (const void *const *)ptr1; } void test_good4() { const unsigned char **ptr1 = 0; const void **ptr2 = (const void **)ptr1; } void test_good5() { const unsigned char **ptr1 = 0; const void *const *ptr2 = (const void *const *)ptr1; } void test_good6() { const unsigned char *const *ptr1 = 0; const void *const *ptr2 = (const void *const *)ptr1; } GCC does not warn about such code at all, clang in C mode does warn about only one combination: $ gcc -c /tmp/test.c -Wcast-qual $ echo $? 0 $ clang -c /tmp/test.c -Wcast-qual /tmp/test.c:7:38: warning: cast from 'unsigned char **' to 'const void **' must have all intermediate pointers const qualified to be safe [-Wcast-qual] const void **ptr2 = (const void **)ptr1; // expected-warning {{cast from 'unsigned char **' to 'const void **' must have all intermediate pointers const qualified to be safe}} ^ 1 warning generated. David, you reviewed the original -Wcast-qual patch, does all that ^ make sense? |
Avoid else after return, instead write:
etc...