blob: 8818192eb45435990b96b6ceba50444cd86194d2 [file] [log] [blame]
/* { dg-do compile } */
/* { dg-options "-O -fdiagnostics-show-caret" } */
/* This is a collection of unittests for ranges within string literals,
using diagnostic_plugin_test_string_literals, which handles
"__emit_string_literal_range" by generating a warning at the given
subset of a string literal.
The indices are 0-based. It's easiest to verify things using string
literals that are runs of 0-based digits (to avoid having to count
characters).
LITERAL is a const void * to allow testing the various kinds of wide
string literal, rather than just const char *. */
extern void __emit_string_literal_range (const void *literal, int caret_idx,
int start_idx, int end_idx);
void
test_simple_string_literal (void)
{
__emit_string_literal_range ("0123456789", /* { dg-warning "range" } */
6, 6, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("0123456789",
^~
{ dg-end-multiline-output "" } */
}
void
test_concatenated_string_literal (void)
{
__emit_string_literal_range ("01234" "56789", /* { dg-warning "range" } */
4, 3, 6);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234" "56789",
~^~~~~~
{ dg-end-multiline-output "" } */
}
void
test_multiline_string_literal (void)
{
__emit_string_literal_range ("01234" /* { dg-warning "range" } */
"56789",
4, 3, 6);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234"
~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"56789",
~~~
{ dg-end-multiline-output "" } */
/* FIXME: why does the above need three trailing spaces? */
}
/* Tests of various unicode encodings.
Digits 0 through 9 are unicode code points:
U+0030 DIGIT ZERO
...
U+0039 DIGIT NINE
However, these are not always valid as UCN (see the comment in
libcpp/charset.c:_cpp_valid_ucn).
Hence we need to test UCN using an alternative unicode
representation of numbers; let's use Roman numerals,
(though these start at one, not zero):
U+2170 SMALL ROMAN NUMERAL ONE
...
U+2174 SMALL ROMAN NUMERAL FIVE ("v")
U+2175 SMALL ROMAN NUMERAL SIX ("vi")
...
U+2178 SMALL ROMAN NUMERAL NINE. */
void
test_hex (void)
{
/* Digits 0-9, expressing digit 5 in ASCII as "\x35"
and with a space in place of digit 6, to terminate the escaped
hex code. */
__emit_string_literal_range ("01234\x35 789", /* { dg-warning "range" } */
4, 3, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234\x35 789"
~^~~~~~~
{ dg-end-multiline-output "" } */
}
void
test_oct (void)
{
/* Digits 0-9, expressing digit 5 in ASCII as "\065"
and with a space in place of digit 6, to terminate the escaped
octal code. */
__emit_string_literal_range ("01234\065 789", /* { dg-warning "range" } */
4, 3, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234\065 789"
~^~~~~~~
{ dg-end-multiline-output "" } */
}
void
test_multiple (void)
{
/* Digits 0-9, expressing digit 5 in ASCII as hex "\x35"
digit 6 in ASCII as octal "\066", concatenating multiple strings. */
__emit_string_literal_range ("01234" "\x35" "\066" "789", /* { dg-warning "range" } */
5, 3, 8);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234" "\x35" "\066" "789",
~~~~~~^~~~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
void
test_ucn4 (void)
{
/* Digits 0-9, expressing digits 5 and 6 as Roman numerals expressed
as UCN 4.
The resulting string is encoded as UTF-8. Most of the digits are 1 byte
each, but digits 5 and 6 are encoded with 3 bytes each.
Hence to underline digits 4-7 we need to underling using bytes 4-11 in
the UTF-8 encoding. */
__emit_string_literal_range ("01234\u2174\u2175789", /* { dg-warning "range" } */
5, 4, 11);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234\u2174\u2175789",
~^~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
void
test_ucn8 (void)
{
/* Digits 0-9, expressing digits 5 and 6 as Roman numerals as UCN 8.
The resulting string is the same as as in test_ucn4 above, and hence
has the same UTF-8 encoding, and so we again need to underline bytes
4-11 in the UTF-8 encoding in order to underline digits 4-7. */
__emit_string_literal_range ("01234\U00002174\U00002175789", /* { dg-warning "range" } */
5, 4, 11);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234\U00002174\U00002175789",
~^~~~~~~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
void
test_u8 (void)
{
/* Digits 0-9. */
__emit_string_literal_range (u8"0123456789", /* { dg-warning "range" } */
6, 4, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (u8"0123456789",
~~^~
{ dg-end-multiline-output "" } */
}
void
test_u (void)
{
/* Digits 0-9. */
__emit_string_literal_range (u"0123456789", /* { dg-error "unable to read substring location: execution character set != source character set" } */
6, 4, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (u"0123456789",
^~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
void
test_U (void)
{
/* Digits 0-9. */
__emit_string_literal_range (U"0123456789", /* { dg-error "unable to read substring location: execution character set != source character set" } */
6, 4, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (U"0123456789",
^~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
void
test_L (void)
{
/* Digits 0-9. */
__emit_string_literal_range (L"0123456789", /* { dg-error "unable to read substring location: execution character set != source character set" } */
6, 4, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (L"0123456789",
^~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
void
test_raw_string_one_liner (void)
{
/* Digits 0-9. */
__emit_string_literal_range (R"foo(0123456789)foo", /* { dg-warning "range" } */
6, 4, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (R"foo(0123456789)foo",
~~^~
{ dg-end-multiline-output "" } */
}
void
test_raw_string_multiline (void)
{
__emit_string_literal_range (R"foo(
hello
world
)foo",
6, 4, 7);
/* { dg-error "unable to read substring location: range endpoints are on different lines" "" { target *-*-* } .-5 } */
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (R"foo(
^~~~~~
hello
~~~~~
world
~~~~~
)foo",
~~~~~
{ dg-end-multiline-output "" } */
}
void
test_macro (void)
{
#define START "01234" /* { dg-warning "range" } */
__emit_string_literal_range (START
"56789",
4, 3, 6);
/* { dg-begin-multiline-output "" }
#define START "01234"
~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__emit_string_literal_range (START
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"56789",
~~~
{ dg-end-multiline-output "" } */
}
void
test_multitoken_macro (void)
{
#define RANGE ("0123456789") /* { dg-error "unable to read substring location: macro expansion" } */
__emit_string_literal_range (RANGE, 4, 3, 6);
/* { dg-begin-multiline-output "" }
#define RANGE ("0123456789")
^~~~~~~~~~~~~~
{ dg-end-multiline-output "" { target c } } */
/* { dg-begin-multiline-output "" }
#define RANGE ("0123456789")
~^~~~~~~~~~~~~
{ dg-end-multiline-output "" { target c++ } } */
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (RANGE, 4, 3, 6);
^~~~~
{ dg-end-multiline-output "" } */
#undef RANGE
}
/* Verify that the location of the closing quote is used
for the location of the null terminating character. */
void
test_terminator_location (void)
{
__emit_string_literal_range ("0123456789", /* { dg-warning "range" } */
10, 10, 10);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("0123456789",
^
{ dg-end-multiline-output "" } */
}
/* Verify that we fail gracefully when a string literal token is split
across multiple physical lines. */
void
test_backslash_continued_logical_lines (void)
{
__emit_string_literal_range ("\
01234\
56789", 6, 6, 7);
/* { dg-error "unable to read substring location: range endpoints are on different lines" "" { target *-*-* } .-3 } */
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("\
^~
01234\
~~~~~~
56789", 6, 6, 7);
~~~~~~
{ dg-end-multiline-output "" } */
}
/* Reproducer for PR 87652; this is whitespace-sensitive. */
#include "pr87562-a.h"
#include "pr87562-b.h"
void
pr87652 (const char *stem, int counter)
{
char label[100];
ASM_GENERATE_INTERNAL_LABEL (label, stem, counter);
/* This warning is actually in "pr87562-a.h". */
/* { dg-warning "39: range" "" { target *-*-* } 5 } */
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("*.%s%u", 2, 2, 3); \
^~
{ dg-end-multiline-output "" } */
}
/* Reproducer for PR 87721. */
# define OFFSET __builtin_strlen (__FILE__) + __builtin_strlen(":%5d: ")
# define DBG_ERROR(format, caret_idx, start_idx, end_idx) \
do { \
__emit_string_literal_range(__FILE__":%5d: " format, \
OFFSET + caret_idx, \
OFFSET + start_idx, \
OFFSET + end_idx); \
} while (0)
/* { dg-error "unable to read substring location: failed to get ordinary maps" "" { target c } 329 } */
/* { dg-error "unable to read substring location: macro expansion" "" { target c++ } 329 } */
/* { dg-begin-multiline-output "" }
__emit_string_literal_range(__FILE__":%5d: " format, \
^~~~~~~~
{ dg-end-multiline-output "" { target c } } */
/* { dg-begin-multiline-output "" }
__emit_string_literal_range(__FILE__":%5d: " format, \
^
{ dg-end-multiline-output "" { target c++ } } */
void pr87721 (void) {
DBG_ERROR("Bad password, expected [%s], got [%s].", 24, 24, 25); /* { dg-message "in expansion of macro 'DBG_ERROR'" } */
/* { dg-begin-multiline-output "" }
DBG_ERROR("Bad password, expected [%s], got [%s].", 24, 24, 25);
^~~~~~~~~
{ dg-end-multiline-output "" } */
}