124ad1215SRichard Smith // RUN: %clang_cc1 -std=c++17 -verify=cxx17 -Wc++20-compat %s
224ad1215SRichard Smith // RUN: %clang_cc1 -std=c++20 -verify=cxx20 -Wc++17-compat %s
3b78e8e0dSRichard Smith
4b78e8e0dSRichard Smith namespace disambig {
5b78e8e0dSRichard Smith
6b78e8e0dSRichard Smith // Cases that are valid in C++17 and before, ill-formed in C++20, and that we
7b78e8e0dSRichard Smith // should not treat as explicit(bool) as an extension.
824ad1215SRichard Smith struct A { // cxx20-note +{{}}
Adisambig::A9b78e8e0dSRichard Smith constexpr A() {}
operator booldisambig::A10b78e8e0dSRichard Smith constexpr operator bool() { return true; }
11b78e8e0dSRichard Smith
12b78e8e0dSRichard Smith constexpr explicit (A)(int); // #1
13b78e8e0dSRichard Smith // cxx17-warning@#1 {{will be parsed as explicit(bool)}}
1424ad1215SRichard Smith // cxx20-error@#1 +{{}} cxx20-note@#1 +{{}}
1524ad1215SRichard Smith // cxx20-warning@#1 {{incompatible with C++ standards before C++20}}
16b78e8e0dSRichard Smith
17b78e8e0dSRichard Smith // This is ill-formed (via a DR change), and shouldn't be recognized as a
18b78e8e0dSRichard Smith // constructor (the function declarator cannot be parenthesized in a
19b78e8e0dSRichard Smith // constructor declaration). But accepting it as an extension seems
20b78e8e0dSRichard Smith // reasonable.
21b78e8e0dSRichard Smith // FIXME: Produce an ExtWarn for this.
22b78e8e0dSRichard Smith constexpr explicit (A(float)); // #1b
23b78e8e0dSRichard Smith // cxx17-warning@#1b {{will be parsed as explicit(bool)}}
2424ad1215SRichard Smith // cxx20-error@#1b +{{}}
2524ad1215SRichard Smith // cxx20-warning@#1b {{incompatible with C++ standards before C++20}}
26b78e8e0dSRichard Smith
27b78e8e0dSRichard Smith explicit (operator int)(); // #2
28b78e8e0dSRichard Smith // cxx17-warning@#2 {{will be parsed as explicit(bool)}}
2924ad1215SRichard Smith // cxx20-error@#2 +{{}}
3024ad1215SRichard Smith // cxx20-warning@#2 {{incompatible with C++ standards before C++20}}
31b78e8e0dSRichard Smith
32b78e8e0dSRichard Smith explicit (A::operator float)(); // #2b
33b78e8e0dSRichard Smith // cxx17-warning@#2b {{will be parsed as explicit(bool)}}
34b78e8e0dSRichard Smith // cxx17-error@#2b {{extra qualification on member}}
3524ad1215SRichard Smith // cxx20-error@#2b +{{}}
3624ad1215SRichard Smith // cxx20-warning@#2b {{incompatible with C++ standards before C++20}}
37b78e8e0dSRichard Smith };
38b78e8e0dSRichard Smith
operator +(A)39b78e8e0dSRichard Smith constexpr bool operator+(A) { return true; }
40b78e8e0dSRichard Smith
41b78e8e0dSRichard Smith constexpr bool C = false;
42b78e8e0dSRichard Smith
43b78e8e0dSRichard Smith // Cases that should (ideally) be disambiguated as explicit(bool) in earlier
44b78e8e0dSRichard Smith // language modes as an extension.
45b78e8e0dSRichard Smith struct B {
46b78e8e0dSRichard Smith // Looks like a constructor, but not the constructor of B.
47b78e8e0dSRichard Smith explicit (A()) B(); // #3
4824ad1215SRichard Smith // cxx17-warning@#3 {{C++20 extension}}
4924ad1215SRichard Smith // cxx20-warning@#3 {{incompatible with C++ standards before C++20}}
50b78e8e0dSRichard Smith
51b78e8e0dSRichard Smith // Looks like a 'constructor' of C. Actually a constructor of B.
52b78e8e0dSRichard Smith explicit (C)(B)(A); // #4
5324ad1215SRichard Smith // cxx17-warning@#4 {{C++20 extension}}
5424ad1215SRichard Smith // cxx20-warning@#4 {{incompatible with C++ standards before C++20}}
55b78e8e0dSRichard Smith
56b78e8e0dSRichard Smith explicit (operator+(A())) operator int(); // #5
57*2cb2cd24SAaron Ballman // cxx17-error@#5 {{a type specifier is required}} cxx17-error@#5 {{expected ';'}}
58b78e8e0dSRichard Smith // cxx17-warning@#5 {{will be parsed as explicit(bool)}}
5924ad1215SRichard Smith // cxx20-warning@#5 {{incompatible with C++ standards before C++20}}
60b78e8e0dSRichard Smith };
61b78e8e0dSRichard Smith
62b78e8e0dSRichard Smith }
63