================
@@ -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;
+ }
+
+ auto ParseTail = [&] {
+ bool ParametersInScope = ParametersAlreadyInScope;
+ if (Tok.is(tok::kw_requires)) {
+ ParseTrailingRequiresClause(D);
+ ParametersInScope = true;
+ }
+
+ while (getContractSpecifierKind()) {
+ if (!ParametersInScope) {
+ // FIXME: ActOnStartTrailingRequiresClause is not actually deal with
+ // require clause. It is actually adds the parameters to the scope
+ // chains. It needs a better name.
+ Actions.ActOnStartTrailingRequiresClause(getCurScope(), D);
+ ParametersInScope = true;
+ }
----------------
ChuanqiXu9 wrote:
Done for both.
https://github.com/llvm/llvm-project/pull/221139
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits