1 /* PR middle-end/81824 - Warn for missing attributes with function aliases
2    Exercise attribute copy for functions.
3    { dg-do compile }
4    { dg-require-alias "" }
5    { dg-options "-O2 -Wall -Wno-array-bounds" } */
6 
7 #define Assert(expr)   typedef char AssertExpr[2 * !!(expr) - 1]
8 
9 #define ATTR(list)   __attribute__ (list)
10 
11 /* Verify that referencing a symbol with no attributes is accepted
12    with no diagnostics.  */
13 
14 void ref0 (void);
15 
16 ATTR ((copy (ref0))) void
17 f0 (void);
18 
19 /* Verify that referencing a symbol using the address-of and dereferencing
20    operators is also accepted with no diagnostics.  */
21 
22 ATTR ((copy (&ref0))) void f1 (void);
23 ATTR ((copy (*ref0))) void f2 (void);
24 
25 /* Verify that referencing a symbol of a different kind than that
26    of the one the attribute is applied to is diagnosed.  */
27 
28 int v0;                       /* { dg-message "symbol .v0. referenced by .f3. declared here" } */
29 
30 ATTR ((copy (v0))) void
31 f3 (void);                    /* { dg-warning ".copy. attribute ignored on a declaration of a different kind than referenced symbol" } */
32 
33 void f4 (void);              /* { dg-message "symbol .f4. referenced by .v1. declared here" } */
34 
35 ATTR ((copy (f4))) int
36 v1;                           /* { dg-warning ".copy. attribute ignored on a declaration of a different kind than referenced symbol" } */
37 
38 
39 ATTR ((copy (v0 + 1)))
40 void f5 (void);               /* { dg-warning ".copy. attribute ignored on a declaration of a different kind than referenced symbol" } */
41 
42 void f6 (void);
43 
44 ATTR ((copy (f6 - 1)))
45 int v1;                       /* { dg-warning ".copy. attribute ignored on a declaration of a different kind than referenced symbol" } */
46 
47 
48 
49 /* Verify that circular references of the copy function attribute
50    are handled gracefully (i.e., not by getting into an infinite
51    recursion) by issuing a diagnostic.  */
52 
53 void xref1 (void);            /* { dg-message "previous declaration here" } */
54 ATTR ((copy (xref1))) void
55 xref1 (void);                 /* { dg-warning ".copy. attribute ignored on a redeclaration of the referenced symbol" } */
56 ATTR ((copy (xref1))) void
57 xref1 (void);                 /* { dg-warning ".copy. attribute ignored on a redeclaration of the referenced symbol" } */
58 ATTR ((copy (xref1), copy (xref1))) void
59 xref1 (void);                 /* { dg-warning ".copy. attribute ignored on a redeclaration of the referenced symbol" } */
60 
61 
62 /* Use attribute noreturn to verify that circular references propagate
63    atttibutes as expected, and unlike in the self-referential instances
64    above, without a warning.  Also use the address-of operator to make
65    sure it doesn't change anything.  */
66 
67 ATTR ((noreturn))      void xref2 (void);
68 ATTR ((copy (xref2)))  void xref3 (void);
69 ATTR ((copy (&xref3))) void xref4 (void);
70 ATTR ((copy (xref4)))  void xref5 (void);
71 ATTR ((copy (&xref5))) void xref6 (void);
72 ATTR ((copy (xref6)))  void xref7 (void);
73 ATTR ((copy (&xref7))) void xref8 (void);
74 ATTR ((copy (xref8)))  void xref9 (void);
75 ATTR ((copy (&xref9))) void xref2 (void);
76 
call_ref2(void)77 int call_ref2 (void) { xref2 (); }
call_ref3(void)78 int call_ref3 (void) { xref3 (); }
call_ref4(void)79 int call_ref4 (void) { xref4 (); }
call_ref5(void)80 int call_ref5 (void) { xref5 (); }
call_ref6(void)81 int call_ref6 (void) { xref6 (); }
call_ref7(void)82 int call_ref7 (void) { xref7 (); }
call_ref8(void)83 int call_ref8 (void) { xref8 (); }
call_ref9(void)84 int call_ref9 (void) { xref9 (); }
85 
86 
87 /* Verify that copying attributes from multiple symbols into one works
88    as expected.  */
89 
90 ATTR ((malloc)) void*
91 xref10 (void);
92 
93 ATTR ((alloc_size (1)))
94 void* xref11 (int);
95 
96 ATTR ((copy (xref10), copy (xref11)))
97 void* xref12 (int);
98 
call_xref12(void)99 void* call_xref12 (void)
100 {
101   void *p = xref12 (3);
102   __builtin___strcpy_chk (p, "123", __builtin_object_size (p, 0));   /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
103   return p;
104 }
105 
106 
107 /* Verify that attribute exclusions apply.  */
108 
109 ATTR ((const)) int
110 fconst (void);
111 
112 ATTR ((pure)) int
113 fpure (void);                 /* { dg-message "previous declaration here" } */
114 
115 ATTR ((copy (fconst), copy (fpure))) int
116 fconst_pure (void);           /* { dg-warning "ignoring attribute .pure. because it conflicts with attribute .const." } */
117 
118 
119 /* Also verify that the note in the exclusion warning points to
120    the declaration from which the conflicting attribute is copied.
121    The wording in the note could be improved but it's the same as
122    in ordinary exclusions so making it different between the two
123    would take some API changes.  */
124 
125 ATTR ((const)) int
126 gconst (void);                /* { dg-message "previous declaration here" } */
127 
128 ATTR ((pure, copy (gconst))) int
129 gpure_const (void);           /* { dg-warning "ignoring attribute .const. because it conflicts with attribute .pure." } */
130 
131 
132 /* Verify that attribute deprecated isn't copied (but referencing
133    the deprecated declaration still triggers a warning).  */
134 
135 ATTR ((deprecated)) void
136 fdeprecated (void);           /* { dg-message "declared here" } */
137 
138 /* Unlike in most other instance the warning below is on the line
139    with the copy attribute that references the deprecated function.  */
140 ATTR ((copy (fdeprecated)))   /* { dg-warning "\\\[-Wdeprecated-declarations]" } */
141 int fcurrent (void);
142 
143 ATTR ((copy (fcurrent))) int
144 fcurrent2 (void);
145 
call_fcurrent(void)146 int call_fcurrent (void) { return fcurrent () + fcurrent2 (); }
147 
148 
149 /* Verify that attributes are copied on a declaration using __typeof__
150    and that -Wmissing-attributes is not issued.  */
151 
152 ATTR ((cold)) int
target_cold(void)153 target_cold (void)
154 { return 0; }
155 
156 __typeof__ (target_cold) ATTR ((copy (target_cold), alias ("target_cold")))
157 alias_cold;                   /* { dg-bogus "\\\[-Wmissing-attributes]." } */
158 
159 
160 /* Verify that attribute alias is not copied.  This also indirectly
161    verifies that attribute copy itself isn't copied.  */
162 
fnoret(void)163 ATTR ((noreturn)) void fnoret (void) { __builtin_abort (); }
164 ATTR ((alias ("fnoret"), copy (fnoret))) void fnoret_alias (void);
copy(fnoret_alias)165 ATTR ((copy (fnoret_alias))) void fnoret2 (void) { __builtin_exit (1); }
166 
167 /* Expect no warning below.  */
call_noret(void)168 int call_noret (void) { fnoret2 (); }
169 
170 
171 /* Verify that attribute nonnull (which is part of a function type,
172    even when it's specified on a function declaration) is copied to
173    the alias from its target.  Expect no warning about the alias
174    specifying less restrictive attributes than its target, but do
175    verify that passing a null to the alias triggers -Wnonnull.  */
176 
177 ATTR ((nonnull))
ftarget_nonnull(void * p)178 void* ftarget_nonnull (void *p) { return p; }
179 
180 ATTR ((alias ("ftarget_nonnull"), copy (ftarget_nonnull)))
181 void* falias_nonnull (void*);
182 
call_falias_nonnull(void)183 void call_falias_nonnull (void)
184 {
185   falias_nonnull (0);         /* { dg-warning "-Wnonnull" } */
186 }
187 
188 /* Same as above but for malloc.  Also verify that the attribute
189    on the alias is used by -Wstringop-overflow.  */
190 
191 ATTR ((malloc))
ftarget_malloc(void)192 void* ftarget_malloc (void) { return __builtin_malloc (1); }
193 
194 ATTR ((alias ("ftarget_malloc"), copy (ftarget_malloc)))
195 void* falias_malloc (void);
196 
call_falias_malloc(void)197 void* call_falias_malloc (void)
198 {
199   char *p = falias_malloc ();
200   __builtin___strcpy_chk (p, "123", __builtin_object_size (p, 0));   /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
201   return p;
202 }
203 
204 /* Same as above but for nothrow.  */
205 
206 ATTR ((nothrow))
ftarget_nothrow(void)207 void ftarget_nothrow (void) { }
208 
209 ATTR ((alias ("ftarget_nothrow"), copy (ftarget_nothrow)))
210 void falias_nothrow (void);
211