diff options
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 104 |
1 files changed, 97 insertions, 7 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 2ce8fa9..8405b44 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3288,6 +3288,19 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, } } +void Parser::DistributeCLateParsedAttrs(Decl *Dcl, + LateParsedAttrList *LateAttrs) { + assert(Dcl && "Dcl cannot be null"); + + if (!LateAttrs) + return; + + for (auto *LateAttr : *LateAttrs) { + if (LateAttr->Decls.empty()) + LateAttr->addDecl(Dcl); + } +} + /// Bounds attributes (e.g., counted_by): /// AttrName '(' expression ')' void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName, @@ -4825,13 +4838,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. @@ -4896,10 +4910,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. @@ -4910,6 +4926,69 @@ void Parser::ParseStructDeclaration( } } +/// 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, + 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); + + 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 + const AttributeCommonInfo::Form ParsedForm = ParsedAttr::Form::GNU(); + IdentifierInfo *ScopeName = nullptr; + const ParsedAttr::Kind AttrKind = + ParsedAttr::getParsedKind(&LA.AttrName, /*ScopeName=*/ScopeName, + /*SyntaxUsed=*/ParsedForm.getSyntax()); + switch (AttrKind) { + case ParsedAttr::Kind::AT_CountedBy: + ParseBoundsAttribute(LA.AttrName, LA.AttrNameLoc, Attrs, + /*ScopeName=*/ScopeName, SourceLocation(), + /*Form=*/ParsedForm); + break; + default: + llvm_unreachable("Unhandled late parsed attribute"); + } + + 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 @@ -4933,6 +5012,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=*/false, + /*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)) { @@ -4983,18 +5067,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)) { @@ -5035,7 +5120,12 @@ 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. + assert(!getLangOpts().CPlusPlus); + for (auto *LateAttr : LateFieldAttrs) + ParseLexedCAttribute(*LateAttr); SmallVector<Decl *, 32> FieldDecls(TagDecl->fields()); |