================ @@ -1395,6 +1411,171 @@ bool Parser::HandlePragmaMSAllocText(StringRef PragmaName, return true; } +NestedNameSpecifier * +Parser::zOSParseIdentifier(StringRef PragmaName, + const IdentifierInfo *IdentName) { + NestedNameSpecifier *NestedId = nullptr; + if (PP.getLangOpts().CPlusPlus) { + if (Tok.is(tok::coloncolon)) { + // Nothing to do. + } else if (Actions.CurContext->isNamespace()) { + auto *NS = cast<NamespaceDecl>(Actions.CurContext); + NestedId = + NestedNameSpecifier::Create(Actions.Context, NS->getIdentifier()); + NestedId = + NestedNameSpecifier::Create(Actions.Context, NestedId, IdentName); + PP.Lex(Tok); + } else { + NestedId = NestedNameSpecifier::Create(Actions.Context, IdentName); + PP.Lex(Tok); + } + while (Tok.is(tok::coloncolon)) { + PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) + << PragmaName; + return nullptr; + } + IdentifierInfo *II = Tok.getIdentifierInfo(); + NestedId = NestedNameSpecifier::Create(Actions.Context, NestedId, II); + PP.Lex(Tok); + } + } else { + NestedId = NestedNameSpecifier::Create(Actions.Context, IdentName); + PP.Lex(Tok); + } + return NestedId; +} + +bool Parser::zOSParseParameterList( + StringRef PragmaName, std::optional<SmallVector<QualType, 4>> &TypeList, + Qualifiers &CVQual) { + if (Tok.is(tok::l_paren)) { + TypeList = SmallVector<QualType, 4>(); + PP.Lex(Tok); + while (Tok.isNot(tok::eof) && !Tok.is(tok::r_paren)) { + TypeResult TResult = ParseTypeName(nullptr); + if (!TResult.isInvalid()) { + QualType QT = TResult.get().get(); + if (!QT.getTypePtr()->isVoidType()) { + TypeList->push_back(QT); + } + } + if (Tok.is(tok::comma) || Tok.is(tok::identifier)) + PP.Lex(Tok); + } + if (Tok.is(tok::r_paren)) + PP.Lex(Tok); + else { + // We ate the whole line trying to find the right paren of the parameter + // list. + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) + << PragmaName; + return false; + } + + if (TypeList.has_value()) + while (Tok.is(tok::kw_const) || Tok.is(tok::kw_volatile)) { + if (Tok.is(tok::kw_const)) { + CVQual.addConst(); + } else { + assert(Tok.is(tok::kw_volatile)); + CVQual.addVolatile(); + } + PP.Lex(Tok); + } + } + return true; +} + +bool Parser::zOSHandlePragmaHelper(tok::TokenKind PragmaKind) { + assert(Tok.is(PragmaKind)); + + bool IsPragmaExport = PragmaKind == tok::annot_pragma_export; + assert(IsPragmaExport); + StringRef PragmaName = "export"; + + using namespace clang::charinfo; + auto *TheTokens = + (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue(); + PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true, + false); + ConsumeAnnotationToken(); + + do { + PP.Lex(Tok); + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) + << PragmaName; + return false; + } + + // C++ could have a nested name, or be qualified with ::. + PP.Lex(Tok); + if (Tok.isNot(tok::identifier) && + !(PP.getLangOpts().CPlusPlus && Tok.is(tok::coloncolon))) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) + << PragmaName; + return false; + } + + IdentifierInfo *IdentName = Tok.getIdentifierInfo(); + SourceLocation IdentNameLoc = Tok.getLocation(); + NestedNameSpecifier *NestedId = zOSParseIdentifier(PragmaName, IdentName); + if (!NestedId) + return false; + + // C++ can have a paramater list for overloaded functions. + // Try to parse the argument types. + std::optional<SmallVector<QualType, 4>> TypeList; + Qualifiers CVQual; + + if (PP.getLangOpts().CPlusPlus && Tok.is(tok::l_paren)) { + if (!zOSParseParameterList(PragmaName, TypeList, CVQual)) + return false; + } + + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) + << PragmaName; + return false; + } + + PP.Lex(Tok); + Actions.ActOnPragmaExport(NestedId, IdentNameLoc, std::move(TypeList), + CVQual); + + // Because export is also a C++ keyword, we also check for that. + if (Tok.is(tok::identifier) || Tok.is(tok::kw_export)) { + IsPragmaExport = false; + PragmaName = Tok.getIdentifierInfo()->getName(); + if (PragmaName == "export") + IsPragmaExport = true; + else + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << PragmaName; + } else if (Tok.isNot(tok::eof)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << PragmaName; + return false; + } + } while (Tok.isNot(tok::eof)); + PP.Lex(Tok); ---------------- erichkeane wrote:
There is quite a bit on how htis parsing is working that doesn't seem right to me, but the parser code owner shoudl take a look. https://github.com/llvm/llvm-project/pull/141671 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits