Skip to content

[Clang][NFC] Improve const correctess of constraint normalization #133633

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

Merged
merged 1 commit into from
Mar 30, 2025
Merged
Show file tree
Hide file tree
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
17 changes: 10 additions & 7 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -14660,7 +14660,8 @@ class Sema final : public SemaBase {
bool First = true);

const NormalizedConstraint *getNormalizedAssociatedConstraints(
NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints);
const NamedDecl *ConstrainedDecl,
ArrayRef<const Expr *> AssociatedConstraints);

/// \brief Check whether the given declaration's associated constraints are
/// at least as constrained than another declaration's according to the
Expand All @@ -14670,28 +14671,30 @@ class Sema final : public SemaBase {
/// at least constrained than D2, and false otherwise.
///
/// \returns true if an error occurred, false otherwise.
bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef<const Expr *> AC1,
NamedDecl *D2, MutableArrayRef<const Expr *> AC2,
bool &Result);
bool IsAtLeastAsConstrained(const NamedDecl *D1,
MutableArrayRef<const Expr *> AC1,
const NamedDecl *D2,
MutableArrayRef<const Expr *> AC2, bool &Result);

/// If D1 was not at least as constrained as D2, but would've been if a pair
/// of atomic constraints involved had been declared in a concept and not
/// repeated in two separate places in code.
/// \returns true if such a diagnostic was emitted, false otherwise.
bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
NamedDecl *D1, ArrayRef<const Expr *> AC1, NamedDecl *D2,
const NamedDecl *D1, ArrayRef<const Expr *> AC1, const NamedDecl *D2,
ArrayRef<const Expr *> AC2);

private:
/// Caches pairs of template-like decls whose associated constraints were
/// checked for subsumption and whether or not the first's constraints did in
/// fact subsume the second's.
llvm::DenseMap<std::pair<NamedDecl *, NamedDecl *>, bool> SubsumptionCache;
llvm::DenseMap<std::pair<const NamedDecl *, const NamedDecl *>, bool>
SubsumptionCache;
/// Caches the normalized associated constraints of declarations (concepts or
/// constrained declarations). If an error occurred while normalizing the
/// associated constraints of the template or concept, nullptr will be cached
/// here.
llvm::DenseMap<NamedDecl *, NormalizedConstraint *> NormalizationCache;
llvm::DenseMap<const NamedDecl *, NormalizedConstraint *> NormalizationCache;

llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
SatisfactionCache;
Expand Down
14 changes: 7 additions & 7 deletions clang/include/clang/Sema/SemaConcept.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ enum { ConstraintAlignment = 8 };

