================
@@ -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

Reply via email to