@@ -146,6 +146,86 @@ void Parser::ParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs,
146
146
} while (MoreToParse);
147
147
}
148
148
149
+ // / ParseSingleGNUAttribute - Parse a single GNU attribute.
150
+ // /
151
+ // / [GNU] attrib:
152
+ // / empty
153
+ // / attrib-name
154
+ // / attrib-name '(' identifier ')'
155
+ // / attrib-name '(' identifier ',' nonempty-expr-list ')'
156
+ // / attrib-name '(' argument-expression-list [C99 6.5.2] ')'
157
+ // /
158
+ // / [GNU] attrib-name:
159
+ // / identifier
160
+ // / typespec
161
+ // / typequal
162
+ // / storageclass
163
+ bool Parser::ParseSingleGNUAttribute (ParsedAttributes &Attrs,
164
+ SourceLocation &EndLoc,
165
+ LateParsedAttrList *LateAttrs,
166
+ Declarator *D) {
167
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo ();
168
+ if (!AttrName)
169
+ return true ;
170
+
171
+ SourceLocation AttrNameLoc = ConsumeToken ();
172
+
173
+ if (Tok.isNot (tok::l_paren)) {
174
+ Attrs.addNew (AttrName, AttrNameLoc, nullptr , AttrNameLoc, nullptr , 0 ,
175
+ ParsedAttr::Form::GNU ());
176
+ return false ;
177
+ }
178
+
179
+ bool LateParse = false ;
180
+ if (!LateAttrs)
181
+ LateParse = false ;
182
+ else if (LateAttrs->lateAttrParseExperimentalExtOnly ()) {
183
+ // The caller requested that this attribute **only** be late
184
+ // parsed for `LateAttrParseExperimentalExt` attributes. This will
185
+ // only be late parsed if the experimental language option is enabled.
186
+ LateParse = getLangOpts ().ExperimentalLateParseAttributes &&
187
+ IsAttributeLateParsedExperimentalExt (*AttrName);
188
+ } else {
189
+ // The caller did not restrict late parsing to only
190
+ // `LateAttrParseExperimentalExt` attributes so late parse
191
+ // both `LateAttrParseStandard` and `LateAttrParseExperimentalExt`
192
+ // attributes.
193
+ LateParse = IsAttributeLateParsedExperimentalExt (*AttrName) ||
194
+ IsAttributeLateParsedStandard (*AttrName);
195
+ }
196
+
197
+ // Handle "parameterized" attributes
198
+ if (!LateParse) {
199
+ ParseGNUAttributeArgs (AttrName, AttrNameLoc, Attrs, &EndLoc, nullptr ,
200
+ SourceLocation (), ParsedAttr::Form::GNU (), D);
201
+ return false ;
202
+ }
203
+
204
+ // Handle attributes with arguments that require late parsing.
205
+ LateParsedAttribute *LA =
206
+ new LateParsedAttribute (this , *AttrName, AttrNameLoc);
207
+ LateAttrs->push_back (LA);
208
+
209
+ // Attributes in a class are parsed at the end of the class, along
210
+ // with other late-parsed declarations.
211
+ if (!ClassStack.empty () && !LateAttrs->parseSoon ())
212
+ getCurrentClass ().LateParsedDeclarations .push_back (LA);
213
+
214
+ // Be sure ConsumeAndStoreUntil doesn't see the start l_paren, since it
215
+ // recursively consumes balanced parens.
216
+ LA->Toks .push_back (Tok);
217
+ ConsumeParen ();
218
+ // Consume everything up to and including the matching right parens.
219
+ ConsumeAndStoreUntil (tok::r_paren, LA->Toks , /* StopAtSemi=*/ true );
220
+
221
+ Token Eof;
222
+ Eof.startToken ();
223
+ Eof.setLocation (Tok.getLocation ());
224
+ LA->Toks .push_back (Eof);
225
+
226
+ return false ;
227
+ }
228
+
149
229
// / ParseGNUAttributes - Parse a non-empty attributes list.
150
230
// /
151
231
// / [GNU] attributes:
@@ -223,64 +303,9 @@ void Parser::ParseGNUAttributes(ParsedAttributes &Attrs,
223
303
AttributeCommonInfo::Syntax::AS_GNU);
224
304
break ;
225
305
}
226
- IdentifierInfo *AttrName = Tok.getIdentifierInfo ();
227
- if (!AttrName)
228
- break ;
229
306
230
- SourceLocation AttrNameLoc = ConsumeToken ();
231
-
232
- if (Tok.isNot (tok::l_paren)) {
233
- Attrs.addNew (AttrName, AttrNameLoc, nullptr , AttrNameLoc, nullptr , 0 ,
234
- ParsedAttr::Form::GNU ());
235
- continue ;
236
- }
237
-
238
- bool LateParse = false ;
239
- if (!LateAttrs)
240
- LateParse = false ;
241
- else if (LateAttrs->lateAttrParseExperimentalExtOnly ()) {
242
- // The caller requested that this attribute **only** be late
243
- // parsed for `LateAttrParseExperimentalExt` attributes. This will
244
- // only be late parsed if the experimental language option is enabled.
245
- LateParse = getLangOpts ().ExperimentalLateParseAttributes &&
246
- IsAttributeLateParsedExperimentalExt (*AttrName);
247
- } else {
248
- // The caller did not restrict late parsing to only
249
- // `LateAttrParseExperimentalExt` attributes so late parse
250
- // both `LateAttrParseStandard` and `LateAttrParseExperimentalExt`
251
- // attributes.
252
- LateParse = IsAttributeLateParsedExperimentalExt (*AttrName) ||
253
- IsAttributeLateParsedStandard (*AttrName);
254
- }
255
-
256
- // Handle "parameterized" attributes
257
- if (!LateParse) {
258
- ParseGNUAttributeArgs (AttrName, AttrNameLoc, Attrs, &EndLoc, nullptr ,
259
- SourceLocation (), ParsedAttr::Form::GNU (), D);
260
- continue ;
261
- }
262
-
263
- // Handle attributes with arguments that require late parsing.
264
- LateParsedAttribute *LA =
265
- new LateParsedAttribute (this , *AttrName, AttrNameLoc);
266
- LateAttrs->push_back (LA);
267
-
268
- // Attributes in a class are parsed at the end of the class, along
269
- // with other late-parsed declarations.
270
- if (!ClassStack.empty () && !LateAttrs->parseSoon ())
271
- getCurrentClass ().LateParsedDeclarations .push_back (LA);
272
-
273
- // Be sure ConsumeAndStoreUntil doesn't see the start l_paren, since it
274
- // recursively consumes balanced parens.
275
- LA->Toks .push_back (Tok);
276
- ConsumeParen ();
277
- // Consume everything up to and including the matching right parens.
278
- ConsumeAndStoreUntil (tok::r_paren, LA->Toks , /* StopAtSemi=*/ true );
279
-
280
- Token Eof;
281
- Eof.startToken ();
282
- Eof.setLocation (Tok.getLocation ());
283
- LA->Toks .push_back (Eof);
307
+ if (ParseSingleGNUAttribute (Attrs, EndLoc, LateAttrs, D))
308
+ break ;
284
309
} while (Tok.is (tok::comma));
285
310
286
311
if (ExpectAndConsume (tok::r_paren))
0 commit comments