@@ -3285,6 +3285,17 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
3285
3285
}
3286
3286
}
3287
3287
3288
+ void Parser::DistributeCLateParsedAttrs (Declarator &D, Decl *Dcl,
3289
+ LateParsedAttrList *LateAttrs) {
3290
+ if (!LateAttrs)
3291
+ return ;
3292
+
3293
+ for (auto *LateAttr : *LateAttrs) {
3294
+ if (LateAttr->Decls .empty ())
3295
+ LateAttr->addDecl (Dcl);
3296
+ }
3297
+ }
3298
+
3288
3299
// / Bounds attributes (e.g., counted_by):
3289
3300
// / AttrName '(' expression ')'
3290
3301
void Parser::ParseBoundsAttribute (IdentifierInfo &AttrName,
@@ -4818,13 +4829,14 @@ static void DiagnoseCountAttributedTypeInUnnamedAnon(ParsingDeclSpec &DS,
4818
4829
// /
4819
4830
void Parser::ParseStructDeclaration (
4820
4831
ParsingDeclSpec &DS,
4821
- llvm::function_ref<void (ParsingFieldDeclarator &)> FieldsCallback) {
4832
+ llvm::function_ref<void (ParsingFieldDeclarator &, Decl *&)> FieldsCallback,
4833
+ LateParsedAttrList *LateFieldAttrs) {
4822
4834
4823
4835
if (Tok.is (tok::kw___extension__)) {
4824
4836
// __extension__ silences extension warnings in the subexpression.
4825
4837
ExtensionRAIIObject O (Diags); // Use RAII to do this.
4826
4838
ConsumeToken ();
4827
- return ParseStructDeclaration (DS, FieldsCallback);
4839
+ return ParseStructDeclaration (DS, FieldsCallback, LateFieldAttrs );
4828
4840
}
4829
4841
4830
4842
// Parse leading attributes.
@@ -4889,10 +4901,12 @@ void Parser::ParseStructDeclaration(
4889
4901
}
4890
4902
4891
4903
// If attributes exist after the declarator, parse them.
4892
- MaybeParseGNUAttributes (DeclaratorInfo.D );
4904
+ MaybeParseGNUAttributes (DeclaratorInfo.D , LateFieldAttrs );
4893
4905
4894
4906
// We're done with this declarator; invoke the callback.
4895
- FieldsCallback (DeclaratorInfo);
4907
+ Decl *Field = nullptr ;
4908
+ FieldsCallback (DeclaratorInfo, Field);
4909
+ DistributeCLateParsedAttrs (DeclaratorInfo.D , Field, LateFieldAttrs);
4896
4910
4897
4911
// If we don't have a comma, it is either the end of the list (a ';')
4898
4912
// or an error, bail out.
@@ -4903,6 +4917,79 @@ void Parser::ParseStructDeclaration(
4903
4917
}
4904
4918
}
4905
4919
4920
+ // Parse all attributes in LA, and attach them to Decl D.
4921
+ void Parser::ParseLexedCAttributeList (LateParsedAttrList &LA, bool EnterScope, ParsedAttributes *OutAttrs) {
4922
+ assert (LA.parseSoon () &&
4923
+ " Attribute list should be marked for immediate parsing." );
4924
+ for (unsigned i = 0 , ni = LA.size (); i < ni; ++i) {
4925
+ ParseLexedCAttribute (*LA[i], EnterScope, OutAttrs);
4926
+ delete LA[i];
4927
+ }
4928
+ LA.clear ();
4929
+ }
4930
+
4931
+ // / Finish parsing an attribute for which parsing was delayed.
4932
+ // / This will be called at the end of parsing a class declaration
4933
+ // / for each LateParsedAttribute. We consume the saved tokens and
4934
+ // / create an attribute with the arguments filled in. We add this
4935
+ // / to the Attribute list for the decl.
4936
+ void Parser::ParseLexedCAttribute (LateParsedAttribute &LA, bool EnterScope, ParsedAttributes *OutAttrs) {
4937
+ // Create a fake EOF so that attribute parsing won't go off the end of the
4938
+ // attribute.
4939
+ Token AttrEnd;
4940
+ AttrEnd.startToken ();
4941
+ AttrEnd.setKind (tok::eof);
4942
+ AttrEnd.setLocation (Tok.getLocation ());
4943
+ AttrEnd.setEofData (LA.Toks .data ());
4944
+ LA.Toks .push_back (AttrEnd);
4945
+
4946
+ // Append the current token at the end of the new token stream so that it
4947
+ // doesn't get lost.
4948
+ LA.Toks .push_back (Tok);
4949
+ PP.EnterTokenStream (LA.Toks , true , /* IsReinject=*/ true );
4950
+ // Consume the previously pushed token.
4951
+ ConsumeAnyToken (/* ConsumeCodeCompletionTok=*/ true );
4952
+
4953
+ ParsedAttributes Attrs (AttrFactory);
4954
+
4955
+ assert (
4956
+ LA.Decls .size () < 2 &&
4957
+ " late field attribute expects to have at most a single declaration." );
4958
+
4959
+ Decl *D = LA.Decls .empty () ? nullptr : LA.Decls [0 ];
4960
+
4961
+ // If the Decl is on a function, add function parameters to the scope.
4962
+ {
4963
+ std::unique_ptr<ParseScope> Scope;
4964
+ EnterScope &= D && D->isFunctionOrFunctionTemplate ();
4965
+ if (EnterScope) {
4966
+ Scope.reset (new ParseScope (this , Scope::FnScope | Scope::DeclScope));
4967
+ Actions.ActOnReenterFunctionContext (Actions.CurScope , D);
4968
+ }
4969
+ ParseBoundsAttribute (LA.AttrName , LA.AttrNameLoc , Attrs,
4970
+ /* ScopeName*/ nullptr , SourceLocation (),
4971
+ ParsedAttr::Form::GNU ());
4972
+ if (EnterScope) {
4973
+ Actions.ActOnExitFunctionContext ();
4974
+ }
4975
+ }
4976
+
4977
+ for (unsigned i = 0 , ni = LA.Decls .size (); i < ni; ++i)
4978
+ Actions.ActOnFinishDelayedAttribute (getCurScope (), LA.Decls [i], Attrs);
4979
+
4980
+ // Due to a parsing error, we either went over the cached tokens or
4981
+ // there are still cached tokens left, so we skip the leftover tokens.
4982
+ while (Tok.isNot (tok::eof))
4983
+ ConsumeAnyToken ();
4984
+
4985
+ if (Tok.is (tok::eof) && Tok.getEofData () == AttrEnd.getEofData ())
4986
+ ConsumeAnyToken ();
4987
+
4988
+ if (OutAttrs) {
4989
+ OutAttrs->takeAllFrom (Attrs);
4990
+ }
4991
+ }
4992
+
4906
4993
// / ParseStructUnionBody
4907
4994
// / struct-contents:
4908
4995
// / struct-declaration-list
@@ -4926,6 +5013,11 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
4926
5013
ParseScope StructScope (this , Scope::ClassScope|Scope::DeclScope);
4927
5014
Actions.ActOnTagStartDefinition (getCurScope (), TagDecl);
4928
5015
5016
+ // `LateAttrParseExperimentalExtOnly=true` requests that only attributes
5017
+ // marked with `LateAttrParseExperimentalExt` are late parsed.
5018
+ LateParsedAttrList LateFieldAttrs (/* PSoon=*/ false ,
5019
+ /* LateAttrParseExperimentalExtOnly=*/ true );
5020
+
4929
5021
// While we still have something to read, read the declarations in the struct.
4930
5022
while (!tryParseMisplacedModuleImport () && Tok.isNot (tok::r_brace) &&
4931
5023
Tok.isNot (tok::eof)) {
@@ -4976,18 +5068,19 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
4976
5068
}
4977
5069
4978
5070
if (!Tok.is (tok::at)) {
4979
- auto CFieldCallback = [&](ParsingFieldDeclarator &FD) {
5071
+ auto CFieldCallback = [&](ParsingFieldDeclarator &FD, Decl *&Dcl ) {
4980
5072
// Install the declarator into the current TagDecl.
4981
5073
Decl *Field =
4982
5074
Actions.ActOnField (getCurScope (), TagDecl,
4983
5075
FD.D .getDeclSpec ().getSourceRange ().getBegin (),
4984
5076
FD.D , FD.BitfieldSize );
4985
5077
FD.complete (Field);
5078
+ Dcl = Field;
4986
5079
};
4987
5080
4988
5081
// Parse all the comma separated declarators.
4989
5082
ParsingDeclSpec DS (*this );
4990
- ParseStructDeclaration (DS, CFieldCallback);
5083
+ ParseStructDeclaration (DS, CFieldCallback, &LateFieldAttrs );
4991
5084
} else { // Handle @defs
4992
5085
ConsumeToken ();
4993
5086
if (!Tok.isObjCAtKeyword (tok::objc_defs)) {
@@ -5028,7 +5121,11 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
5028
5121
5029
5122
ParsedAttributes attrs (AttrFactory);
5030
5123
// If attributes exist after struct contents, parse them.
5031
- MaybeParseGNUAttributes (attrs);
5124
+ MaybeParseGNUAttributes (attrs, &LateFieldAttrs);
5125
+
5126
+ assert (!getLangOpts ().CPlusPlus );
5127
+ for (auto *LateAttr : LateFieldAttrs)
5128
+ ParseLexedCAttribute (*LateAttr, true );
5032
5129
5033
5130
SmallVector<Decl *, 32 > FieldDecls (TagDecl->fields ());
5034
5131
0 commit comments