Skip to content

[clang] Introduce SemaConcept #92672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
407 changes: 26 additions & 381 deletions clang/include/clang/Sema/Sema.h

Large diffs are not rendered by default.

391 changes: 388 additions & 3 deletions clang/include/clang/Sema/SemaConcept.h

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenMP.h"
@@ -4082,8 +4083,9 @@ void Parser::ParseDeclarationSpecifiers(
if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
goto DoneWithDeclSpec;

if (TemplateId && !isInvalid && Actions.CheckTypeConstraint(TemplateId))
TemplateId = nullptr;
if (TemplateId && !isInvalid &&
Actions.Concept().CheckTypeConstraint(TemplateId))
TemplateId = nullptr;

ConsumeAnnotationToken();
SourceLocation AutoLoc = Tok.getLocation();
6 changes: 3 additions & 3 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
@@ -4290,16 +4290,16 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) {
Scope::FunctionDeclarationScope |
Scope::FunctionPrototypeScope);

Actions.ActOnStartTrailingRequiresClause(getCurScope(), D);
Actions.Concept().ActOnStartTrailingRequiresClause(getCurScope(), D);

std::optional<Sema::CXXThisScopeRAII> ThisScope;
InitCXXThisScopeForDeclaratorIfRelevant(D, D.getDeclSpec(), ThisScope);

TrailingRequiresClause =
ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);

TrailingRequiresClause =
Actions.ActOnFinishTrailingRequiresClause(TrailingRequiresClause);
TrailingRequiresClause = Actions.Concept().ActOnFinishTrailingRequiresClause(
TrailingRequiresClause);