struct alignas(ConstraintAlignment) AtomicConstraint {
const Expr *ConstraintExpr;
NamedDecl *ConstraintDecl;
const NamedDecl *ConstraintDecl;
std::optional<ArrayRef<TemplateArgumentLoc>> ParameterMapping;

AtomicConstraint(const Expr *ConstraintExpr, NamedDecl *ConstraintDecl)
AtomicConstraint(const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl)
: ConstraintExpr(ConstraintExpr), ConstraintDecl(ConstraintDecl) {};

bool hasMatchingParameterMapping(ASTContext &C,
Expand Down Expand Up @@ -114,9 +114,9 @@ struct NormalizedConstraint {

private:
static std::optional<NormalizedConstraint>
fromConstraintExprs(Sema &S, NamedDecl *D, ArrayRef<const Expr *> E);
fromConstraintExprs(Sema &S, const NamedDecl *D, ArrayRef<const Expr *> E);
static std::optional<NormalizedConstraint>
fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E);
fromConstraintExpr(Sema &S, const NamedDecl *D, const Expr *E);
};

struct alignas(ConstraintAlignment) NormalizedConstraintPair {
Expand All @@ -137,7 +137,7 @@ struct alignas(ConstraintAlignment) FoldExpandedConstraint {
};

const NormalizedConstraint *getNormalizedAssociatedConstraints(
Sema &S, NamedDecl *ConstrainedDecl,
Sema &S, const NamedDecl *ConstrainedDecl,
ArrayRef<const Expr *> AssociatedConstraints);

/// \brief SubsumptionChecker establishes subsumption
Expand All @@ -149,8 +149,8 @@ class SubsumptionChecker {

SubsumptionChecker(Sema &SemaRef, SubsumptionCallable Callable = {});

std::optional<bool> Subsumes(NamedDecl *DP, ArrayRef<const Expr *> P,
NamedDecl *DQ, ArrayRef<const Expr *> Q);
std::optional<bool> Subsumes(const NamedDecl *DP, ArrayRef<const Expr *> P,
const NamedDecl *DQ, ArrayRef<const Expr *> Q);

bool Subsumes(const NormalizedConstraint *P, const NormalizedConstraint *Q);

Expand Down
36 changes: 20 additions & 16 deletions clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ static ExprResult calculateConstraintSatisfaction(
Sema::InstantiatingTemplate Inst(
S, AtomicExpr->getBeginLoc(),
Sema::InstantiatingTemplate::ConstraintSubstitution{},
// FIXME: improve const-correctness of InstantiatingTemplate
const_cast<NamedDecl *>(Template), Info,
AtomicExpr->getSourceRange());
if (Inst.isInvalid())
Expand Down Expand Up @@ -1435,9 +1436,9 @@ void Sema::DiagnoseUnsatisfiedConstraint(
}
}

const NormalizedConstraint *
Sema::getNormalizedAssociatedConstraints(
NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints(
const NamedDecl *ConstrainedDecl,
ArrayRef<const Expr *> AssociatedConstraints) {
// In case the ConstrainedDecl comes from modules, it is necessary to use
// the canonical decl to avoid different atomic constraints with the 'same'
// declarations.
Expand All @@ -1461,7 +1462,7 @@ Sema::getNormalizedAssociatedConstraints(
}

const NormalizedConstraint *clang::getNormalizedAssociatedConstraints(
Sema &S, NamedDecl *ConstrainedDecl,
Sema &S, const NamedDecl *ConstrainedDecl,
ArrayRef<const Expr *> AssociatedConstraints) {
return S.getNormalizedAssociatedConstraints(ConstrainedDecl,
AssociatedConstraints);
Expand Down Expand Up @@ -1527,7 +1528,8 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N,
Sema::InstantiatingTemplate Inst(
S, InstLocBegin,
Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
Atomic.ConstraintDecl, {InstLocBegin, InstLocEnd});
const_cast<NamedDecl *>(Atomic.ConstraintDecl),
{InstLocBegin, InstLocEnd});
if (Inst.isInvalid())
return true;
if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
Expand Down Expand Up @@ -1591,7 +1593,7 @@ NormalizedConstraint &NormalizedConstraint::getRHS() const {
}

std::optional<NormalizedConstraint>
NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
NormalizedConstraint::fromConstraintExprs(Sema &S, const NamedDecl *D,
ArrayRef<const Expr *> E) {
assert(E.size() != 0);
auto Conjunction = fromConstraintExpr(S, D, E[0]);
Expand All @@ -1608,7 +1610,8 @@ NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
}

std::optional<NormalizedConstraint>
NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
NormalizedConstraint::fromConstraintExpr(Sema &S, const NamedDecl *D,
const Expr *E) {
assert(E != nullptr);

// C++ [temp.constr.normal]p1.1
Expand Down Expand Up @@ -1637,8 +1640,9 @@ NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
{
Sema::InstantiatingTemplate Inst(
S, CSE->getExprLoc(),
Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
CSE->getSourceRange());
Sema::InstantiatingTemplate::ConstraintNormalization{},
// FIXME: improve const-correctness of InstantiatingTemplate
const_cast<NamedDecl *>(D), CSE->getSourceRange());
if (Inst.isInvalid())
return std::nullopt;
// C++ [temp.constr.normal]p1.1
Expand Down Expand Up @@ -1726,9 +1730,9 @@ bool FoldExpandedConstraint::AreCompatibleForSubsumption(
return false;
}

bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1,
MutableArrayRef<const Expr *> AC1,
NamedDecl *D2,
const NamedDecl *D2,
MutableArrayRef<const Expr *> AC2,
bool &Result) {
#ifndef NDEBUG
Expand All @@ -1755,7 +1759,7 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
return false;
}

std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
auto CacheEntry = SubsumptionCache.find(Key);
if (CacheEntry != SubsumptionCache.end()) {
Result = CacheEntry->second;
Expand Down Expand Up @@ -1789,7 +1793,7 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
}

bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
NamedDecl *D1, ArrayRef<const Expr *> AC1, NamedDecl *D2,
const NamedDecl *D1, ArrayRef<const Expr *> AC1, const NamedDecl *D2,
ArrayRef<const Expr *> AC2) {

if (isSFINAEContext())
Expand Down Expand Up @@ -2055,7 +2059,7 @@ FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
FormulaType Res;

auto Add = [&, this](Clause C) {
// Sort each clause and remove duplicates for faster comparisons
// Sort each clause and remove duplicates for faster comparisons.
llvm::sort(C);
C.erase(llvm::unique(C), C.end());
AddUniqueClauseToFormula(Res, std::move(C));
Expand Down Expand Up @@ -2102,9 +2106,9 @@ void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
F.push_back(C);
}

std::optional<bool> SubsumptionChecker::Subsumes(NamedDecl *DP,
std::optional<bool> SubsumptionChecker::Subsumes(const NamedDecl *DP,
ArrayRef<const Expr *> P,
NamedDecl *DQ,
const NamedDecl *DQ,
ArrayRef<const Expr *> Q) {
const NormalizedConstraint *PNormalized =
getNormalizedAssociatedConstraints(SemaRef, DP, P);
Expand Down
Loading