1 | // RUN: %clang_cc1 -fsyntax-only -Wno-pragma-clang-attribute -verify %s |
2 | // RUN: not %clang_cc1 -fsyntax-only -ast-dump -ast-dump-filter test %s | FileCheck %s |
3 | |
4 | // Check for contradictions in rules for attribute without a strict subject set: |
5 | |
6 | #pragma clang attribute push (__attribute__((annotate("subRuleContradictions"))), apply_to = any(variable, variable(is_parameter), function(is_member), variable(is_global))) |
7 | // expected-error@-1 {{redundant attribute subject matcher sub-rule 'variable(is_parameter)'; 'variable' already matches those declarations}} |
8 | // expected-error@-2 {{redundant attribute subject matcher sub-rule 'variable(is_global)'; 'variable' already matches those declarations}} |
9 | |
10 | // Ensure that we've recovered from the error: |
11 | int testRecoverSubRuleContradiction = 0; |
12 | // CHECK-LABEL: VarDecl{{.*}} testRecoverSubRuleContradiction |
13 | // CHECK-NEXT: IntegerLiteral |
14 | // CHECK-NEXT: AnnotateAttr{{.*}} "subRuleContradictions" |
15 | |
16 | #pragma clang attribute pop |
17 | |
18 | #pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions2"))), apply_to = any(variable(unless(is_parameter)), variable(is_thread_local), function, variable(is_global))) |
19 | // expected-error@-1 {{negated attribute subject matcher sub-rule 'variable(unless(is_parameter))' contradicts sub-rule 'variable(is_global)'}} |
20 | // We have just one error, don't error on 'variable(is_global)' |
21 | |
22 | // Ensure that we've recovered from the error: |
23 | int testRecoverNegatedContradiction = 0; |
24 | // CHECK-LABEL: VarDecl{{.*}} testRecoverNegatedContradiction |
25 | // CHECK-NEXT: IntegerLiteral |
26 | // CHECK-NEXT: AnnotateAttr{{.*}} "negatedSubRuleContradictions2" |
27 | |
28 | void testRecoverNegatedContradictionFunc(void); |
29 | // CHECK-LABEL: FunctionDecl{{.*}} testRecoverNegatedContradictionFunc |
30 | // CHECK-NEXT: AnnotateAttr{{.*}} "negatedSubRuleContradictions2" |
31 | |
32 | #pragma clang attribute pop |
33 | |
34 | // Verify the strict subject set verification. |
35 | |
36 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) |
37 | |
38 | int testRecoverStrictnessVar = 0; |
39 | // CHECK-LABEL: VarDecl{{.*}} testRecoverStrictnessVar |
40 | // CHECK-NEXT: IntegerLiteral |
41 | // CHECK-NOT: AbiTagAttr |
42 | |
43 | void testRecoverStrictnessFunc(void); |
44 | // CHECK-LABEL: FunctionDecl{{.*}} testRecoverStrictnessFunc |
45 | // CHECK-NEXT: AbiTagAttr |
46 | |
47 | struct testRecoverStrictnessStruct { }; |
48 | // CHECK-LABEL: RecordDecl{{.*}} testRecoverStrictnessStruct |
49 | // CHECK-NOT: AbiTagAttr |
50 | |
51 | #pragma clang attribute pop |
52 | |
53 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), variable, enum)) |
54 | // expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} |
55 | |
56 | int testRecoverExtraVar = 0; |
57 | // CHECK-LABEL: VarDecl{{.*}} testRecoverExtraVar |
58 | // CHECK-NEXT: IntegerLiteral |
59 | // CHECK-NEXT: AbiTagAttr |
60 | |
61 | void testRecoverExtraFunc(void); |
62 | // CHECK-LABEL: FunctionDecl{{.*}} testRecoverExtraFunc |
63 | // CHECK-NEXT: AbiTagAttr |
64 | |
65 | struct testRecoverExtraStruct { }; |
66 | // CHECK-LABEL: RecordDecl{{.*}} testRecoverExtraStruct |
67 | // CHECK-NEXT: AbiTagAttr |
68 | |
69 | enum testNoEnumAbiTag { CaseCase }; |
70 | // CHECK-LABEL: EnumDecl{{.*}} testNoEnumAbiTag |
71 | // CHECK-NO: AbiTagAttr |
72 | |
73 | #pragma clang attribute pop |
74 | |
75 | // Verify the non-strict subject set verification. |
76 | |
77 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) |
78 | |
79 | int testSubset1Var; |
80 | // CHECK-LABEL: VarDecl{{.*}} testSubset1Var |
81 | // CHECK-NOT: AbiTagAttr |
82 | |
83 | void testSubset1Func(void); |
84 | // CHECK-LABEL: FunctionDecl{{.*}} testSubset1Func |
85 | // CHECK-NEXT: AbiTagAttr |
86 | |
87 | struct testSubset1Struct { }; |
88 | // CHECK-LABEL: RecordDecl{{.*}} testSubset1Struct |
89 | // CHECK-NOT: AbiTagAttr |
90 | |
91 | #pragma clang attribute pop |
92 | |
93 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = variable) |
94 | |
95 | int testSubset2Var; |
96 | // CHECK-LABEL: VarDecl{{.*}} testSubset2Var |
97 | // CHECK-NEXT: AbiTagAttr |
98 | |
99 | void testSubset2Func(void); |
100 | // CHECK-LABEL: FunctionDecl{{.*}} testSubset2Func |
101 | // CHECK-NOT: AbiTagAttr |
102 | |
103 | struct testSubset2Struct { }; |
104 | // CHECK-LABEL: RecordDecl{{.*}} testSubset2Struct |
105 | // CHECK-NOT: AbiTagAttr |
106 | |
107 | #pragma clang attribute pop |
108 | |
109 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)))) |
110 | |
111 | int testSubset3Var; |
112 | // CHECK-LABEL: VarDecl{{.*}} testSubset3Var |
113 | // CHECK-NOT: AbiTagAttr |
114 | |
115 | void testSubset3Func(void); |
116 | // CHECK-LABEL: FunctionDecl{{.*}} testSubset3Func |
117 | // CHECK-NOT: AbiTagAttr |
118 | |
119 | struct testSubset3Struct { }; |
120 | // CHECK-LABEL: RecordDecl{{.*}} testSubset3Struct |
121 | // CHECK-NEXT: AbiTagAttr |
122 | |
123 | #pragma clang attribute pop |
124 | |
125 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, variable)) |
126 | |
127 | int testSubset4Var; |
128 | // CHECK-LABEL: VarDecl{{.*}} testSubset4Var |
129 | // CHECK-NEXT: AbiTagAttr |
130 | |
131 | void testSubset4Func(void); |
132 | // CHECK-LABEL: FunctionDecl{{.*}} testSubset4Func |
133 | // CHECK-NEXT: AbiTagAttr |
134 | |
135 | struct testSubset4Struct { }; |
136 | // CHECK-LABEL: RecordDecl{{.*}} testSubset4Struct |
137 | // CHECK-NOT: AbiTagAttr |
138 | |
139 | #pragma clang attribute pop |
140 | |
141 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(variable, record(unless(is_union)))) |
142 | |
143 | int testSubset5Var; |
144 | // CHECK-LABEL: VarDecl{{.*}} testSubset5Var |
145 | // CHECK-NEXT: AbiTagAttr |
146 | |
147 | void testSubset5Func(void); |
148 | // CHECK-LABEL: FunctionDecl{{.*}} testSubset5Func |
149 | // CHECK-NOT: AbiTagAttr |
150 | |
151 | struct testSubset5Struct { }; |
152 | // CHECK-LABEL: RecordDecl{{.*}} testSubset5Struct |
153 | // CHECK-NEXT: AbiTagAttr |
154 | |
155 | #pragma clang attribute pop |
156 | |
157 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function)) |
158 | |
159 | int testSubset6Var; |
160 | // CHECK-LABEL: VarDecl{{.*}} testSubset6Var |
161 | // CHECK-NOT: AbiTagAttr |
162 | |
163 | void testSubset6Func(void); |
164 | // CHECK-LABEL: FunctionDecl{{.*}} testSubset6Func |
165 | // CHECK-NEXT: AbiTagAttr |
166 | |
167 | struct testSubset6Struct { }; |
168 | // CHECK-LABEL: RecordDecl{{.*}} testSubset6Struct |
169 | // CHECK-NEXT: AbiTagAttr |
170 | |
171 | #pragma clang attribute pop |
172 | |
173 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable)) |
174 | |
175 | int testSubset7Var; |
176 | // CHECK-LABEL: VarDecl{{.*}} testSubset7Var |
177 | // CHECK-NEXT: AbiTagAttr |
178 | |
179 | void testSubset7Func(void); |
180 | // CHECK-LABEL: FunctionDecl{{.*}} testSubset7Func |
181 | // CHECK-NEXT: AbiTagAttr |
182 | |
183 | struct testSubset7Struct { }; |
184 | // CHECK-LABEL: RecordDecl{{.*}} testSubset7Struct |
185 | // CHECK-NEXT: AbiTagAttr |
186 | |
187 | #pragma clang attribute pop |
188 | |
189 | |
190 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable, enum, enum_constant)) |
191 | // expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum_constant', and 'enum'}} |
192 | |
193 | int testSubsetRecoverVar; |
194 | // CHECK-LABEL: VarDecl{{.*}} testSubsetRecoverVar |
195 | // CHECK-NEXT: AbiTagAttr |
196 | |
197 | void testSubsetRecoverFunc(void); |
198 | // CHECK-LABEL: FunctionDecl{{.*}} testSubsetRecoverFunc |
199 | // CHECK-NEXT: AbiTagAttr |
200 | |
201 | struct testSubsetRecoverStruct { }; |
202 | // CHECK-LABEL: RecordDecl{{.*}} testSubsetRecoverStruct |
203 | // CHECK-NEXT: AbiTagAttr |
204 | |
205 | #pragma clang attribute pop |
206 | |
207 | #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = enum) |
208 | // expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} |
209 | |
210 | int testSubsetNoVar; |
211 | // CHECK-LABEL: VarDecl{{.*}} testSubsetNoVar |
212 | // CHECK-NOT: AbiTagAttr |
213 | |
214 | void testSubsetNoFunc(void); |
215 | // CHECK-LABEL: FunctionDecl{{.*}} testSubsetNoFunc |
216 | // CHECK-NOT: AbiTagAttr |
217 | |
218 | struct testSubsetNoStruct { }; |
219 | // CHECK-LABEL: RecordDecl{{.*}} testSubsetNoStruct |
220 | // CHECK-NOT: AbiTagAttr |
221 | |
222 | #pragma clang attribute pop |
223 | |