if (!D.isDeclarationOfFunction()) {
Diag(RequiresKWLoc,
9 changes: 5 additions & 4 deletions clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenACC.h"
#include "clang/Sema/SemaOpenMP.h"
@@ -268,7 +269,8 @@ ExprResult Parser::ParseConstraintExpression() {
Actions, Sema::ExpressionEvaluationContext::Unevaluated);
ExprResult LHS(ParseCastExpression(AnyCastExpr));
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) {
if (Res.isUsable() &&
!Actions.Concept().CheckConstraintExpression(Res.get())) {
Actions.CorrectDelayedTyposInExpr(Res);
return ExprError();
}
@@ -329,9 +331,8 @@ Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
NotPrimaryExpression = false;
}
bool PossibleNonPrimary;
bool IsConstraintExpr =
Actions.CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary,
IsTrailingRequiresClause);
bool IsConstraintExpr = Actions.Concept().CheckConstraintExpression(
E.get(), Tok, &PossibleNonPrimary, IsTrailingRequiresClause);
if (!IsConstraintExpr || PossibleNonPrimary) {
// Atomic constraint might be an unparenthesized non-primary expression
// (such as a binary operator), in which case we might get here (e.g. in
30 changes: 16 additions & 14 deletions clang/lib/Parse/ParseExprCXX.cpp
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Sema/SemaConcept.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <numeric>
@@ -1417,8 +1418,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
++CurTemplateDepthTracker;
ExprResult RequiresClause;
if (TryConsumeToken(tok::kw_requires)) {
RequiresClause =
Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(
RequiresClause = Actions.Concept().ActOnRequiresClause(
ParseConstraintLogicalOrExpression(
/*IsTrailingRequiresClause=*/false));
if (RequiresClause.isInvalid())
SkipUntil({tok::l_brace, tok::l_paren}, StopAtSemi | StopBeforeMatch);
@@ -3628,7 +3629,7 @@ ExprResult Parser::ParseRequiresExpression() {
// Dependent diagnostics are attached to this Decl and non-depenedent
// diagnostics are surfaced after this parse.
ParsingDeclRAIIObject ParsingBodyDecl(*this, ParsingDeclRAIIObject::NoParent);
RequiresExprBodyDecl *Body = Actions.ActOnStartRequiresExpr(
RequiresExprBodyDecl *Body = Actions.Concept().ActOnStartRequiresExpr(
RequiresKWLoc, LocalParameterDecls, getCurScope());

if (Tok.is(tok::r_brace)) {
@@ -3669,7 +3670,8 @@ ExprResult Parser::ParseRequiresExpression() {
SourceLocation NoexceptLoc;
TryConsumeToken(tok::kw_noexcept, NoexceptLoc);
if (Tok.is(tok::semi)) {
Req = Actions.ActOnCompoundRequirement(Expression.get(), NoexceptLoc);
Req = Actions.Concept().ActOnCompoundRequirement(Expression.get(),
NoexceptLoc);
if (Req)
Requirements.push_back(Req);
break;
@@ -3696,7 +3698,7 @@ ExprResult Parser::ParseRequiresExpression() {
ConsumeAnnotationToken();
}

Req = Actions.ActOnCompoundRequirement(
Req = Actions.Concept().ActOnCompoundRequirement(
Expression.get(), NoexceptLoc, SS, takeTemplateIdAnnotation(Tok),
TemplateParameterDepth);
ConsumeAnnotationToken();
@@ -3764,8 +3766,8 @@ ExprResult Parser::ParseRequiresExpression() {
SkipUntilFlags::StopBeforeMatch);
break;
}
if (auto *Req =
Actions.ActOnNestedRequirement(ConstraintExpr.get()))
if (auto *Req = Actions.Concept().ActOnNestedRequirement(
ConstraintExpr.get()))
Requirements.push_back(Req);
else {
SkipUntil(tok::semi, tok::r_brace,
@@ -3810,9 +3812,8 @@ ExprResult Parser::ParseRequiresExpression() {
break;
}

if (auto *Req = Actions.ActOnTypeRequirement(TypenameKWLoc, SS,
NameLoc, II,
TemplateId)) {
if (auto *Req = Actions.Concept().ActOnTypeRequirement(
TypenameKWLoc, SS, NameLoc, II, TemplateId)) {
Requirements.push_back(Req);
}
break;
@@ -3833,7 +3834,8 @@ ExprResult Parser::ParseRequiresExpression() {
if (!Expression.isInvalid() && PossibleRequiresExprInSimpleRequirement)
Diag(StartLoc, diag::err_requires_expr_in_simple_requirement)
<< FixItHint::CreateInsertion(StartLoc, "requires");
if (auto *Req = Actions.ActOnSimpleRequirement(Expression.get()))
if (auto *Req =
Actions.Concept().ActOnSimpleRequirement(Expression.get()))
Requirements.push_back(Req);
else {
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
@@ -3861,14 +3863,14 @@ ExprResult Parser::ParseRequiresExpression() {
// other diagnostics quoting an empty requires expression they never
// wrote.
Braces.consumeClose();
Actions.ActOnFinishRequiresExpr();
Actions.Concept().ActOnFinishRequiresExpr();
return ExprError();
}
}
Braces.consumeClose();
Actions.ActOnFinishRequiresExpr();
Actions.Concept().ActOnFinishRequiresExpr();
ParsingBodyDecl.complete(Body);
return Actions.ActOnRequiresExpr(
return Actions.Concept().ActOnRequiresExpr(
RequiresKWLoc, Body, Parens.getOpenLocation(), LocalParameterDecls,
Parens.getCloseLocation(), Requirements, Braces.getCloseLocation());
}
23 changes: 13 additions & 10 deletions clang/lib/Parse/ParseTemplate.cpp
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/Support/TimeProfiler.h"
using namespace clang;
@@ -145,8 +146,9 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(

if (TryConsumeToken(tok::kw_requires)) {
OptionalRequiresClauseConstraintER =
Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(
/*IsTrailingRequiresClause=*/false));
Actions.Concept().ActOnRequiresClause(
ParseConstraintLogicalOrExpression(
/*IsTrailingRequiresClause=*/false));
if (!OptionalRequiresClauseConstraintER.isUsable()) {
// Skip until the semi-colon or a '}'.
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
@@ -339,9 +341,9 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
DeclEnd = Tok.getLocation();
ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
Expr *ConstraintExpr = ConstraintExprResult.get();
return Actions.ActOnConceptDefinition(getCurScope(),
*TemplateInfo.TemplateParams, Id, IdLoc,
ConstraintExpr, Attrs);
return Actions.Concept().ActOnConceptDefinition(
getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc, ConstraintExpr,
Attrs);
}

/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
@@ -763,9 +765,9 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
TypeConstraint != nullptr);

if (TypeConstraint) {
Actions.ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,
cast<TemplateTypeParmDecl>(NewDecl),
EllipsisLoc);
Actions.Concept().ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,
cast<TemplateTypeParmDecl>(NewDecl),
EllipsisLoc);
}

return NewDecl;
@@ -800,8 +802,9 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
}
if (TryConsumeToken(tok::kw_requires)) {
OptionalRequiresClauseConstraintER =
Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(
/*IsTrailingRequiresClause=*/false));
Actions.Concept().ActOnRequiresClause(
ParseConstraintLogicalOrExpression(
/*IsTrailingRequiresClause=*/false));
if (!OptionalRequiresClauseConstraintER.isUsable()) {
SkipUntil(tok::comma, tok::greater, tok::greatergreater,
StopAtSemi | StopBeforeMatch);
12 changes: 3 additions & 9 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Sema/SemaHLSL.h"
#include "clang/Sema/SemaInternal.h"
@@ -205,6 +206,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
CurScope(nullptr), Ident_super(nullptr),
CodeCompletionPtr(
std::make_unique<SemaCodeCompletion>(*this, CodeCompleter)),
ConceptPtr(std::make_unique<SemaConcept>(*this)),
CUDAPtr(std::make_unique<SemaCUDA>(*this)),
HLSLPtr(std::make_unique<SemaHLSL>(*this)),
ObjCPtr(std::make_unique<SemaObjC>(*this)),
@@ -228,7 +230,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TyposCorrected(0), IsBuildingRecoveryCallExpr(false), NumSFINAEErrors(0),
AccessCheckingSFINAE(false), CurrentInstantiationScope(nullptr),
InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
ArgumentPackSubstitutionIndex(-1), SatisfactionCache(Context) {
ArgumentPackSubstitutionIndex(-1) {
assert(pp.TUKind == TUKind);
TUScope = nullptr;

@@ -491,14 +493,6 @@ Sema::~Sema() {
= dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
ExternalSema->ForgetSema();

// Delete cached satisfactions.
std::vector<ConstraintSatisfaction *> Satisfactions;
Satisfactions.reserve(SatisfactionCache.size());
for (auto &Node : SatisfactionCache)
Satisfactions.push_back(&Node);
for (auto *Node : Satisfactions)
delete Node;

threadSafety::threadSafetyCleanup(ThreadSafetyDeclCache);

// Destroys data sharing attributes stack for OpenMP
6 changes: 0 additions & 6 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
@@ -8092,12 +8092,6 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
}

void Sema::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) {
if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) {
DiagnoseUseOfDecl(Decl, Loc);
}
}

/// CheckConstructorCall - Check a constructor call for correctness and safety
/// properties not enforced by the C type system.
void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,
Loading