[clang] [SystemZ][z/OS] Implement #pragma export (PR #141671)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Tue May 27 14:51:03 PDT 2025
================
@@ -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
More information about the cfe-commits
mailing list