================
@@ -4244,6 +4254,134 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) 
{
   }
 }
 
+std::optional<Parser::ContractSpecifierKind>
+Parser::getContractSpecifierKind() {
+  if (!getLangOpts().Contracts || Tok.isNot(tok::identifier))
+    return std::nullopt;
+
+  IdentifierInfo *II = Tok.getIdentifierInfo();
+  if (II->isStr("pre"))
+    return ContractSpecifierKind::Pre;
+  if (II->isStr("post"))
+    return ContractSpecifierKind::Post;
+  return std::nullopt;
+}
+
+void Parser::ParseContractSpecifiers(Declarator &D) {
+  assert(getLangOpts().Contracts && "contracts are not enabled");
+
+  const bool IsFunction = D.isDeclarationOfFunction() &&
+                          (D.isFunctionDeclarationContext() ||
+                           D.getContext() == DeclaratorContext::LambdaExpr);
+  if (!IsFunction)
+    Diag(Tok, diag::err_contract_specifier_not_function);
+
+  while (std::optional<ContractSpecifierKind> Kind =
+             getContractSpecifierKind()) {
+    const bool IsPost = *Kind == ContractSpecifierKind::Post;
+    ConsumeToken();
+
+    ParsedAttributes Attrs(AttrFactory);
+    MaybeParseCXX11Attributes(Attrs);
+
+    BalancedDelimiterTracker T(*this, tok::l_paren);
+    if (T.expectAndConsume(diag::err_expected_lparen_after,
+                           IsPost ? "post" : "pre"))
+      return;
+
+    // !IsFunction is diagnosed before, avoid confusing diagnostics.
+    if (!IsFunction) {
+      T.skipToEnd();
+      continue;
+    }
+
+    // FIXME: We should accept attribute for the result binding, e.g.,
+    // post(r [[attr]] : expr).
+    std::optional<ParseScope> ResultNameScope;
+    if (IsPost && Tok.is(tok::identifier) && NextToken().is(tok::colon)) {
+      IdentifierInfo *ResultName = Tok.getIdentifierInfo();
+      SourceLocation ResultNameLoc = ConsumeToken();
+      ConsumeToken();
+
+      ResultNameScope.emplace(this, Scope::DeclScope);
+      Actions.ActOnPostConditionResultName(getCurScope(), ResultName,
+                                           ResultNameLoc);
+    }
+
+    EnterExpressionEvaluationContext Evaluated(
+        Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+    ExprResult Predicate = ParseConditionalExpression();
+    ResultNameScope.reset();
+    if (Predicate.isInvalid())
+      T.skipToEnd();
+    else
+      T.consumeClose();
+  }
+}
+
+// Parse the function tail where the require clause must appear first
+// and the contracts later.
+void Parser::ParseFunctionDeclaratorTail(Declarator &D,
+                                         bool ParametersAlreadyInScope) {
+  assert((Tok.is(tok::kw_requires) || getContractSpecifierKind()) &&
+         "expected a function declarator tail");
+
+  // TODO: We can consider merging ParseTrailingRequiresClauseWithScope into
+  // this function.
+  if (!ParametersAlreadyInScope && Tok.is(tok::kw_requires)) {
+    ParseTrailingRequiresClauseWithScope(D);
+    if (!getContractSpecifierKind())
+      return;
+  }
----------------
ChuanqiXu9 wrote:

Done now ParseTrailingRequiresClause don't set up the scope

https://github.com/llvm/llvm-project/pull/221139
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to