1// { dg-do compile } 2// { dg-options "-fshow-column" }" 3// Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org> 4// Try to find out when the digraph '<:' is used as a mistake, and parse it 5// correctly to avoid cascaded errors. 6 7struct B; 8 9template <class A> 10struct Foo 11{ 12 template <class T> 13 struct Nested 14 { 15 static void method(void) {} 16 }; 17 18 void method(void) { 19 typename Foo<::B>::template Nested<::B> n; // { dg-error "17:'<::' cannot begin" "17-begin" } 20// { dg-message "17:'<:' is an alternate spelling" "17-alt" { target *-*-* } 19 } 21// { dg-error "39:'<::' cannot begin" "39-begin" { target *-*-* } 19 } 22// { dg-message "39:'<:' is an alternate spelling" "39-alt" { target *-*-* } 19 } 23 n.template Nested<B>::method(); 24 n.template Nested<::B>::method(); // { dg-error "22:'<::' cannot begin" "error" } 25// { dg-message "22:'<:' is an alternate" "note" { target *-*-* } 24 } 26 Nested<B>::method(); 27 Nested<::B>::method(); // { dg-error "11:'<::' cannot begin" "error" } 28// { dg-message "11:'<:' is an alternate" "note" { target *-*-* } 27 } 29 } 30}; 31 32template <int N> struct Foo2 {}; 33template struct Foo2<::B>; // { dg-error "21:'<::' cannot begin" "begin" } 34// { dg-message "21:'<:' is an alternate" "alt" { target *-*-* } 33 } 35// { dg-message "25:type/value mismatch" "mismatch" { target *-*-* } 33 } 36// { dg-error "25:expected a constant" "const" { target *-*-* } 33 } 37 38int value = 0; 39 40void func(void) 41{ 42 Foo<::B> f; // { dg-error "cannot begin" "begin" } 43// { dg-message "alternate spelling" "alt" { target *-*-* } 42 } 44 f.Foo<B>::method(); 45 f.Foo<::B>::method(); // { dg-error "8:cannot begin" "begin" } 46// { dg-message "8:alternate spelling" "alt" { target *-*-* } 45 } 47 48 // Check cases where we the token sequence is the correct one, but there 49 // was no digraph or whitespaces in the middle, so we should not emit 50 // the special error message. 51 Foo<: :B> k2; // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" } 52 Foo[:B> k1; // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" } 53// { dg-error "6:missing template arguments before" "template" { target *-*-* } { 51 } } 54// { dg-error "9:expected primary-expression before ':' token" "primary" { target *-*-* } 51 } 55// { dg-error "9:expected '\]' before ':' token" "backslash" { target *-*-* } 51 } 56// { dg-error "9:expected ';' before ':' token" "semicolon" { target *-*-* } 51 } 57// { dg-error "6:missing template arguments before" "template" { target *-*-* } 52 } 58// { dg-error "7:expected primary-expression before ':' token" "primary" { target *-*-* } 52 } 59// { dg-error "7:expected '\]' before ':' token" "backslash" { target *-*-* } 52 } 60// { dg-error "7:expected ';' before ':' token" "semicolon" { target *-*-* } 52 } 61// 62 int Foo[2]; 63 Foo[::value] = 0; 64} 65 66template struct Foo<::B>; // { dg-error "20:'<::' cannot begin" "begin" } 67// { dg-message "20:is an alternate" "alt" { target *-*-* } 66 } 68 69// On the first error message, an additional note about the use of 70// -fpermissive should be present 71// { dg-message "17:\\(if you use '-fpermissive' G\\+\\+ will accept your code\\)" "-fpermissive" { target *-*-* } 19 } 72