131
|
1 // Bug c++/83871 - wrong code due to attributes on distinct template
|
|
2 // specializations
|
|
3 // Test to verify that an explicit template specifialization does not
|
|
4 // "inherit" attribute noreturn from a primary template declared with
|
|
5 // one.
|
|
6 // { dg-do compile }
|
|
7 // { dg-options "-O -Wall -fdump-tree-optimized" }
|
|
8
|
|
9 struct Noreturn { };
|
|
10 struct Returns { };
|
|
11
|
|
12 // Primary declared noreturn but explicit specialization is not.
|
|
13 template <class T> int __attribute__ ((noreturn)) f ();
|
|
14 template <> int f<Returns>();
|
|
15
|
|
16 // Explicit specialization is noreturn but primary is not.
|
|
17 template <class T> int g ();
|
|
18 template <> int __attribute__ ((noreturn)) g<Noreturn>();
|
|
19
|
|
20 int val;
|
|
21
|
|
22 int test_primary_noreturn (char, short)
|
|
23 {
|
|
24 // Only the first call should be emitted, the second one should
|
|
25 // be eliminated because the first one doesn't return.
|
|
26 val = f<char>() + f<short>();
|
|
27 } // expect no -Wreturn-type warning here
|
|
28
|
|
29 int test_noreturn (int)
|
|
30 {
|
|
31 // Call should be retained.
|
|
32 f<int>();
|
|
33 } // expect no -Wreturn-type warning here
|
|
34
|
|
35 int test_special_return (int)
|
|
36 {
|
|
37 // Both calls must be emitted.
|
|
38 int val = f<Returns>() + f<Returns>();
|
|
39 (void)&val;
|
|
40 } // { dg-warning "no return statement in function returning non-void" }
|
|
41
|
|
42
|
|
43 int test_primary_return (void)
|
|
44 {
|
|
45 int val = g<char>() + g<int>();
|
|
46 (void)&val;
|
|
47 } // { dg-warning "no return statement in function returning non-void" }
|
|
48
|
|
49
|
|
50 int test_special_noreturn (int, long)
|
|
51 {
|
|
52 g<Noreturn>();
|
|
53 } // expect no -Wreturn-type warning here
|
|
54
|
|
55
|
|
56 // Verify that the call to f<short>() above is eliminated but the call
|
|
57 // to f<int>() and the two calls to f<Returns>() are retained.
|
|
58 // { dg-final { scan-tree-dump-not "f<short>" "optimized" } }
|
|
59 // { dg-final { scan-tree-dump-times "f<Returns>" 2 "optimized" } }
|
|
60
|
|
61 // Verify that the second call to f<Returns>() in test_special_return()
|
|
62 // is followed by __builtin_unreachable() because there is no return
|
|
63 // statement in the function.
|
|
64 // { dg-final { scan-tree-dump-times "f<Returns> \\(\\);\[\n\r \]+__builtin_unreachable" 1 "optimized" } }
|
|
65
|
|
66
|
|
67 // Verify that the call to g<short>() above is eliminated but the call
|
|
68 // to g<char>() and to g<Noreturn>() are both retained.
|
|
69 // { dg-final { scan-tree-dump-not "g<short>" "optimized" } }
|
|
70 // { dg-final { scan-tree-dump-times "g<char>" 1 "optimized" } }
|
|
71 // { dg-final { scan-tree-dump-times "g<Noreturn>" 1 "optimized" } }
|
|
72
|
|
73 // Verify that the call to g<int>() in test_primary_return() is
|
|
74 // followed by __builtin_unreachable() because there is no return
|
|
75 // statement in the function.
|
|
76 // { dg-final { scan-tree-dump-times "g<int> *\\(\\);\[\n\r \]+__builtin_unreachable" 1 "optimized" } }
|
|
77 // Verify that the call to g<Noreturn>() in test_special_noreturn()
|
|
78 // is not followed by __builtin_unreachable() even though there is no
|
|
79 // return statement in the function.
|
|
80 // { dg-final { scan-tree-dump-times "g<Noreturn> *\\(\\);\[\n\r \]+__builtin_unreachable" 0 "optimized" } }
|