V1069. Do not concatenate string literals with different prefixes.
The analyzer found a code fragment where two concatenated strings have different encoding prefixes.
Take a look at this example:
// Until C99/C++11
L"Hello, this is my special "
"string literal with interesting behavior";
Prior to the C11/C++11 standards, C and C++ provided only two kinds of string literals:
- a "narrow" string literal - " s-char-sequence "
- a "wide" string literal - L" s-char-sequence "
In languages prior to C99 or C++11, concatenating string literals with different prefixes leads to undefined behavior. This triggers the analyzer to issue a first-level warning. Below is the correct code:
// Until C99/C++11
L"Hello, this is my special "
L"string literal with defined behavior";
Starting with C99 and C++11 this behavior is defined. If one of string literals has a prefix, and the second one does not, the resulting string literal has the first string's prefix. In this case the analyzer issues no warnings:
// Since C99/C++11
L"Hello, this is my special "
"string literal with "
"defined behavior";
C11/C++11 and newer language versions provide three more prefixed string literals:
- UTF-8 string literal - u8" s-char-sequence "
- 16-bit wide string literal - u" s-char-sequence "
- 32-bit wide string literal - U" s-char-sequence "
Concatenating UTF-8 and any "wide" string literal leads to a compile-time error. In this case the analyzer does not issue a warning.
L"Hello, this is my special "
u8"string literal that won't compile"; // compile-time error
Any other combinations of prefixed string literals lead to undefined behavior. In these cases, the analyzer issues second-level warnings:
// Until C11/C++11
L"Hello, this is my special "
u"string literal with implementation-defined behavior";
L"Hello, this is my special "
U"string literal with implementation-defined behavior";
u"Hello, this is my special "
U"string literal with implementation-defined behavior";
When one "narrow" string literal is concatenated with two or more prefixed string literals, the analyzer issues third-level warnings:
template <typename T>
void foo(T &&val) { .... }
....
void bar()
{
foo("This" L"is" "strange");
foo(L"This" "is" L"strange");
}
Though in modern standards this behavior is defined, such code cultivates errors and we recommend refactoring.