Skip to content

Commit 7815abe

Browse files
authored
[Parser][NFC] Move the core parsing of an attribute into a separate method (#107300)
Refactor attribute parsing so that the main code parsing an attribute can be called by a separate code path that doesn't start with the '__attribute' keyword.
1 parent fc7a893 commit 7815abe

File tree

2 files changed

+85
-57
lines changed

2 files changed

+85
-57
lines changed

clang/include/clang/Parse/Parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2943,6 +2943,9 @@ class Parser : public CodeCompletionHandler {
29432943
return false;
29442944
}
29452945

2946+
bool ParseSingleGNUAttribute(ParsedAttributes &Attrs, SourceLocation &EndLoc,
2947+
LateParsedAttrList *LateAttrs = nullptr,
2948+
Declarator *D = nullptr);
29462949
void ParseGNUAttributes(ParsedAttributes &Attrs,
29472950
LateParsedAttrList *LateAttrs = nullptr,
29482951
Declarator *D = nullptr);

clang/lib/Parse/ParseDecl.cpp

Lines changed: 82 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,86 @@ void Parser::ParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs,
146146
} while (MoreToParse);
147147
}
148148

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+
149229
/// ParseGNUAttributes - Parse a non-empty attributes list.
150230
///
151231
/// [GNU] attributes:
@@ -223,64 +303,9 @@ void Parser::ParseGNUAttributes(ParsedAttributes &Attrs,
223303
AttributeCommonInfo::Syntax::AS_GNU);
224304
break;
225305
}
226-
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
227-
if (!AttrName)
228-
break;
229306

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;
284309
} while (Tok.is(tok::comma));
285310

286311
if (ExpectAndConsume(tok::r_paren))

0 commit comments

Comments
 (0)