aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp106
1 files changed, 99 insertions, 7 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index fdb8c93..86e8a6b 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3312,6 +3312,19 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
}
}
+void Parser::DistributeCLateParsedAttrs(Decl *Dcl,
+ LateParsedAttrList *LateAttrs) {
+ if (!LateAttrs)
+ return;
+
+ if (Dcl) {
+ for (auto *LateAttr : *LateAttrs) {
+ if (LateAttr->Decls.empty())
+ LateAttr->addDecl(Dcl);
+ }
+ }
+}
+
/// Bounds attributes (e.g., counted_by):
/// AttrName '(' expression ')'
void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
@@ -4849,13 +4862,14 @@ static void DiagnoseCountAttributedTypeInUnnamedAnon(ParsingDeclSpec &DS,
///
void Parser::ParseStructDeclaration(
ParsingDeclSpec &DS,
- llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback) {
+ llvm::function_ref<Decl *(ParsingFieldDeclarator &)> FieldsCallback,
+ LateParsedAttrList *LateFieldAttrs) {
if (Tok.is(tok::kw___extension__)) {
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
ConsumeToken();
- return ParseStructDeclaration(DS, FieldsCallback);
+ return ParseStructDeclaration(DS, FieldsCallback, LateFieldAttrs);
}
// Parse leading attributes.
@@ -4920,10 +4934,12 @@ void Parser::ParseStructDeclaration(
}
// If attributes exist after the declarator, parse them.
- MaybeParseGNUAttributes(DeclaratorInfo.D);
+ MaybeParseGNUAttributes(DeclaratorInfo.D, LateFieldAttrs);
// We're done with this declarator; invoke the callback.
- FieldsCallback(DeclaratorInfo);
+ Decl *Field = FieldsCallback(DeclaratorInfo);
+ if (Field)
+ DistributeCLateParsedAttrs(Field, LateFieldAttrs);
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
@@ -4934,6 +4950,73 @@ void Parser::ParseStructDeclaration(
}
}
+// TODO: All callers of this function should be moved to
+// `Parser::ParseLexedAttributeList`.
+void Parser::ParseLexedCAttributeList(LateParsedAttrList &LAs, bool EnterScope,
+ ParsedAttributes *OutAttrs) {
+ assert(LAs.parseSoon() &&
+ "Attribute list should be marked for immediate parsing.");
+ for (auto *LA : LAs) {
+ ParseLexedCAttribute(*LA, EnterScope, OutAttrs);
+ delete LA;
+ }
+ LAs.clear();
+}
+
+/// Finish parsing an attribute for which parsing was delayed.
+/// This will be called at the end of parsing a class declaration
+/// for each LateParsedAttribute. We consume the saved tokens and
+/// create an attribute with the arguments filled in. We add this
+/// to the Attribute list for the decl.
+void Parser::ParseLexedCAttribute(LateParsedAttribute &LA, bool EnterScope,
+ ParsedAttributes *OutAttrs) {
+ // Create a fake EOF so that attribute parsing won't go off the end of the
+ // attribute.
+ Token AttrEnd;
+ AttrEnd.startToken();
+ AttrEnd.setKind(tok::eof);
+ AttrEnd.setLocation(Tok.getLocation());
+ AttrEnd.setEofData(LA.Toks.data());
+ LA.Toks.push_back(AttrEnd);
+
+ // Append the current token at the end of the new token stream so that it
+ // doesn't get lost.
+ LA.Toks.push_back(Tok);
+ PP.EnterTokenStream(LA.Toks, /*DisableMacroExpansion=*/true,
+ /*IsReinject=*/true);
+ // Drop the current token and bring the first cached one. It's the same token
+ // as when we entered this function.
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+
+ // TODO: Use `EnterScope`
+ (void)EnterScope;
+
+ ParsedAttributes Attrs(AttrFactory);
+
+ assert(LA.Decls.size() <= 1 &&
+ "late field attribute expects to have at most one declaration.");
+
+ // Dispatch based on the attribute and parse it
+ ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, nullptr, nullptr,
+ SourceLocation(), ParsedAttr::Form::GNU(), nullptr);
+
+ for (auto *D : LA.Decls)
+ Actions.ActOnFinishDelayedAttribute(getCurScope(), D, Attrs);
+
+ // Due to a parsing error, we either went over the cached tokens or
+ // there are still cached tokens left, so we skip the leftover tokens.
+ while (Tok.isNot(tok::eof))
+ ConsumeAnyToken();
+
+ // Consume the fake EOF token if it's there
+ if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData())
+ ConsumeAnyToken();
+
+ if (OutAttrs) {
+ OutAttrs->takeAllFrom(Attrs);
+ }
+}
+
/// ParseStructUnionBody
/// struct-contents:
/// struct-declaration-list
@@ -4957,6 +5040,11 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
+ // `LateAttrParseExperimentalExtOnly=true` requests that only attributes
+ // marked with `LateAttrParseExperimentalExt` are late parsed.
+ LateParsedAttrList LateFieldAttrs(/*PSoon=*/true,
+ /*LateAttrParseExperimentalExtOnly=*/true);
+
// While we still have something to read, read the declarations in the struct.
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
Tok.isNot(tok::eof)) {
@@ -5007,18 +5095,19 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
}
if (!Tok.is(tok::at)) {
- auto CFieldCallback = [&](ParsingFieldDeclarator &FD) {
+ auto CFieldCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {
// Install the declarator into the current TagDecl.
Decl *Field =
Actions.ActOnField(getCurScope(), TagDecl,
FD.D.getDeclSpec().getSourceRange().getBegin(),
FD.D, FD.BitfieldSize);
FD.complete(Field);
+ return Field;
};
// Parse all the comma separated declarators.
ParsingDeclSpec DS(*this);
- ParseStructDeclaration(DS, CFieldCallback);
+ ParseStructDeclaration(DS, CFieldCallback, &LateFieldAttrs);
} else { // Handle @defs
ConsumeToken();
if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
@@ -5059,7 +5148,10 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
ParsedAttributes attrs(AttrFactory);
// If attributes exist after struct contents, parse them.
- MaybeParseGNUAttributes(attrs);
+ MaybeParseGNUAttributes(attrs, &LateFieldAttrs);
+
+ // Late parse field attributes if necessary.
+ ParseLexedCAttributeList(LateFieldAttrs, /*EnterScope=*/false);
SmallVector<Decl *, 32> FieldDecls(TagDecl->fields());