[clang] [clang] Introduce `SemaConcept` (PR #92672)
Vlad Serebrennikov via cfe-commits
cfe-commits at lists.llvm.org
Sun May 19 03:14:51 PDT 2024
https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/92672
>From 716135aa2b0e87172890b545ee20107ceba624e0 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 18 May 2024 21:41:19 +0300
Subject: [PATCH 1/4] [clang] Introduce `SemaConcept`
---
clang/include/clang/Sema/Sema.h | 319 ++-------------------
clang/include/clang/Sema/SemaConcept.h | 271 ++++++++++++++++-
clang/lib/Parse/ParseExpr.cpp | 5 +-
clang/lib/Sema/Sema.cpp | 12 +-
clang/lib/Sema/SemaConcept.cpp | 219 +++++++-------
clang/lib/Sema/SemaDecl.cpp | 7 +-
clang/lib/Sema/SemaDeclCXX.cpp | 7 +-
clang/lib/Sema/SemaExpr.cpp | 5 +-
clang/lib/Sema/SemaExprCXX.cpp | 3 +-
clang/lib/Sema/SemaOverload.cpp | 29 +-
clang/lib/Sema/SemaTemplate.cpp | 19 +-
clang/lib/Sema/SemaTemplateDeduction.cpp | 21 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 41 ++-
13 files changed, 490 insertions(+), 468 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d4d4a82525a02..1e92eb929e62e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -168,6 +168,7 @@ class PseudoDestructorTypeStorage;
class PseudoObjectExpr;
class QualType;
class SemaCodeCompletion;
+class SemaConcept;
class SemaCUDA;
class SemaHLSL;
class SemaObjC;
@@ -181,6 +182,7 @@ class SwitchStmt;
class TemplateArgument;
class TemplateArgumentList;
class TemplateArgumentLoc;
+class TemplateCompareNewDeclInfo;
class TemplateDecl;
class TemplateInstantiationCallback;
class TemplateParameterList;
@@ -989,6 +991,11 @@ class Sema final : public SemaBase {
return *CodeCompletionPtr;
}
+ SemaConcept &Concept() {
+ assert(ConceptPtr);
+ return *ConceptPtr;
+ }
+
SemaCUDA &CUDA() {
assert(CUDAPtr);
return *CUDAPtr;
@@ -1050,6 +1057,7 @@ class Sema final : public SemaBase {
mutable IdentifierInfo *Ident_super;
std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
+ std::unique_ptr<SemaConcept> ConceptPtr;
std::unique_ptr<SemaCUDA> CUDAPtr;
std::unique_ptr<SemaHLSL> HLSLPtr;
std::unique_ptr<SemaObjC> ObjCPtr;
@@ -9198,46 +9206,6 @@ class Sema final : public SemaBase {
TPL_TemplateParamsEquivalent,
};
- // A struct to represent the 'new' declaration, which is either itself just
- // the named decl, or the important information we need about it in order to
- // do constraint comparisons.
- class TemplateCompareNewDeclInfo {
- const NamedDecl *ND = nullptr;
- const DeclContext *DC = nullptr;
- const DeclContext *LexicalDC = nullptr;
- SourceLocation Loc;
-
- public:
- TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
- TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
- const DeclContext *LexicalDeclCtx,
- SourceLocation Loc)
-
- : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
- assert(DC && LexicalDC &&
- "Constructor only for cases where we have the information to put "
- "in here");
- }
-
- // If this was constructed with no information, we cannot do substitution
- // for constraint comparison, so make sure we can check that.
- bool isInvalid() const { return !ND && !DC; }
-
- const NamedDecl *getDecl() const { return ND; }
-
- bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
-
- const DeclContext *getLexicalDeclContext() const {
- return ND ? ND->getLexicalDeclContext() : LexicalDC;
- }
-
- const DeclContext *getDeclContext() const {
- return ND ? ND->getDeclContext() : DC;
- }
-
- SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
- };
-
bool TemplateParameterListsAreEqual(
const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
@@ -10402,6 +10370,15 @@ class Sema final : public SemaBase {
return CodeSynthesisContexts.size() > NonInstantiationEntries;
}
+ private:
+
+ /// Introduce the instantiated captures of the lambda into the local
+ /// instantiation scope.
+ bool addInstantiatedCapturesToScope(
+ FunctionDecl *Function, const FunctionDecl *PatternDecl,
+ LocalInstantiationScope &Scope,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
///@}
//
@@ -10638,12 +10615,6 @@ class Sema final : public SemaBase {
const DeclContext *Pattern,
const MultiLevelTemplateArgumentList &TemplateArgs);
-private:
- /// Introduce the instantiated local variables into the local
- /// instantiation scope.
- void addInstantiatedLocalVarsToScope(FunctionDecl *Function,
- const FunctionDecl *PatternDecl,
- LocalInstantiationScope &Scope);
/// Introduce the instantiated function parameters into the local
/// instantiation scope, and set the parameter names to those used
/// in the template.
@@ -10652,6 +10623,13 @@ class Sema final : public SemaBase {
LocalInstantiationScope &Scope,
const MultiLevelTemplateArgumentList &TemplateArgs);
+private:
+ /// Introduce the instantiated local variables into the local
+ /// instantiation scope.
+ void addInstantiatedLocalVarsToScope(FunctionDecl *Function,
+ const FunctionDecl *PatternDecl,
+ LocalInstantiationScope &Scope);
+
int ParsingClassDepth = 0;
class SavePendingParsedClassStateRAII {
@@ -11092,255 +11070,6 @@ class Sema final : public SemaBase {
//
//
- /// \name Constraints and Concepts
- /// Implementations are in SemaConcept.cpp
- ///@{
-
-public:
- void PushSatisfactionStackEntry(const NamedDecl *D,
- const llvm::FoldingSetNodeID &ID) {
- const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
- SatisfactionStack.emplace_back(Can, ID);
- }
-
- void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); }
-
- bool SatisfactionStackContains(const NamedDecl *D,
- const llvm::FoldingSetNodeID &ID) const {
- const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
- return llvm::find(SatisfactionStack, SatisfactionStackEntryTy{Can, ID}) !=
- SatisfactionStack.end();
- }
-
- using SatisfactionStackEntryTy =
- std::pair<const NamedDecl *, llvm::FoldingSetNodeID>;
-
- // Resets the current SatisfactionStack for cases where we are instantiating
- // constraints as a 'side effect' of normal instantiation in a way that is not
- // indicative of recursive definition.
- class SatisfactionStackResetRAII {
- llvm::SmallVector<SatisfactionStackEntryTy, 10> BackupSatisfactionStack;
- Sema &SemaRef;
-
- public:
- SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
- SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
- }
-
- ~SatisfactionStackResetRAII() {
- SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
- }
- };
-
- void SwapSatisfactionStack(
- llvm::SmallVectorImpl<SatisfactionStackEntryTy> &NewSS) {
- SatisfactionStack.swap(NewSS);
- }
-
- /// Check whether the given expression is a valid constraint expression.
- /// A diagnostic is emitted if it is not, false is returned, and
- /// PossibleNonPrimary will be set to true if the failure might be due to a
- /// non-primary expression being used as an atomic constraint.
- bool CheckConstraintExpression(const Expr *CE, Token NextToken = Token(),
- bool *PossibleNonPrimary = nullptr,
- bool IsTrailingRequiresClause = false);
-
- /// \brief Check whether the given list of constraint expressions are
- /// satisfied (as if in a 'conjunction') given template arguments.
- /// \param Template the template-like entity that triggered the constraints
- /// check (either a concept or a constrained entity).
- /// \param ConstraintExprs a list of constraint expressions, treated as if
- /// they were 'AND'ed together.
- /// \param TemplateArgLists the list of template arguments to substitute into
- /// the constraint expression.
- /// \param TemplateIDRange The source range of the template id that
- /// caused the constraints check.
- /// \param Satisfaction if true is returned, will contain details of the
- /// satisfaction, with enough information to diagnose an unsatisfied
- /// expression.
- /// \returns true if an error occurred and satisfaction could not be checked,
- /// false otherwise.
- bool CheckConstraintSatisfaction(
- const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
- const MultiLevelTemplateArgumentList &TemplateArgLists,
- SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
- llvm::SmallVector<Expr *, 4> Converted;
- return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted,
- TemplateArgLists, TemplateIDRange,
- Satisfaction);
- }
-
- /// \brief Check whether the given list of constraint expressions are
- /// satisfied (as if in a 'conjunction') given template arguments.
- /// Additionally, takes an empty list of Expressions which is populated with
- /// the instantiated versions of the ConstraintExprs.
- /// \param Template the template-like entity that triggered the constraints
- /// check (either a concept or a constrained entity).
- /// \param ConstraintExprs a list of constraint expressions, treated as if
- /// they were 'AND'ed together.
- /// \param ConvertedConstraints a out parameter that will get populated with
- /// the instantiated version of the ConstraintExprs if we successfully checked
- /// satisfaction.
- /// \param TemplateArgList the multi-level list of template arguments to
- /// substitute into the constraint expression. This should be relative to the
- /// top-level (hence multi-level), since we need to instantiate fully at the
- /// time of checking.
- /// \param TemplateIDRange The source range of the template id that
- /// caused the constraints check.
- /// \param Satisfaction if true is returned, will contain details of the
- /// satisfaction, with enough information to diagnose an unsatisfied
- /// expression.
- /// \returns true if an error occurred and satisfaction could not be checked,
- /// false otherwise.
- bool CheckConstraintSatisfaction(
- const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
- llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
- const MultiLevelTemplateArgumentList &TemplateArgList,
- SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
-
- /// \brief Check whether the given non-dependent constraint expression is
- /// satisfied. Returns false and updates Satisfaction with the satisfaction
- /// verdict if successful, emits a diagnostic and returns true if an error
- /// occurred and satisfaction could not be determined.
- ///
- /// \returns true if an error occurred, false otherwise.
- bool CheckConstraintSatisfaction(const Expr *ConstraintExpr,
- ConstraintSatisfaction &Satisfaction);
-
- /// Check whether the given function decl's trailing requires clause is
- /// satisfied, if any. Returns false and updates Satisfaction with the
- /// satisfaction verdict if successful, emits a diagnostic and returns true if
- /// an error occurred and satisfaction could not be determined.
- ///
- /// \returns true if an error occurred, false otherwise.
- bool CheckFunctionConstraints(const FunctionDecl *FD,
- ConstraintSatisfaction &Satisfaction,
- SourceLocation UsageLoc = SourceLocation(),
- bool ForOverloadResolution = false);
-
- // Calculates whether two constraint expressions are equal irrespective of a
- // difference in 'depth'. This takes a pair of optional 'NamedDecl's 'Old' and
- // 'New', which are the "source" of the constraint, since this is necessary
- // for figuring out the relative 'depth' of the constraint. The depth of the
- // 'primary template' and the 'instantiated from' templates aren't necessarily
- // the same, such as a case when one is a 'friend' defined in a class.
- bool AreConstraintExpressionsEqual(const NamedDecl *Old,
- const Expr *OldConstr,
- const TemplateCompareNewDeclInfo &New,
- const Expr *NewConstr);
-
- // Calculates whether the friend function depends on an enclosing template for
- // the purposes of [temp.friend] p9.
- bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD);
-
- /// \brief Ensure that the given template arguments satisfy the constraints
- /// associated with the given template, emitting a diagnostic if they do not.
- ///
- /// \param Template The template to which the template arguments are being
- /// provided.
- ///
- /// \param TemplateArgs The converted, canonicalized template arguments.
- ///
- /// \param TemplateIDRange The source range of the template id that
- /// caused the constraints check.
- ///
- /// \returns true if the constrains are not satisfied or could not be checked
- /// for satisfaction, false if the constraints are satisfied.
- bool EnsureTemplateArgumentListConstraints(
- TemplateDecl *Template,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SourceRange TemplateIDRange);
-
- bool CheckInstantiatedFunctionTemplateConstraints(
- SourceLocation PointOfInstantiation, FunctionDecl *Decl,
- ArrayRef<TemplateArgument> TemplateArgs,
- ConstraintSatisfaction &Satisfaction);
-
- /// \brief Emit diagnostics explaining why a constraint expression was deemed
- /// unsatisfied.
- /// \param First whether this is the first time an unsatisfied constraint is
- /// diagnosed for this error.
- void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
- bool First = true);
-
- /// \brief Emit diagnostics explaining why a constraint expression was deemed
- /// unsatisfied.
- void
- DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
- bool First = true);
-
- const NormalizedConstraint *getNormalizedAssociatedConstraints(
- 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
- /// partial ordering of constraints.
- ///
- /// \param Result If no error occurred, receives the result of true if D1 is
- /// 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);
-
- /// 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,
- 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;
- /// 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::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
- SatisfactionCache;
-
- // The current stack of constraint satisfactions, so we can exit-early.
- llvm::SmallVector<SatisfactionStackEntryTy, 10> SatisfactionStack;
-
- /// Introduce the instantiated captures of the lambda into the local
- /// instantiation scope.
- bool addInstantiatedCapturesToScope(
- FunctionDecl *Function, const FunctionDecl *PatternDecl,
- LocalInstantiationScope &Scope,
- const MultiLevelTemplateArgumentList &TemplateArgs);
-
- /// Used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
- /// the case of lambdas) set up the LocalInstantiationScope of the current
- /// function.
- bool
- SetupConstraintScope(FunctionDecl *FD,
- std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
- const MultiLevelTemplateArgumentList &MLTAL,
- LocalInstantiationScope &Scope);
-
- /// Used during constraint checking, sets up the constraint template argument
- /// lists, and calls SetupConstraintScope to set up the
- /// LocalInstantiationScope to have the proper set of ParVarDecls configured.
- std::optional<MultiLevelTemplateArgumentList>
- SetupConstraintCheckingTemplateArgumentsAndScope(
- FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
- LocalInstantiationScope &Scope);
-
- ///@}
-
- //
- //
- // -------------------------------------------------------------------------
- //
- //
-
/// \name Types
/// Implementations are in SemaType.cpp
///@{
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 711443505174f..7104e91f24b61 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -17,6 +17,8 @@
#include "clang/AST/Expr.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Token.h"
+#include "clang/Sema/SemaBase.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include <optional>
@@ -24,7 +26,6 @@
#include <utility>
namespace clang {
-class Sema;
struct AtomicConstraint {
const Expr *ConstraintExpr;
@@ -80,6 +81,7 @@ struct AtomicConstraint {
/// disjunction of normalized constraints.
struct NormalizedConstraint {
friend class Sema;
+ friend class SemaConcept;
enum CompoundConstraintKind { CCK_Conjunction, CCK_Disjunction };
@@ -150,6 +152,271 @@ struct NormalizedConstraint {
fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E);
};
-} // clang
+class LocalInstantiationScope;
+class MultiLevelTemplateArgumentList;
+
+// A struct to represent the 'new' declaration, which is either itself just
+// the named decl, or the important information we need about it in order to
+// do constraint comparisons.
+class TemplateCompareNewDeclInfo {
+ const NamedDecl *ND = nullptr;
+ const DeclContext *DC = nullptr;
+ const DeclContext *LexicalDC = nullptr;
+ SourceLocation Loc;
+
+public:
+ TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
+ TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
+ const DeclContext *LexicalDeclCtx,
+ SourceLocation Loc)
+
+ : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
+ assert(DC && LexicalDC &&
+ "Constructor only for cases where we have the information to put "
+ "in here");
+ }
+
+ // If this was constructed with no information, we cannot do substitution
+ // for constraint comparison, so make sure we can check that.
+ bool isInvalid() const { return !ND && !DC; }
+
+ const NamedDecl *getDecl() const { return ND; }
+
+ bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
+
+ const DeclContext *getLexicalDeclContext() const {
+ return ND ? ND->getLexicalDeclContext() : LexicalDC;
+ }
+
+ const DeclContext *getDeclContext() const {
+ return ND ? ND->getDeclContext() : DC;
+ }
+
+ SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
+};
+
+class SemaConcept : public SemaBase {
+public:
+ SemaConcept(Sema &S);
+ ~SemaConcept();
+
+ void PushSatisfactionStackEntry(const NamedDecl *D,
+ const llvm::FoldingSetNodeID &ID) {
+ const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
+ SatisfactionStack.emplace_back(Can, ID);
+ }
+
+ void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); }
+
+ bool SatisfactionStackContains(const NamedDecl *D,
+ const llvm::FoldingSetNodeID &ID) const {
+ const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
+ return llvm::find(SatisfactionStack, SatisfactionStackEntryTy{Can, ID}) !=
+ SatisfactionStack.end();
+ }
+
+ using SatisfactionStackEntryTy =
+ std::pair<const NamedDecl *, llvm::FoldingSetNodeID>;
+
+ // Resets the current SatisfactionStack for cases where we are instantiating
+ // constraints as a 'side effect' of normal instantiation in a way that is not
+ // indicative of recursive definition.
+ class SatisfactionStackResetRAII {
+ llvm::SmallVector<SatisfactionStackEntryTy, 10> BackupSatisfactionStack;
+ Sema &SemaRef;
+
+ public:
+ SatisfactionStackResetRAII(Sema &S);
+ ~SatisfactionStackResetRAII();
+ };
+
+ void SwapSatisfactionStack(
+ llvm::SmallVectorImpl<SatisfactionStackEntryTy> &NewSS) {
+ SatisfactionStack.swap(NewSS);
+ }
+
+ /// Check whether the given expression is a valid constraint expression.
+ /// A diagnostic is emitted if it is not, false is returned, and
+ /// PossibleNonPrimary will be set to true if the failure might be due to a
+ /// non-primary expression being used as an atomic constraint.
+ bool CheckConstraintExpression(const Expr *CE, Token NextToken = Token(),
+ bool *PossibleNonPrimary = nullptr,
+ bool IsTrailingRequiresClause = false);
+
+ /// \brief Check whether the given list of constraint expressions are
+ /// satisfied (as if in a 'conjunction') given template arguments.
+ /// \param Template the template-like entity that triggered the constraints
+ /// check (either a concept or a constrained entity).
+ /// \param ConstraintExprs a list of constraint expressions, treated as if
+ /// they were 'AND'ed together.
+ /// \param TemplateArgLists the list of template arguments to substitute into
+ /// the constraint expression.
+ /// \param TemplateIDRange The source range of the template id that
+ /// caused the constraints check.
+ /// \param Satisfaction if true is returned, will contain details of the
+ /// satisfaction, with enough information to diagnose an unsatisfied
+ /// expression.
+ /// \returns true if an error occurred and satisfaction could not be checked,
+ /// false otherwise.
+ bool CheckConstraintSatisfaction(
+ const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
+ const MultiLevelTemplateArgumentList &TemplateArgLists,
+ SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
+ llvm::SmallVector<Expr *, 4> Converted;
+ return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted,
+ TemplateArgLists, TemplateIDRange,
+ Satisfaction);
+ }
+
+ /// \brief Check whether the given list of constraint expressions are
+ /// satisfied (as if in a 'conjunction') given template arguments.
+ /// Additionally, takes an empty list of Expressions which is populated with
+ /// the instantiated versions of the ConstraintExprs.
+ /// \param Template the template-like entity that triggered the constraints
+ /// check (either a concept or a constrained entity).
+ /// \param ConstraintExprs a list of constraint expressions, treated as if
+ /// they were 'AND'ed together.
+ /// \param ConvertedConstraints a out parameter that will get populated with
+ /// the instantiated version of the ConstraintExprs if we successfully checked
+ /// satisfaction.
+ /// \param TemplateArgList the multi-level list of template arguments to
+ /// substitute into the constraint expression. This should be relative to the
+ /// top-level (hence multi-level), since we need to instantiate fully at the
+ /// time of checking.
+ /// \param TemplateIDRange The source range of the template id that
+ /// caused the constraints check.
+ /// \param Satisfaction if true is returned, will contain details of the
+ /// satisfaction, with enough information to diagnose an unsatisfied
+ /// expression.
+ /// \returns true if an error occurred and satisfaction could not be checked,
+ /// false otherwise.
+ bool CheckConstraintSatisfaction(
+ const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
+ llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
+ const MultiLevelTemplateArgumentList &TemplateArgList,
+ SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
+
+ /// \brief Check whether the given non-dependent constraint expression is
+ /// satisfied. Returns false and updates Satisfaction with the satisfaction
+ /// verdict if successful, emits a diagnostic and returns true if an error
+ /// occurred and satisfaction could not be determined.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool CheckConstraintSatisfaction(const Expr *ConstraintExpr,
+ ConstraintSatisfaction &Satisfaction);
+
+ /// Check whether the given function decl's trailing requires clause is
+ /// satisfied, if any. Returns false and updates Satisfaction with the
+ /// satisfaction verdict if successful, emits a diagnostic and returns true if
+ /// an error occurred and satisfaction could not be determined.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool CheckFunctionConstraints(const FunctionDecl *FD,
+ ConstraintSatisfaction &Satisfaction,
+ SourceLocation UsageLoc = SourceLocation(),
+ bool ForOverloadResolution = false);
+
+ // Calculates whether two constraint expressions are equal irrespective of a
+ // difference in 'depth'. This takes a pair of optional 'NamedDecl's 'Old' and
+ // 'New', which are the "source" of the constraint, since this is necessary
+ // for figuring out the relative 'depth' of the constraint. The depth of the
+ // 'primary template' and the 'instantiated from' templates aren't necessarily
+ // the same, such as a case when one is a 'friend' defined in a class.
+ bool AreConstraintExpressionsEqual(const NamedDecl *Old,
+ const Expr *OldConstr,
+ const TemplateCompareNewDeclInfo &New,
+ const Expr *NewConstr);
+
+ // Calculates whether the friend function depends on an enclosing template for
+ // the purposes of [temp.friend] p9.
+ bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD);
+
+ /// \brief Ensure that the given template arguments satisfy the constraints
+ /// associated with the given template, emitting a diagnostic if they do not.
+ ///
+ /// \param Template The template to which the template arguments are being
+ /// provided.
+ ///
+ /// \param TemplateArgs The converted, canonicalized template arguments.
+ ///
+ /// \param TemplateIDRange The source range of the template id that
+ /// caused the constraints check.
+ ///
+ /// \returns true if the constrains are not satisfied or could not be checked
+ /// for satisfaction, false if the constraints are satisfied.
+ bool EnsureTemplateArgumentListConstraints(
+ TemplateDecl *Template,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceRange TemplateIDRange);
+
+ bool CheckInstantiatedFunctionTemplateConstraints(
+ SourceLocation PointOfInstantiation, FunctionDecl *Decl,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ ConstraintSatisfaction &Satisfaction);
+
+ /// \brief Emit diagnostics explaining why a constraint expression was deemed
+ /// unsatisfied.
+ /// \param First whether this is the first time an unsatisfied constraint is
+ /// diagnosed for this error.
+ void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
+ bool First = true);
+
+ /// \brief Emit diagnostics explaining why a constraint expression was deemed
+ /// unsatisfied.
+ void
+ DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
+ bool First = true);
+
+ const NormalizedConstraint *getNormalizedAssociatedConstraints(
+ 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
+ /// partial ordering of constraints.
+ ///
+ /// \param Result If no error occurred, receives the result of true if D1 is
+ /// 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);
+
+ /// 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,
+ ArrayRef<const Expr *> AC2);
+
+ /// Used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
+ /// the case of lambdas) set up the LocalInstantiationScope of the current
+ /// function.
+ bool
+ SetupConstraintScope(FunctionDecl *FD,
+ std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
+ const MultiLevelTemplateArgumentList &MLTAL,
+ LocalInstantiationScope &Scope);
+
+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;
+ /// 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::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
+ SatisfactionCache;
+
+ // The current stack of constraint satisfactions, so we can exit-early.
+ llvm::SmallVector<SatisfactionStackEntryTy, 10> SatisfactionStack;
+};
+
+} // namespace clang
#endif // LLVM_CLANG_SEMA_SEMACONCEPT_H
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index eb7447fa038e4..175e0bce683f7 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -31,6 +31,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenACC.h"
@@ -268,7 +269,7 @@ 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();
}
@@ -330,7 +331,7 @@ Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
}
bool PossibleNonPrimary;
bool IsConstraintExpr =
- Actions.CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary,
+ Actions.Concept().CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary,
IsTrailingRequiresClause);
if (!IsConstraintExpr || PossibleNonPrimary) {
// Atomic constraint might be an unparenthesized non-primary expression
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index f847c49920cf3..e3f9648db1793 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -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
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 202dd86c67f62..3f92eac2e5769 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -88,9 +88,10 @@ class LogicalBinOp {
};
}
-bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
+bool SemaConcept::CheckConstraintExpression(const Expr *ConstraintExpression,
Token NextToken, bool *PossibleNonPrimary,
bool IsTrailingRequiresClause) {
+ ASTContext &Context = getASTContext();
// C++2a [temp.constr.atomic]p1
// ..E shall be a constant expression of type bool.
@@ -126,7 +127,7 @@ bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
(IsTrailingRequiresClause ||
(Type->isDependentType() &&
isa<UnresolvedLookupExpr>(ConstraintExpression) &&
- !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
+ !dyn_cast_if_present<LambdaScopeInfo>(SemaRef.getCurFunction())) ||
Type->isFunctionType() ||
Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
// We have the following case:
@@ -166,13 +167,13 @@ struct SatisfactionStackRAII {
const llvm::FoldingSetNodeID &FSNID)
: SemaRef(SemaRef) {
if (ND) {
- SemaRef.PushSatisfactionStackEntry(ND, FSNID);
+ SemaRef.Concept().PushSatisfactionStackEntry(ND, FSNID);
Inserted = true;
}
}
~SatisfactionStackRAII() {
if (Inserted)
- SemaRef.PopSatisfactionStackEntry();
+ SemaRef.Concept().PopSatisfactionStackEntry();
}
};
} // namespace
@@ -323,7 +324,7 @@ DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
// expression, or when trying to determine the constexpr-ness of special
// members. Otherwise we could just use the
// Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
- if (S.SatisfactionStackContains(Templ, ID)) {
+ if (S.Concept().SatisfactionStackContains(Templ, ID)) {
S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
<< const_cast<Expr *>(E) << E->getSourceRange();
return true;
@@ -401,7 +402,7 @@ static ExprResult calculateConstraintSatisfaction(
}
}
- if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
+ if (!S.Concept().CheckConstraintExpression(SubstitutedExpression.get()))
return ExprError();
// [temp.constr.atomic]p3: To determine if an atomic constraint is
@@ -472,7 +473,7 @@ static bool CheckConstraintSatisfaction(
return false;
}
-bool Sema::CheckConstraintSatisfaction(
+bool SemaConcept::CheckConstraintSatisfaction(
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
const MultiLevelTemplateArgumentList &TemplateArgsLists,
@@ -483,7 +484,7 @@ bool Sema::CheckConstraintSatisfaction(
}
if (!Template) {
return ::CheckConstraintSatisfaction(
- *this, nullptr, ConstraintExprs, ConvertedConstraints,
+ SemaRef, nullptr, ConstraintExprs, ConvertedConstraints,
TemplateArgsLists, TemplateIDRange, OutSatisfaction);
}
@@ -497,7 +498,7 @@ bool Sema::CheckConstraintSatisfaction(
List.Args.end());
llvm::FoldingSetNodeID ID;
- ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
+ ConstraintSatisfaction::Profile(ID, SemaRef.Context, Template, FlattenedArgs);
void *InsertPos;
if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
OutSatisfaction = *Cached;
@@ -506,7 +507,7 @@ bool Sema::CheckConstraintSatisfaction(
auto Satisfaction =
std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
- if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
+ if (::CheckConstraintSatisfaction(SemaRef, Template, ConstraintExprs,
ConvertedConstraints, TemplateArgsLists,
TemplateIDRange, *Satisfaction)) {
OutSatisfaction = *Satisfaction;
@@ -535,63 +536,26 @@ bool Sema::CheckConstraintSatisfaction(
return false;
}
-bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
+bool SemaConcept::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
ConstraintSatisfaction &Satisfaction) {
return calculateConstraintSatisfaction(
- *this, ConstraintExpr, Satisfaction,
+ SemaRef, ConstraintExpr, Satisfaction,
[this](const Expr *AtomicExpr) -> ExprResult {
// We only do this to immitate lvalue-to-rvalue conversion.
- return PerformContextuallyConvertToBool(
+ return SemaRef.PerformContextuallyConvertToBool(
const_cast<Expr *>(AtomicExpr));
})
.isInvalid();
}
-bool Sema::addInstantiatedCapturesToScope(
- FunctionDecl *Function, const FunctionDecl *PatternDecl,
- LocalInstantiationScope &Scope,
- const MultiLevelTemplateArgumentList &TemplateArgs) {
- const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
- const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
-
- unsigned Instantiated = 0;
-
- auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
- unsigned Index) {
- ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
- if (CapturedVar->isInitCapture())
- Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
- };
-
- for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
- if (!CapturePattern.capturesVariable()) {
- Instantiated++;
- continue;
- }
- const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
- if (!CapturedPattern->isParameterPack()) {
- AddSingleCapture(CapturedPattern, Instantiated++);
- } else {
- Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
- std::optional<unsigned> NumArgumentsInExpansion =
- getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
- if (!NumArgumentsInExpansion)
- continue;
- for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
- AddSingleCapture(CapturedPattern, Instantiated++);
- }
- }
- return false;
-}
-
-bool Sema::SetupConstraintScope(
+bool SemaConcept::SetupConstraintScope(
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
const MultiLevelTemplateArgumentList &MLTAL,
LocalInstantiationScope &Scope) {
if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
- InstantiatingTemplate Inst(
- *this, FD->getPointOfInstantiation(),
+ Sema::InstantiatingTemplate Inst(
+ SemaRef, FD->getPointOfInstantiation(),
Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
SourceRange());
@@ -606,7 +570,7 @@ bool Sema::SetupConstraintScope(
if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
/*Final=*/false);
- if (addInstantiatedParametersToScope(
+ if (SemaRef.addInstantiatedParametersToScope(
FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
return true;
}
@@ -621,7 +585,7 @@ bool Sema::SetupConstraintScope(
PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
while (FromMemTempl->getInstantiatedFromMemberTemplate())
FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate();
- if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
+ if (SemaRef.addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
Scope, MLTAL))
return true;
}
@@ -636,8 +600,8 @@ bool Sema::SetupConstraintScope(
? FD->getInstantiatedFromMemberFunction()
: FD->getInstantiatedFromDecl();
- InstantiatingTemplate Inst(
- *this, FD->getPointOfInstantiation(),
+ Sema::InstantiatingTemplate Inst(
+ SemaRef, FD->getPointOfInstantiation(),
Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
SourceRange());
@@ -646,17 +610,20 @@ bool Sema::SetupConstraintScope(
// Case where this was not a template, but instantiated as a
// child-function.
- if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
+ if (SemaRef.addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
return true;
}
return false;
}
-// This function collects all of the template arguments for the purposes of
-// constraint-instantiation and checking.
-std::optional<MultiLevelTemplateArgumentList>
-Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
+/// This function collects all of the template arguments for the purposes of
+/// constraint-instantiation and checking.
+/// Used during constraint checking, sets up the constraint template argument
+/// lists, and calls SetupConstraintScope to set up the
+/// LocalInstantiationScope to have the proper set of ParVarDecls configured.
+static std::optional<MultiLevelTemplateArgumentList>
+SetupConstraintCheckingTemplateArgumentsAndScope(Sema &SemaRef,
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
LocalInstantiationScope &Scope) {
MultiLevelTemplateArgumentList MLTAL;
@@ -665,18 +632,18 @@ Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
// We need the entire list, since the constraint is completely uninstantiated
// at this point.
MLTAL =
- getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
+ SemaRef.getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
- if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
+ if (SemaRef.Concept().SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
return std::nullopt;
return MLTAL;
}
-bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
+bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
ConstraintSatisfaction &Satisfaction,
SourceLocation UsageLoc,
bool ForOverloadResolution) {
@@ -713,10 +680,10 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
CtxToSave = CtxToSave->getNonTransparentContext();
}
- ContextRAII SavedContext{*this, CtxToSave};
- LocalInstantiationScope Scope(*this, !ForOverloadResolution);
+ Sema::ContextRAII SavedContext{SemaRef, CtxToSave};
+ LocalInstantiationScope Scope(SemaRef, !ForOverloadResolution);
std::optional<MultiLevelTemplateArgumentList> MLTAL =
- SetupConstraintCheckingTemplateArgumentsAndScope(
+ SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef,
const_cast<FunctionDecl *>(FD), {}, Scope);
if (!MLTAL)
@@ -728,10 +695,10 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
ThisQuals = Method->getMethodQualifiers();
Record = const_cast<CXXRecordDecl *>(Method->getParent());
}
- CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals, Record != nullptr);
- LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
- *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
+ Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
+ SemaRef, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
ForOverloadResolution);
return CheckConstraintSatisfaction(
@@ -785,7 +752,7 @@ namespace {
} // namespace
static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
- Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
+ Sema &S, const TemplateCompareNewDeclInfo &DeclInfo,
const Expr *ConstrExpr) {
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
@@ -837,7 +804,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
return SubstConstr.get();
}
-bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
+bool SemaConcept::AreConstraintExpressionsEqual(const NamedDecl *Old,
const Expr *OldConstr,
const TemplateCompareNewDeclInfo &New,
const Expr *NewConstr) {
@@ -847,13 +814,13 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
if (const Expr *SubstConstr =
- SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,
+ SubstituteConstraintExpressionWithoutSatisfaction(SemaRef, Old,
OldConstr))
OldConstr = SubstConstr;
else
return false;
if (const Expr *SubstConstr =
- SubstituteConstraintExpressionWithoutSatisfaction(*this, New,
+ SubstituteConstraintExpressionWithoutSatisfaction(SemaRef, New,
NewConstr))
NewConstr = SubstConstr;
else
@@ -861,12 +828,12 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
}
llvm::FoldingSetNodeID ID1, ID2;
- OldConstr->Profile(ID1, Context, /*Canonical=*/true);
- NewConstr->Profile(ID2, Context, /*Canonical=*/true);
+ OldConstr->Profile(ID1, SemaRef.Context, /*Canonical=*/true);
+ NewConstr->Profile(ID2, SemaRef.Context, /*Canonical=*/true);
return ID1 == ID2;
}
-bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
+bool SemaConcept::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
assert(FD->getFriendObjectKind() && "Must be a friend!");
// The logic for non-templates is handled in ASTContext::isSameEntity, so we
@@ -878,16 +845,16 @@ bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
SmallVector<const Expr *, 3> ACs;
FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
- unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
+ unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(SemaRef, FD);
for (const Expr *Constraint : ACs)
- if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
+ if (SemaRef.ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
Constraint))
return true;
return false;
}
-bool Sema::EnsureTemplateArgumentListConstraints(
+bool SemaConcept::EnsureTemplateArgumentListConstraints(
TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
SourceRange TemplateIDRange) {
ConstraintSatisfaction Satisfaction;
@@ -900,13 +867,13 @@ bool Sema::EnsureTemplateArgumentListConstraints(
if (!Satisfaction.IsSatisfied) {
SmallString<128> TemplateArgString;
TemplateArgString = " ";
- TemplateArgString += getTemplateArgumentBindingsText(
+ TemplateArgString += SemaRef.getTemplateArgumentBindingsText(
TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
TemplateArgsLists.getInnermost().size());
Diag(TemplateIDRange.getBegin(),
diag::err_template_arg_list_constraints_not_satisfied)
- << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
+ << (int)SemaRef.getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
<< TemplateArgString << TemplateIDRange;
DiagnoseUnsatisfiedConstraint(Satisfaction);
return true;
@@ -914,7 +881,7 @@ bool Sema::EnsureTemplateArgumentListConstraints(
return false;
}
-bool Sema::CheckInstantiatedFunctionTemplateConstraints(
+bool SemaConcept::CheckInstantiatedFunctionTemplateConstraints(
SourceLocation PointOfInstantiation, FunctionDecl *Decl,
ArrayRef<TemplateArgument> TemplateArgs,
ConstraintSatisfaction &Satisfaction) {
@@ -931,11 +898,11 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
- Sema::ContextRAII savedContext(*this, Decl);
- LocalInstantiationScope Scope(*this);
+ Sema::ContextRAII savedContext(SemaRef, Decl);
+ LocalInstantiationScope Scope(SemaRef);
std::optional<MultiLevelTemplateArgumentList> MLTAL =
- SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
+ SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef, Decl, TemplateArgs,
Scope);
if (!MLTAL)
@@ -948,9 +915,9 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
Record = Method->getParent();
}
- CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
- LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
- *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals, Record != nullptr);
+ Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
+ SemaRef, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
llvm::SmallVector<Expr *, 1> Converted;
return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
@@ -1014,7 +981,7 @@ static void diagnoseUnsatisfiedRequirement(Sema &S,
diag::note_expr_requirement_constraints_not_satisfied)
<< (int)First << ConstraintExpr;
}
- S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
+ S.Concept().DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
break;
}
case concepts::ExprRequirement::SS_Satisfied:
@@ -1146,7 +1113,7 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
diag::note_concept_specialization_constraint_evaluated_to_false)
<< (int)First << CSE;
}
- S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
+ S.Concept().DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
return;
} else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
// FIXME: RequiresExpr should store dependent diagnostics.
@@ -1192,29 +1159,29 @@ static void diagnoseUnsatisfiedConstraintExpr(
}
void
-Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
+SemaConcept::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
bool First) {
assert(!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint");
for (auto &Pair : Satisfaction.Details) {
- diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
+ diagnoseUnsatisfiedConstraintExpr(SemaRef, Pair.first, Pair.second, First);
First = false;
}
}
-void Sema::DiagnoseUnsatisfiedConstraint(
+void SemaConcept::DiagnoseUnsatisfiedConstraint(
const ASTConstraintSatisfaction &Satisfaction,
bool First) {
assert(!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint");
for (auto &Pair : Satisfaction) {
- diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
+ diagnoseUnsatisfiedConstraintExpr(SemaRef, Pair.first, Pair.second, First);
First = false;
}
}
const NormalizedConstraint *
-Sema::getNormalizedAssociatedConstraints(
+SemaConcept::getNormalizedAssociatedConstraints(
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'
@@ -1224,13 +1191,13 @@ Sema::getNormalizedAssociatedConstraints(
auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
if (CacheEntry == NormalizationCache.end()) {
auto Normalized =
- NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
+ NormalizedConstraint::fromConstraintExprs(SemaRef, ConstrainedDecl,
AssociatedConstraints);
CacheEntry =
NormalizationCache
.try_emplace(ConstrainedDecl,
Normalized
- ? new (Context) NormalizedConstraint(
+ ? new (SemaRef.Context) NormalizedConstraint(
std::move(*Normalized))
: nullptr)
.first;
@@ -1377,7 +1344,7 @@ NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
// expression, the program is ill-formed; no diagnostic is required.
// [...]
ConceptDecl *CD = CSE->getNamedConcept();
- SubNF = S.getNormalizedAssociatedConstraints(CD,
+ SubNF = S.Concept().getNormalizedAssociatedConstraints(CD,
{CD->getConstraintExpr()});
if (!SubNF)
return std::nullopt;
@@ -1496,12 +1463,12 @@ static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
// In order to determine if a constraint P subsumes a constraint Q, P is
// transformed into disjunctive normal form, and Q is transformed into
// conjunctive normal form. [...]
- auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
+ auto *PNormalized = S.Concept().getNormalizedAssociatedConstraints(DP, P);
if (!PNormalized)
return true;
const NormalForm PDNF = makeDNF(*PNormalized);
- auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
+ auto *QNormalized = S.Concept().getNormalizedAssociatedConstraints(DQ, Q);
if (!QNormalized)
return true;
const NormalForm QCNF = makeCNF(*QNormalized);
@@ -1510,7 +1477,7 @@ static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
return false;
}
-bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
+bool SemaConcept::IsAtLeastAsConstrained(NamedDecl *D1,
MutableArrayRef<const Expr *> AC1,
NamedDecl *D2,
MutableArrayRef<const Expr *> AC2,
@@ -1547,33 +1514,33 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
return false;
}
- unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
- unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
+ unsigned Depth1 = CalculateTemplateDepthForConstraints(SemaRef, D1, true);
+ unsigned Depth2 = CalculateTemplateDepthForConstraints(SemaRef, D2, true);
for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
if (Depth2 > Depth1) {
- AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
+ AC1[I] = AdjustConstraintDepth(SemaRef, Depth2 - Depth1)
.TransformExpr(const_cast<Expr *>(AC1[I]))
.get();
} else if (Depth1 > Depth2) {
- AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
+ AC2[I] = AdjustConstraintDepth(SemaRef, Depth1 - Depth2)
.TransformExpr(const_cast<Expr *>(AC2[I]))
.get();
}
}
- if (subsumes(*this, D1, AC1, D2, AC2, Result,
+ if (subsumes(SemaRef, D1, AC1, D2, AC2, Result,
[this] (const AtomicConstraint &A, const AtomicConstraint &B) {
- return A.subsumes(Context, B);
+ return A.subsumes(SemaRef.Context, B);
}))
return true;
SubsumptionCache.try_emplace(Key, Result);
return false;
}
-bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
+bool SemaConcept::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
- if (isSFINAEContext())
+ if (SemaRef.isSFINAEContext())
// No need to work here because our notes would be discarded.
return false;
@@ -1582,13 +1549,13 @@ bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
auto NormalExprEvaluator =
[this] (const AtomicConstraint &A, const AtomicConstraint &B) {
- return A.subsumes(Context, B);
+ return A.subsumes(SemaRef.Context, B);
};
const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
auto IdenticalExprEvaluator =
[&] (const AtomicConstraint &A, const AtomicConstraint &B) {
- if (!A.hasMatchingParameterMapping(Context, B))
+ if (!A.hasMatchingParameterMapping(SemaRef.Context, B))
return false;
const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
if (EA == EB)
@@ -1597,8 +1564,8 @@ bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
// Not the same source level expression - are the expressions
// identical?
llvm::FoldingSetNodeID IDA, IDB;
- EA->Profile(IDA, Context, /*Canonical=*/true);
- EB->Profile(IDB, Context, /*Canonical=*/true);
+ EA->Profile(IDA, SemaRef.Context, /*Canonical=*/true);
+ EB->Profile(IDB, SemaRef.Context, /*Canonical=*/true);
if (IDA != IDB)
return false;
@@ -1609,7 +1576,7 @@ bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
{
// The subsumption checks might cause diagnostics
- SFINAETrap Trap(*this);
+ Sema::SFINAETrap Trap(SemaRef);
auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
if (!Normalized1)
return false;
@@ -1700,3 +1667,23 @@ concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
Value(T),
Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
: SS_Satisfied) {}
+
+clang::SemaConcept::SemaConcept(Sema &S) : SemaBase(S), SatisfactionCache(S.Context) {}
+
+clang::SemaConcept::~SemaConcept() {
+ // 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;
+}
+
+clang::SemaConcept::SatisfactionStackResetRAII::SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
+ SemaRef.Concept().SwapSatisfactionStack(BackupSatisfactionStack);
+}
+
+clang::SemaConcept::SatisfactionStackResetRAII::~SatisfactionStackResetRAII() {
+ SemaRef.Concept().SwapSatisfactionStack(BackupSatisfactionStack);
+}
\ No newline at end of file
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f2b9202255cd4..50715866b357d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -46,6 +46,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaHLSL.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
@@ -10901,7 +10902,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Precalculate whether this is a friend function template with a constraint
// that depends on an enclosing template, per [temp.friend]p9.
if (isFriend && FunctionTemplate &&
- FriendConstraintsDependOnEnclosingTemplate(NewFD)) {
+ Concept().FriendConstraintsDependOnEnclosingTemplate(NewFD)) {
NewFD->setFriendConstraintRefersToEnclosingTemplate(true);
// C++ [temp.friend]p9:
@@ -18977,7 +18978,7 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
SatisfactionStatus.push_back(true);
else {
ConstraintSatisfaction Satisfaction;
- if (S.CheckFunctionConstraints(Method, Satisfaction))
+ if (S.Concept().CheckFunctionConstraints(Method, Satisfaction))
SatisfactionStatus.push_back(false);
else
SatisfactionStatus.push_back(Satisfaction.IsSatisfied);
@@ -19012,7 +19013,7 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
AnotherMethodIsMoreConstrained = true;
break;
}
- if (S.IsAtLeastAsConstrained(OtherMethod, {OtherConstraints}, OrigMethod,
+ if (S.Concept().IsAtLeastAsConstrained(OtherMethod, {OtherConstraints}, OrigMethod,
{Constraints},
AnotherMethodIsMoreConstrained)) {
// There was an error with the constraints comparison. Exit the loop
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 8225381985052..a087b8592bdb0 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -43,6 +43,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenMP.h"
@@ -7466,7 +7467,7 @@ static bool specialMemberIsConstexpr(
// Suppress duplicate constraint checking here, in case a constraint check
// caused us to decide to do this. Any truely recursive checks will get
// caught during these checks anyway.
- Sema::SatisfactionStackResetRAII SSRAII{S};
+ SemaConcept::SatisfactionStackResetRAII SSRAII{S};
// If we're inheriting a constructor, see if we need to call it for this base
// class.
@@ -17585,8 +17586,8 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Diag(AssertExpr->getBeginLoc(), diag::err_static_assert_failed)
<< !HasMessage << Msg.str() << AssertExpr->getSourceRange();
ConstraintSatisfaction Satisfaction;
- if (!CheckConstraintSatisfaction(InnerCond, Satisfaction))
- DiagnoseUnsatisfiedConstraint(Satisfaction);
+ if (!Concept().CheckConstraintSatisfaction(InnerCond, Satisfaction))
+ Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
} else if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond)
&& !isa<IntegerLiteral>(InnerCond)) {
Diag(InnerCond->getBeginLoc(),
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 5ecfdee21f09d..b9ab327d37247 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -50,6 +50,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaFixItUtils.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
@@ -294,7 +295,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
// definition.
if (!SkipTrailingRequiresClause && FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckFunctionConstraints(FD, Satisfaction, Loc,
+ if (Concept().CheckFunctionConstraints(FD, Satisfaction, Loc,
/*ForOverloadResolution*/ true))
// A diagnostic will have already been generated (non-constant
// constraint expression, for example)
@@ -303,7 +304,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
Diag(Loc,
diag::err_reference_to_function_with_unsatisfied_constraints)
<< D;
- DiagnoseUnsatisfiedConstraint(Satisfaction);
+ Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
return true;
}
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e4601f7d6c47d..b75ff7f011ae8 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -39,6 +39,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/SemaObjC.h"
@@ -9389,7 +9390,7 @@ concepts::NestedRequirement *
Sema::BuildNestedRequirement(Expr *Constraint) {
ConstraintSatisfaction Satisfaction;
if (!Constraint->isInstantiationDependent() &&
- CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
+ Concept().CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
Constraint->getSourceRange(), Satisfaction))
return nullptr;
return new (Context) concepts::NestedRequirement(Context, Constraint,
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 2eb25237a0de6..4dc433cc0b6c7 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -32,6 +32,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/Template.h"
@@ -1518,7 +1519,7 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
if ((NewRC != nullptr) != (OldRC != nullptr))
return true;
if (NewRC &&
- !SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
+ !SemaRef.Concept().AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
return true;
}
@@ -7093,7 +7094,7 @@ void Sema::AddOverloadCandidate(
if (Function->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckFunctionConstraints(Function, Satisfaction, /*Loc*/ {},
+ if (Concept().CheckFunctionConstraints(Function, Satisfaction, /*Loc*/ {},
/*ForOverloadResolution*/ true) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
@@ -7611,7 +7612,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
if (Method->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckFunctionConstraints(Method, Satisfaction, /*Loc*/ {},
+ if (Concept().CheckFunctionConstraints(Method, Satisfaction, /*Loc*/ {},
/*ForOverloadResolution*/ true) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
@@ -8041,7 +8042,7 @@ void Sema::AddConversionCandidate(
if (Conversion->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckFunctionConstraints(Conversion, Satisfaction) ||
+ if (Concept().CheckFunctionConstraints(Conversion, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -8324,7 +8325,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
if (Conversion->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckFunctionConstraints(Conversion, Satisfaction, /*Loc*/ {},
+ if (Concept().CheckFunctionConstraints(Conversion, Satisfaction, /*Loc*/ {},
/*ForOverloadResolution*/ true) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
@@ -11070,7 +11071,7 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
if (FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (S.CheckFunctionConstraints(FD, Satisfaction, Loc))
+ if (S.Concept().CheckFunctionConstraints(FD, Satisfaction, Loc))
return false;
if (!Satisfaction.IsSatisfied) {
if (Complain) {
@@ -11089,7 +11090,7 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
} else
S.Diag(Loc, diag::err_addrof_function_constraints_not_satisfied)
<< FD;
- S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+ S.Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
}
return false;
}
@@ -11220,7 +11221,7 @@ MaybeDiagnoseAmbiguousConstraints(Sema &S, ArrayRef<OverloadCandidate> Cands) {
return;
// The diagnostic can only happen if there are associated constraints on
// both sides (there needs to be some identical atomic constraint).
- if (S.MaybeEmitAmbiguousAtomicConstraintsDiagnostic(FirstCand, FirstAC,
+ if (S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(FirstCand, FirstAC,
SecondCand, SecondAC))
// Just show the user one diagnostic, they'll probably figure it out
// from here.
@@ -11746,7 +11747,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
diag::note_ovl_candidate_unsatisfied_constraints)
<< TemplateArgString;
- S.DiagnoseUnsatisfiedConstraint(
+ S.Concept().DiagnoseUnsatisfiedConstraint(
static_cast<CNSInfo*>(DeductionFailure.Data)->Satisfaction);
return;
}
@@ -12134,9 +12135,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
<< (unsigned)FnKindPair.first << (unsigned)ocs_non_template
<< FnDesc /* Ignored */;
ConstraintSatisfaction Satisfaction;
- if (S.CheckFunctionConstraints(Fn, Satisfaction))
+ if (S.Concept().CheckFunctionConstraints(Fn, Satisfaction))
break;
- S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+ S.Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
}
}
}
@@ -12178,8 +12179,8 @@ static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
diag::note_ovl_surrogate_constraints_not_satisfied)
<< Cand->Surrogate;
ConstraintSatisfaction Satisfaction;
- if (S.CheckFunctionConstraints(Cand->Surrogate, Satisfaction))
- S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+ if (S.Concept().CheckFunctionConstraints(Cand->Surrogate, Satisfaction))
+ S.Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
} else {
S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
<< FnType;
@@ -13822,7 +13823,7 @@ DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op,
namespace {
class BuildRecoveryCallExprRAII {
Sema &SemaRef;
- Sema::SatisfactionStackResetRAII SatStack;
+ SemaConcept::SatisfactionStackResetRAII SatStack;
public:
BuildRecoveryCallExprRAII(Sema &S) : SemaRef(S), SatStack(S) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 4937cce4621f0..57ab161549450 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -34,6 +34,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
@@ -5166,7 +5167,7 @@ static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) {
SmallVector<const Expr *, 3> PartialAC, TemplateAC;
Template->getAssociatedConstraints(TemplateAC);
Partial->getAssociatedConstraints(PartialAC);
- S.MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Partial, PartialAC, Template,
+ S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Partial, PartialAC, Template,
TemplateAC);
}
@@ -5670,7 +5671,7 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
*this, ExpressionEvaluationContext::ConstantEvaluated, CSD};
if (!AreArgsDependent &&
- CheckConstraintSatisfaction(
+ Concept().CheckConstraintSatisfaction(
NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL,
SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
TemplateArgs->getRAngleLoc()),
@@ -6946,7 +6947,7 @@ bool Sema::CheckTemplateArgumentList(
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConceptInstantiation=*/true);
- if (EnsureTemplateArgumentListConstraints(
+ if (Concept().EnsureTemplateArgumentListConstraints(
Template, MLTAL,
SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) {
if (ConstraintsNotSatisfied)
@@ -8545,7 +8546,7 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
Template->getAssociatedConstraints(TemplateAC);
bool IsParamAtLeastAsConstrained;
- if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
+ if (Concept().IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
IsParamAtLeastAsConstrained))
return true;
if (!IsParamAtLeastAsConstrained) {
@@ -8555,7 +8556,7 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
Diag(Template->getLocation(), diag::note_entity_declared_at)
<< Template;
- MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
+ Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
TemplateAC);
return true;
}
@@ -8884,7 +8885,7 @@ Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
/// Match two template parameters within template parameter lists.
static bool MatchTemplateParameterKind(
Sema &S, NamedDecl *New,
- const Sema::TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old,
+ const TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old,
const NamedDecl *OldInstFrom, bool Complain,
Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
// Check the actual kind (type, non-type, template).
@@ -9019,7 +9020,7 @@ static bool MatchTemplateParameterKind(
}
if (NewC) {
- if (!S.AreConstraintExpressionsEqual(OldInstFrom, OldC, NewInstFrom,
+ if (!S.Concept().AreConstraintExpressionsEqual(OldInstFrom, OldC, NewInstFrom,
NewC)) {
if (Complain)
Diagnose();
@@ -9161,7 +9162,7 @@ bool Sema::TemplateParameterListsAreEqual(
}
if (NewRC) {
- if (!AreConstraintExpressionsEqual(OldInstFrom, OldRC, NewInstFrom,
+ if (!Concept().AreConstraintExpressionsEqual(OldInstFrom, OldRC, NewInstFrom,
NewRC)) {
if (Complain)
Diagnose();
@@ -10566,7 +10567,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
continue;
if (ConstraintSatisfaction Satisfaction;
Method->getTrailingRequiresClause() &&
- (CheckFunctionConstraints(Method, Satisfaction,
+ (Concept().CheckFunctionConstraints(Method, Satisfaction,
/*UsageLoc=*/Member->getLocation(),
/*ForOverloadResolution=*/true) ||
!Satisfaction.IsSatisfied))
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 41fd210f29d09..26c0f8472dde1 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -39,6 +39,7 @@
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/APInt.h"
@@ -3088,7 +3089,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
if (!Innermost)
MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
- if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
+ if (S.Concept().CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
Info.getLocation(),
Info.AssociatedConstraintsSatisfaction) ||
!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
@@ -3940,7 +3941,7 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
if (!PartialOverloading ||
(CanonicalBuilder.size() ==
FunctionTemplate->getTemplateParameters()->size())) {
- if (CheckInstantiatedFunctionTemplateConstraints(
+ if (Concept().CheckInstantiatedFunctionTemplateConstraints(
Info.getLocation(), Specialization, CanonicalBuilder,
Info.AssociatedConstraintsSatisfaction))
return TemplateDeductionResult::MiscellaneousDeductionFailure;
@@ -5100,7 +5101,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
return true;
MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted,
/*Final=*/false);
- if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
+ if (S.Concept().CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
MLTAL, TypeLoc.getLocalSourceRange(),
Satisfaction))
return true;
@@ -5118,7 +5119,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
S.Diag(TypeLoc.getConceptNameLoc(),
diag::err_placeholder_constraints_not_satisfied)
<< Deduced << Buf << TypeLoc.getLocalSourceRange();
- S.DiagnoseUnsatisfiedConstraint(Satisfaction);
+ S.Concept().DiagnoseUnsatisfiedConstraint(Satisfaction);
return true;
}
return false;
@@ -5853,9 +5854,9 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
FT1->getAssociatedConstraints(AC1);
FT2->getAssociatedConstraints(AC2);
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (IsAtLeastAsConstrained(FT1, AC1, FT2, AC2, AtLeastAsConstrained1))
+ if (Concept().IsAtLeastAsConstrained(FT1, AC1, FT2, AC2, AtLeastAsConstrained1))
return nullptr;
- if (IsAtLeastAsConstrained(FT2, AC2, FT1, AC1, AtLeastAsConstrained2))
+ if (Concept().IsAtLeastAsConstrained(FT2, AC2, FT1, AC1, AtLeastAsConstrained2))
return nullptr;
if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
return nullptr;
@@ -5996,9 +5997,9 @@ FunctionDecl *Sema::getMoreConstrainedFunction(FunctionDecl *FD1,
F1->getAssociatedConstraints(AC1);
F2->getAssociatedConstraints(AC2);
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (IsAtLeastAsConstrained(F1, AC1, F2, AC2, AtLeastAsConstrained1))
+ if (Concept().IsAtLeastAsConstrained(F1, AC1, F2, AC2, AtLeastAsConstrained1))
return nullptr;
- if (IsAtLeastAsConstrained(F2, AC2, F1, AC1, AtLeastAsConstrained2))
+ if (Concept().IsAtLeastAsConstrained(F2, AC2, F1, AC1, AtLeastAsConstrained2))
return nullptr;
if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
return nullptr;
@@ -6231,10 +6232,10 @@ getMoreSpecialized(Sema &S, QualType T1, QualType T2, TemplateLikeDecl *P1,
P1->getAssociatedConstraints(AC1);
P2->getAssociatedConstraints(AC2);
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (S.IsAtLeastAsConstrained(P1, AC1, P2, AC2, AtLeastAsConstrained1) ||
+ if (S.Concept().IsAtLeastAsConstrained(P1, AC1, P2, AC2, AtLeastAsConstrained1) ||
(IsMoreSpecialThanPrimaryCheck && !AtLeastAsConstrained1))
return nullptr;
- if (S.IsAtLeastAsConstrained(P2, AC2, P1, AC1, AtLeastAsConstrained2))
+ if (S.Concept().IsAtLeastAsConstrained(P2, AC2, P1, AC1, AtLeastAsConstrained2))
return nullptr;
if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
return nullptr;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 07626058c7977..537982d94570e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2802,7 +2802,7 @@ TemplateInstantiator::TransformNestedRequirement(
if (ConstrInst.isInvalid())
return nullptr;
llvm::SmallVector<Expr *> Result;
- if (!SemaRef.CheckConstraintSatisfaction(
+ if (!SemaRef.Concept().CheckConstraintSatisfaction(
nullptr, {Req->getConstraintExpr()}, Result, TemplateArgs,
Req->getConstraintExpr()->getSourceRange(), Satisfaction) &&
!Result.empty())
@@ -4135,7 +4135,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
if (Function->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckFunctionConstraints(Function, Satisfaction) ||
+ if (Concept().CheckFunctionConstraints(Function, Satisfaction) ||
!Satisfaction.IsSatisfied) {
continue;
}
@@ -4634,3 +4634,40 @@ NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
return nullptr;
}
+
+bool Sema::addInstantiatedCapturesToScope(
+ FunctionDecl *Function, const FunctionDecl *PatternDecl,
+ LocalInstantiationScope &Scope,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
+ const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
+
+ unsigned Instantiated = 0;
+
+ auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
+ unsigned Index) {
+ ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
+ if (CapturedVar->isInitCapture())
+ Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
+ };
+
+ for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
+ if (!CapturePattern.capturesVariable()) {
+ Instantiated++;
+ continue;
+ }
+ const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
+ if (!CapturedPattern->isParameterPack()) {
+ AddSingleCapture(CapturedPattern, Instantiated++);
+ } else {
+ Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
+ std::optional<unsigned> NumArgumentsInExpansion =
+ SemaRef.getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
+ if (!NumArgumentsInExpansion)
+ continue;
+ for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
+ AddSingleCapture(CapturedPattern, Instantiated++);
+ }
+ }
+ return false;
+}
>From ed40814844abfe84afe83a357ebdf06ac1bc5deb Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 18 May 2024 23:23:37 +0300
Subject: [PATCH 2/4] Move more functions to `SemaConcept`
---
clang/include/clang/Sema/Sema.h | 89 +--
clang/include/clang/Sema/SemaConcept.h | 119 ++++
clang/lib/Parse/ParseDecl.cpp | 3 +-
clang/lib/Parse/ParseDeclCXX.cpp | 4 +-
clang/lib/Parse/ParseExprCXX.cpp | 21 +-
clang/lib/Parse/ParseTemplate.cpp | 9 +-
clang/lib/Sema/SemaChecking.cpp | 6 -
clang/lib/Sema/SemaConcept.cpp | 653 ++++++++++++++++++
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Sema/SemaDeclCXX.cpp | 33 -
clang/lib/Sema/SemaExprCXX.cpp | 227 ------
clang/lib/Sema/SemaOverload.cpp | 6 +-
clang/lib/Sema/SemaTemplate.cpp | 383 +---------
clang/lib/Sema/SemaTemplateDeduction.cpp | 32 -
clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 +-
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 +-
clang/lib/Sema/SemaType.cpp | 7 +-
clang/lib/Sema/TreeTransform.h | 15 +-
18 files changed, 824 insertions(+), 790 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e92eb929e62e..06be666027742 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2036,8 +2036,6 @@ class Sema final : public SemaBase {
void CheckTCBEnforcement(const SourceLocation CallExprLoc,
const NamedDecl *Callee);
- void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc);
-
private:
void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const ArraySubscriptExpr *ASE = nullptr,
@@ -4735,9 +4733,6 @@ class Sema final : public SemaBase {
void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind,
StringLiteral *DeletedMessage = nullptr);
- void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
- ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
- ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
NamedDecl *
ActOnDecompositionDeclarator(Scope *S, Declarator &D,
@@ -6819,45 +6814,6 @@ class Sema final : public SemaBase {
bool IsIfExists, CXXScopeSpec &SS,
UnqualifiedId &Name);
- RequiresExprBodyDecl *
- ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
- ArrayRef<ParmVarDecl *> LocalParameters,
- Scope *BodyScope);
- void ActOnFinishRequiresExpr();
- concepts::Requirement *ActOnSimpleRequirement(Expr *E);
- concepts::Requirement *ActOnTypeRequirement(SourceLocation TypenameKWLoc,
- CXXScopeSpec &SS,
- SourceLocation NameLoc,
- const IdentifierInfo *TypeName,
- TemplateIdAnnotation *TemplateId);
- concepts::Requirement *ActOnCompoundRequirement(Expr *E,
- SourceLocation NoexceptLoc);
- concepts::Requirement *ActOnCompoundRequirement(
- Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstraint, unsigned Depth);
- concepts::Requirement *ActOnNestedRequirement(Expr *Constraint);
- concepts::ExprRequirement *BuildExprRequirement(
- Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc,
- concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
- concepts::ExprRequirement *BuildExprRequirement(
- concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag,
- bool IsSatisfied, SourceLocation NoexceptLoc,
- concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
- concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type);
- concepts::TypeRequirement *BuildTypeRequirement(
- concepts::Requirement::SubstitutionDiagnostic *SubstDiag);
- concepts::NestedRequirement *BuildNestedRequirement(Expr *E);
- concepts::NestedRequirement *
- BuildNestedRequirement(StringRef InvalidConstraintEntity,
- const ASTConstraintSatisfaction &Satisfaction);
- ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc,
- RequiresExprBodyDecl *Body,
- SourceLocation LParenLoc,
- ArrayRef<ParmVarDecl *> LocalParameters,
- SourceLocation RParenLoc,
- ArrayRef<concepts::Requirement *> Requirements,
- SourceLocation ClosingBraceLoc);
-
private:
ExprResult BuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
bool IsDelete);
@@ -8855,30 +8811,6 @@ class Sema final : public SemaBase {
unsigned Position, SourceLocation EqualLoc,
ParsedType DefaultArg, bool HasTypeConstraint);
- bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
-
- bool ActOnTypeConstraint(const CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstraint,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc);
- bool BuildTypeConstraint(const CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstraint,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc,
- bool AllowUnexpandedPack);
-
- bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
- DeclarationNameInfo NameInfo,
- ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
- const TemplateArgumentListInfo *TemplateArgs,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc);
-
- bool AttachTypeConstraint(AutoTypeLoc TL,
- NonTypeTemplateParmDecl *NewConstrainedParm,
- NonTypeTemplateParmDecl *OrigConstrainedParm,
- SourceLocation EllipsisLoc);
-
bool RequireStructuralType(QualType T, SourceLocation Loc);
QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
@@ -8982,12 +8914,6 @@ class Sema final : public SemaBase {
SourceLocation TemplateLoc,
const TemplateArgumentListInfo *TemplateArgs);
- ExprResult
- CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &ConceptNameInfo,
- NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
- const TemplateArgumentListInfo *TemplateArgs);
-
void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
@@ -9329,15 +9255,6 @@ class Sema final : public SemaBase {
void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD);
- Decl *ActOnConceptDefinition(Scope *S,
- MultiTemplateParamsArg TemplateParameterLists,
- const IdentifierInfo *Name,
- SourceLocation NameLoc, Expr *ConstraintExpr,
- const ParsedAttributesView &Attrs);
-
- void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
- bool &AddToScope);
-
TypeResult ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
const CXXScopeSpec &SS,
const IdentifierInfo *Name,
@@ -9354,6 +9271,9 @@ class Sema final : public SemaBase {
void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec);
void checkSpecializationReachability(SourceLocation Loc, NamedDecl *Spec);
+ TemplateArgumentListInfo
+ makeTemplateArgumentListInfo(TemplateIdAnnotation &TemplateId);
+
///@}
//
@@ -9621,9 +9541,6 @@ class Sema final : public SemaBase {
const PartialDiagnostic &CandidateDiag,
bool Complain = true, QualType TargetType = QualType());
- FunctionDecl *getMoreConstrainedFunction(FunctionDecl *FD1,
- FunctionDecl *FD2);
-
///@}
//
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 7104e91f24b61..1e24921354cdc 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -14,13 +14,35 @@
#define LLVM_CLANG_SEMA_SEMACONCEPT_H
#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprConcepts.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Token.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/ParsedAttr.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaBase.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include <optional>
#include <string>
#include <utility>
@@ -153,6 +175,7 @@ struct NormalizedConstraint {
};
class LocalInstantiationScope;
+class LookupResult;
class MultiLevelTemplateArgumentList;
// A struct to represent the 'new' declaration, which is either itself just
@@ -399,6 +422,102 @@ class SemaConcept : public SemaBase {
const MultiLevelTemplateArgumentList &MLTAL,
LocalInstantiationScope &Scope);
+ RequiresExprBodyDecl *
+ ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
+ ArrayRef<ParmVarDecl *> LocalParameters,
+ Scope *BodyScope);
+ void ActOnFinishRequiresExpr();
+ concepts::Requirement *ActOnSimpleRequirement(Expr *E);
+ concepts::Requirement *ActOnTypeRequirement(SourceLocation TypenameKWLoc,
+ CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ const IdentifierInfo *TypeName,
+ TemplateIdAnnotation *TemplateId);
+ concepts::Requirement *ActOnCompoundRequirement(Expr *E,
+ SourceLocation NoexceptLoc);
+ concepts::Requirement *ActOnCompoundRequirement(
+ Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstraint, unsigned Depth);
+ concepts::Requirement *ActOnNestedRequirement(Expr *Constraint);
+ concepts::ExprRequirement *BuildExprRequirement(
+ Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc,
+ concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
+ concepts::ExprRequirement *BuildExprRequirement(
+ concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag,
+ bool IsSatisfied, SourceLocation NoexceptLoc,
+ concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
+ concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type);
+ concepts::TypeRequirement *BuildTypeRequirement(
+ concepts::Requirement::SubstitutionDiagnostic *SubstDiag);
+ concepts::NestedRequirement *BuildNestedRequirement(Expr *E);
+ concepts::NestedRequirement *
+ BuildNestedRequirement(StringRef InvalidConstraintEntity,
+ const ASTConstraintSatisfaction &Satisfaction);
+ ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc,
+ RequiresExprBodyDecl *Body,
+ SourceLocation LParenLoc,
+ ArrayRef<ParmVarDecl *> LocalParameters,
+ SourceLocation RParenLoc,
+ ArrayRef<concepts::Requirement *> Requirements,
+ SourceLocation ClosingBraceLoc);
+
+ bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
+
+ bool ActOnTypeConstraint(const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstraint,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc);
+ bool BuildTypeConstraint(const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstraint,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc,
+ bool AllowUnexpandedPack);
+
+ bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
+ DeclarationNameInfo NameInfo,
+ ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
+ const TemplateArgumentListInfo *TemplateArgs,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc);
+
+ bool AttachTypeConstraint(AutoTypeLoc TL,
+ NonTypeTemplateParmDecl *NewConstrainedParm,
+ NonTypeTemplateParmDecl *OrigConstrainedParm,
+ SourceLocation EllipsisLoc);
+
+ ExprResult
+ CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &ConceptNameInfo,
+ NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ Decl *ActOnConceptDefinition(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ const IdentifierInfo *Name,
+ SourceLocation NameLoc, Expr *ConstraintExpr,
+ const ParsedAttributesView &Attrs);
+
+ void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
+ bool &AddToScope);
+
+ void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
+ ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
+ ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
+
+ void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc);
+
+ /// Returns the more constrained function according to the rules of
+ /// partial ordering by constraints (C++ [temp.constr.order]).
+ ///
+ /// \param FD1 the first function
+ ///
+ /// \param FD2 the second function
+ ///
+ /// \returns the more constrained function. If neither function is
+ /// more constrained, returns NULL.
+ FunctionDecl *getMoreConstrainedFunction(FunctionDecl *FD1,
+ FunctionDecl *FD2);
+
private:
/// Caches pairs of template-like decls whose associated constraints were
/// checked for subsumption and whether or not the first's constraints did in
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 8405b44685ae4..bd66ef5318c80 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -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,7 +4083,7 @@ void Parser::ParseDeclarationSpecifiers(
if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
goto DoneWithDeclSpec;
- if (TemplateId && !isInvalid && Actions.CheckTypeConstraint(TemplateId))
+ if (TemplateId && !isInvalid && Actions.Concept().CheckTypeConstraint(TemplateId))
TemplateId = nullptr;
ConsumeAnnotationToken();
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 5eaec2b621e6f..a658c03eda4bc 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4290,7 +4290,7 @@ 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);
@@ -4299,7 +4299,7 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) {
ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);
TrailingRequiresClause =
- Actions.ActOnFinishTrailingRequiresClause(TrailingRequiresClause);
+ Actions.Concept().ActOnFinishTrailingRequiresClause(TrailingRequiresClause);
if (!D.isDeclarationOfFunction()) {
Diag(RequiresKWLoc,
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index e149b1a0fb5ef..224431846fc0f 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -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>
@@ -1418,7 +1419,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
ExprResult RequiresClause;
if (TryConsumeToken(tok::kw_requires)) {
RequiresClause =
- Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(
+ 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,7 @@ 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 +3697,7 @@ ExprResult Parser::ParseRequiresExpression() {
ConsumeAnnotationToken();
}
- Req = Actions.ActOnCompoundRequirement(
+ Req = Actions.Concept().ActOnCompoundRequirement(
Expression.get(), NoexceptLoc, SS, takeTemplateIdAnnotation(Tok),
TemplateParameterDepth);
ConsumeAnnotationToken();
@@ -3765,7 +3766,7 @@ ExprResult Parser::ParseRequiresExpression() {
break;
}
if (auto *Req =
- Actions.ActOnNestedRequirement(ConstraintExpr.get()))
+ Actions.Concept().ActOnNestedRequirement(ConstraintExpr.get()))
Requirements.push_back(Req);
else {
SkipUntil(tok::semi, tok::r_brace,
@@ -3810,7 +3811,7 @@ ExprResult Parser::ParseRequiresExpression() {
break;
}
- if (auto *Req = Actions.ActOnTypeRequirement(TypenameKWLoc, SS,
+ if (auto *Req = Actions.Concept().ActOnTypeRequirement(TypenameKWLoc, SS,
NameLoc, II,
TemplateId)) {
Requirements.push_back(Req);
@@ -3833,7 +3834,7 @@ 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 +3862,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());
}
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index a5130f56600e5..bd732dc50cf9d 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -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,7 +146,7 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(
if (TryConsumeToken(tok::kw_requires)) {
OptionalRequiresClauseConstraintER =
- Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(
+ Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
/*IsTrailingRequiresClause=*/false));
if (!OptionalRequiresClauseConstraintER.isUsable()) {
// Skip until the semi-colon or a '}'.
@@ -339,7 +340,7 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
DeclEnd = Tok.getLocation();
ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
Expr *ConstraintExpr = ConstraintExprResult.get();
- return Actions.ActOnConceptDefinition(getCurScope(),
+ return Actions.Concept().ActOnConceptDefinition(getCurScope(),
*TemplateInfo.TemplateParams, Id, IdLoc,
ConstraintExpr, Attrs);
}
@@ -763,7 +764,7 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
TypeConstraint != nullptr);
if (TypeConstraint) {
- Actions.ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,
+ Actions.Concept().ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,
cast<TemplateTypeParmDecl>(NewDecl),
EllipsisLoc);
}
@@ -800,7 +801,7 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
}
if (TryConsumeToken(tok::kw_requires)) {
OptionalRequiresClauseConstraintER =
- Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(
+ Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
/*IsTrailingRequiresClause=*/false));
if (!OptionalRequiresClauseConstraintER.isUsable()) {
SkipUntil(tok::comma, tok::greater, tok::greatergreater,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index f2dc8e9dd0050..ecd1821651140 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -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,
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 3f92eac2e5769..8957c1d658cb1 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1668,6 +1668,659 @@ concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
: SS_Satisfied) {}
+RequiresExprBodyDecl *
+SemaConcept::ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
+ ArrayRef<ParmVarDecl *> LocalParameters,
+ Scope *BodyScope) {
+ assert(BodyScope);
+
+ RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(SemaRef.Context, SemaRef.CurContext,
+ RequiresKWLoc);
+
+ SemaRef.PushDeclContext(BodyScope, Body);
+
+ for (ParmVarDecl *Param : LocalParameters) {
+ if (Param->hasDefaultArg())
+ // C++2a [expr.prim.req] p4
+ // [...] A local parameter of a requires-expression shall not have a
+ // default argument. [...]
+ Diag(Param->getDefaultArgRange().getBegin(),
+ diag::err_requires_expr_local_parameter_default_argument);
+ // Ignore default argument and move on
+
+ Param->setDeclContext(Body);
+ // If this has an identifier, add it to the scope stack.
+ if (Param->getIdentifier()) {
+ SemaRef.CheckShadow(BodyScope, Param);
+ SemaRef.PushOnScopeChains(Param, BodyScope);
+ }
+ }
+ return Body;
+}
+
+void SemaConcept::ActOnFinishRequiresExpr() {
+ assert(SemaRef.CurContext && "DeclContext imbalance!");
+ SemaRef.CurContext = SemaRef.CurContext->getLexicalParent();
+ assert(SemaRef.CurContext && "Popped translation unit!");
+}
+
+concepts::Requirement *SemaConcept::ActOnSimpleRequirement(Expr *E) {
+ return BuildExprRequirement(E, /*IsSimple=*/true,
+ /*NoexceptLoc=*/SourceLocation(),
+ /*ReturnTypeRequirement=*/{});
+}
+
+concepts::Requirement *SemaConcept::ActOnTypeRequirement(
+ SourceLocation TypenameKWLoc, CXXScopeSpec &SS, SourceLocation NameLoc,
+ const IdentifierInfo *TypeName, TemplateIdAnnotation *TemplateId) {
+ assert(((!TypeName && TemplateId) || (TypeName && !TemplateId)) &&
+ "Exactly one of TypeName and TemplateId must be specified.");
+ TypeSourceInfo *TSI = nullptr;
+ if (TypeName) {
+ QualType T =
+ SemaRef.CheckTypenameType(ElaboratedTypeKeyword::Typename, TypenameKWLoc,
+ SS.getWithLocInContext(SemaRef.Context), *TypeName, NameLoc,
+ &TSI, /*DeducedTSTContext=*/false);
+ if (T.isNull())
+ return nullptr;
+ } else {
+ ASTTemplateArgsPtr ArgsPtr(TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ TypeResult T = SemaRef.ActOnTypenameType(SemaRef.getCurScope(), TypenameKWLoc, SS,
+ TemplateId->TemplateKWLoc,
+ TemplateId->Template, TemplateId->Name,
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc, ArgsPtr,
+ TemplateId->RAngleLoc);
+ if (T.isInvalid())
+ return nullptr;
+ if (SemaRef.GetTypeFromParser(T.get(), &TSI).isNull())
+ return nullptr;
+ }
+ return BuildTypeRequirement(TSI);
+}
+
+concepts::Requirement *
+SemaConcept::ActOnCompoundRequirement(Expr *E, SourceLocation NoexceptLoc) {
+ return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc,
+ /*ReturnTypeRequirement=*/{});
+}
+
+concepts::Requirement *
+SemaConcept::ActOnCompoundRequirement(
+ Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstraint, unsigned Depth) {
+ // C++2a [expr.prim.req.compound] p1.3.3
+ // [..] the expression is deduced against an invented function template
+ // F [...] F is a void function template with a single type template
+ // parameter T declared with the constrained-parameter. Form a new
+ // cv-qualifier-seq cv by taking the union of const and volatile specifiers
+ // around the constrained-parameter. F has a single parameter whose
+ // type-specifier is cv T followed by the abstract-declarator. [...]
+ //
+ // The cv part is done in the calling function - we get the concept with
+ // arguments and the abstract declarator with the correct CV qualification and
+ // have to synthesize T and the single parameter of F.
+ auto &II = SemaRef.Context.Idents.get("expr-type");
+ auto *TParam = TemplateTypeParmDecl::Create(SemaRef.Context, SemaRef.CurContext,
+ SourceLocation(),
+ SourceLocation(), Depth,
+ /*Index=*/0, &II,
+ /*Typename=*/true,
+ /*ParameterPack=*/false,
+ /*HasTypeConstraint=*/true);
+
+ if (BuildTypeConstraint(SS, TypeConstraint, TParam,
+ /*EllipsisLoc=*/SourceLocation(),
+ /*AllowUnexpandedPack=*/true))
+ // Just produce a requirement with no type requirements.
+ return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc, {});
+
+ auto *TPL = TemplateParameterList::Create(SemaRef.Context, SourceLocation(),
+ SourceLocation(),
+ ArrayRef<NamedDecl *>(TParam),
+ SourceLocation(),
+ /*RequiresClause=*/nullptr);
+ return BuildExprRequirement(
+ E, /*IsSimple=*/false, NoexceptLoc,
+ concepts::ExprRequirement::ReturnTypeRequirement(TPL));
+}
+
+concepts::ExprRequirement *
+SemaConcept::BuildExprRequirement(
+ Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
+ concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
+ auto Status = concepts::ExprRequirement::SS_Satisfied;
+ ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr;
+ if (E->isInstantiationDependent() || E->getType()->isPlaceholderType() ||
+ ReturnTypeRequirement.isDependent())
+ Status = concepts::ExprRequirement::SS_Dependent;
+ else if (NoexceptLoc.isValid() && SemaRef.canThrow(E) == CanThrowResult::CT_Can)
+ Status = concepts::ExprRequirement::SS_NoexceptNotMet;
+ else if (ReturnTypeRequirement.isSubstitutionFailure())
+ Status = concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure;
+ else if (ReturnTypeRequirement.isTypeConstraint()) {
+ // C++2a [expr.prim.req]p1.3.3
+ // The immediately-declared constraint ([temp]) of decltype((E)) shall
+ // be satisfied.
+ TemplateParameterList *TPL =
+ ReturnTypeRequirement.getTypeConstraintTemplateParameterList();
+ QualType MatchedType =
+ SemaRef.Context.getReferenceQualifiedType(E).getCanonicalType();
+ llvm::SmallVector<TemplateArgument, 1> Args;
+ Args.push_back(TemplateArgument(MatchedType));
+
+ auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0));
+
+ MultiLevelTemplateArgumentList MLTAL(Param, Args, /*Final=*/false);
+ MLTAL.addOuterRetainedLevels(TPL->getDepth());
+ const TypeConstraint *TC = Param->getTypeConstraint();
+ assert(TC && "Type Constraint cannot be null here");
+ auto *IDC = TC->getImmediatelyDeclaredConstraint();
+ assert(IDC && "ImmediatelyDeclaredConstraint can't be null here.");
+ ExprResult Constraint = SemaRef.SubstExpr(IDC, MLTAL);
+ if (Constraint.isInvalid()) {
+ return new (SemaRef.Context) concepts::ExprRequirement(
+ concepts::createSubstDiagAt(SemaRef, IDC->getExprLoc(),
+ [&](llvm::raw_ostream &OS) {
+ IDC->printPretty(OS, /*Helper=*/nullptr,
+ SemaRef.getPrintingPolicy());
+ }),
+ IsSimple, NoexceptLoc, ReturnTypeRequirement);
+ }
+ SubstitutedConstraintExpr =
+ cast<ConceptSpecializationExpr>(Constraint.get());
+ if (!SubstitutedConstraintExpr->isSatisfied())
+ Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
+ }
+ return new (SemaRef.Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc,
+ ReturnTypeRequirement, Status,
+ SubstitutedConstraintExpr);
+}
+
+concepts::ExprRequirement *
+SemaConcept::BuildExprRequirement(
+ concepts::Requirement::SubstitutionDiagnostic *ExprSubstitutionDiagnostic,
+ bool IsSimple, SourceLocation NoexceptLoc,
+ concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
+ return new (SemaRef.Context) concepts::ExprRequirement(ExprSubstitutionDiagnostic,
+ IsSimple, NoexceptLoc,
+ ReturnTypeRequirement);
+}
+
+concepts::TypeRequirement *
+SemaConcept::BuildTypeRequirement(TypeSourceInfo *Type) {
+ return new (SemaRef.Context) concepts::TypeRequirement(Type);
+}
+
+concepts::TypeRequirement *
+SemaConcept::BuildTypeRequirement(
+ concepts::Requirement::SubstitutionDiagnostic *SubstDiag) {
+ return new (SemaRef.Context) concepts::TypeRequirement(SubstDiag);
+}
+
+concepts::Requirement *SemaConcept::ActOnNestedRequirement(Expr *Constraint) {
+ return BuildNestedRequirement(Constraint);
+}
+
+concepts::NestedRequirement *
+SemaConcept::BuildNestedRequirement(Expr *Constraint) {
+ ConstraintSatisfaction Satisfaction;
+ if (!Constraint->isInstantiationDependent() &&
+ CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
+ Constraint->getSourceRange(), Satisfaction))
+ return nullptr;
+ return new (SemaRef.Context) concepts::NestedRequirement(SemaRef.Context, Constraint,
+ Satisfaction);
+}
+
+concepts::NestedRequirement *
+SemaConcept::BuildNestedRequirement(StringRef InvalidConstraintEntity,
+ const ASTConstraintSatisfaction &Satisfaction) {
+ return new (SemaRef.Context) concepts::NestedRequirement(
+ InvalidConstraintEntity,
+ ASTConstraintSatisfaction::Rebuild(SemaRef.Context, Satisfaction));
+}
+
+ExprResult SemaConcept::ActOnRequiresExpr(
+ SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
+ SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
+ SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
+ SourceLocation ClosingBraceLoc) {
+ auto *RE = RequiresExpr::Create(SemaRef.Context, RequiresKWLoc, Body, LParenLoc,
+ LocalParameters, RParenLoc, Requirements,
+ ClosingBraceLoc);
+ if (SemaRef.DiagnoseUnexpandedParameterPackInRequiresExpr(RE))
+ return ExprError();
+ return RE;
+}
+
+bool SemaConcept::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {
+
+ TemplateName TN = TypeConstr->Template.get();
+ ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
+
+ // C++2a [temp.param]p4:
+ // [...] The concept designated by a type-constraint shall be a type
+ // concept ([temp.concept]).
+ if (!CD->isTypeConcept()) {
+ Diag(TypeConstr->TemplateNameLoc,
+ diag::err_type_constraint_non_type_concept);
+ return true;
+ }
+
+ bool WereArgsSpecified = TypeConstr->LAngleLoc.isValid();
+
+ if (!WereArgsSpecified &&
+ CD->getTemplateParameters()->getMinRequiredArguments() > 1) {
+ Diag(TypeConstr->TemplateNameLoc,
+ diag::err_type_constraint_missing_arguments)
+ << CD;
+ return true;
+ }
+ return false;
+}
+
+bool SemaConcept::ActOnTypeConstraint(const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstr,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc) {
+ return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
+ false);
+}
+
+bool SemaConcept::BuildTypeConstraint(const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstr,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc,
+ bool AllowUnexpandedPack) {
+
+ if (CheckTypeConstraint(TypeConstr))
+ return true;
+
+ TemplateName TN = TypeConstr->Template.get();
+ ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
+ UsingShadowDecl *USD = TN.getAsUsingShadowDecl();
+
+ DeclarationNameInfo ConceptName(DeclarationName(TypeConstr->Name),
+ TypeConstr->TemplateNameLoc);
+
+ TemplateArgumentListInfo TemplateArgs;
+ if (TypeConstr->LAngleLoc.isValid()) {
+ TemplateArgs =
+ SemaRef.makeTemplateArgumentListInfo(*TypeConstr);
+
+ if (EllipsisLoc.isInvalid() && !AllowUnexpandedPack) {
+ for (TemplateArgumentLoc Arg : TemplateArgs.arguments()) {
+ if (SemaRef.DiagnoseUnexpandedParameterPack(Arg, Sema::UPPC_TypeConstraint))
+ return true;
+ }
+ }
+ }
+ return AttachTypeConstraint(
+ SS.isSet() ? SS.getWithLocInContext(SemaRef.Context) : NestedNameSpecifierLoc(),
+ ConceptName, CD, /*FoundDecl=*/USD ? cast<NamedDecl>(USD) : CD,
+ TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr,
+ ConstrainedParameter, EllipsisLoc);
+}
+
+template <typename ArgumentLocAppender>
+static ExprResult formImmediatelyDeclaredConstraint(
+ Sema &S, NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
+ ConceptDecl *NamedConcept, NamedDecl *FoundDecl, SourceLocation LAngleLoc,
+ SourceLocation RAngleLoc, QualType ConstrainedType,
+ SourceLocation ParamNameLoc, ArgumentLocAppender Appender,
+ SourceLocation EllipsisLoc) {
+
+ TemplateArgumentListInfo ConstraintArgs;
+ ConstraintArgs.addArgument(
+ S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
+ /*NTTPType=*/QualType(), ParamNameLoc));
+
+ ConstraintArgs.setRAngleLoc(RAngleLoc);
+ ConstraintArgs.setLAngleLoc(LAngleLoc);
+ Appender(ConstraintArgs);
+
+ // C++2a [temp.param]p4:
+ // [...] This constraint-expression E is called the immediately-declared
+ // constraint of T. [...]
+ CXXScopeSpec SS;
+ SS.Adopt(NS);
+ ExprResult ImmediatelyDeclaredConstraint = S.Concept().CheckConceptTemplateId(
+ SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo,
+ /*FoundDecl=*/FoundDecl ? FoundDecl : NamedConcept, NamedConcept,
+ &ConstraintArgs);
+ if (ImmediatelyDeclaredConstraint.isInvalid() || !EllipsisLoc.isValid())
+ return ImmediatelyDeclaredConstraint;
+
+ // C++2a [temp.param]p4:
+ // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
+ //
+ // We have the following case:
+ //
+ // template<typename T> concept C1 = true;
+ // template<C1... T> struct s1;
+ //
+ // The constraint: (C1<T> && ...)
+ //
+ // Note that the type of C1<T> is known to be 'bool', so we don't need to do
+ // any unqualified lookups for 'operator&&' here.
+ return S.BuildCXXFoldExpr(/*UnqualifiedLookup=*/nullptr,
+ /*LParenLoc=*/SourceLocation(),
+ ImmediatelyDeclaredConstraint.get(), BO_LAnd,
+ EllipsisLoc, /*RHS=*/nullptr,
+ /*RParenLoc=*/SourceLocation(),
+ /*NumExpansions=*/std::nullopt);
+}
+
+/// Attach a type-constraint to a template parameter.
+/// \returns true if an error occurred. This can happen if the
+/// immediately-declared constraint could not be formed (e.g. incorrect number
+/// of arguments for the named concept).
+bool SemaConcept::AttachTypeConstraint(NestedNameSpecifierLoc NS,
+ DeclarationNameInfo NameInfo,
+ ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
+ const TemplateArgumentListInfo *TemplateArgs,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc) {
+ // C++2a [temp.param]p4:
+ // [...] If Q is of the form C<A1, ..., An>, then let E' be
+ // C<T, A1, ..., An>. Otherwise, let E' be C<T>. [...]
+ const ASTTemplateArgumentListInfo *ArgsAsWritten =
+ TemplateArgs ? ASTTemplateArgumentListInfo::Create(SemaRef.Context,
+ *TemplateArgs) : nullptr;
+
+ QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);
+
+ ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
+ SemaRef, NS, NameInfo, NamedConcept, FoundDecl,
+ TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(),
+ TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(),
+ ParamAsArgument, ConstrainedParameter->getLocation(),
+ [&](TemplateArgumentListInfo &ConstraintArgs) {
+ if (TemplateArgs)
+ for (const auto &ArgLoc : TemplateArgs->arguments())
+ ConstraintArgs.addArgument(ArgLoc);
+ },
+ EllipsisLoc);
+ if (ImmediatelyDeclaredConstraint.isInvalid())
+ return true;
+
+ auto *CL = ConceptReference::Create(SemaRef.Context, /*NNS=*/NS,
+ /*TemplateKWLoc=*/SourceLocation{},
+ /*ConceptNameInfo=*/NameInfo,
+ /*FoundDecl=*/FoundDecl,
+ /*NamedConcept=*/NamedConcept,
+ /*ArgsWritten=*/ArgsAsWritten);
+ ConstrainedParameter->setTypeConstraint(CL,
+ ImmediatelyDeclaredConstraint.get());
+ return false;
+}
+
+bool SemaConcept::AttachTypeConstraint(AutoTypeLoc TL,
+ NonTypeTemplateParmDecl *NewConstrainedParm,
+ NonTypeTemplateParmDecl *OrigConstrainedParm,
+ SourceLocation EllipsisLoc) {
+ if (NewConstrainedParm->getType() != TL.getType() ||
+ TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
+ Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+ diag::err_unsupported_placeholder_constraint)
+ << NewConstrainedParm->getTypeSourceInfo()
+ ->getTypeLoc()
+ .getSourceRange();
+ return true;
+ }
+ // FIXME: Concepts: This should be the type of the placeholder, but this is
+ // unclear in the wording right now.
+ DeclRefExpr *Ref =
+ SemaRef.BuildDeclRefExpr(OrigConstrainedParm, OrigConstrainedParm->getType(),
+ VK_PRValue, OrigConstrainedParm->getLocation());
+ if (!Ref)
+ return true;
+ ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
+ SemaRef, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
+ TL.getNamedConcept(), /*FoundDecl=*/TL.getFoundDecl(), TL.getLAngleLoc(),
+ TL.getRAngleLoc(), SemaRef.BuildDecltypeType(Ref),
+ OrigConstrainedParm->getLocation(),
+ [&](TemplateArgumentListInfo &ConstraintArgs) {
+ for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
+ ConstraintArgs.addArgument(TL.getArgLoc(I));
+ },
+ EllipsisLoc);
+ if (ImmediatelyDeclaredConstraint.isInvalid() ||
+ !ImmediatelyDeclaredConstraint.isUsable())
+ return true;
+
+ NewConstrainedParm->setPlaceholderTypeConstraint(
+ ImmediatelyDeclaredConstraint.get());
+ return false;
+}
+
+ExprResult
+SemaConcept::CheckConceptTemplateId(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &ConceptNameInfo,
+ NamedDecl *FoundDecl,
+ ConceptDecl *NamedConcept,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ assert(NamedConcept && "A concept template id without a template?");
+ ASTContext &Context = getASTContext();
+
+ llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+ if (SemaRef.CheckTemplateArgumentList(
+ NamedConcept, ConceptNameInfo.getLoc(),
+ const_cast<TemplateArgumentListInfo &>(*TemplateArgs),
+ /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted,
+ /*UpdateArgsWithConversions=*/false))
+ return ExprError();
+
+ SemaRef.DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc());
+
+ auto *CSD = ImplicitConceptSpecializationDecl::Create(
+ Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
+ CanonicalConverted);
+ ConstraintSatisfaction Satisfaction;
+ bool AreArgsDependent =
+ TemplateSpecializationType::anyDependentTemplateArguments(
+ *TemplateArgs, CanonicalConverted);
+ MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted,
+ /*Final=*/false);
+ LocalInstantiationScope Scope(SemaRef);
+
+ EnterExpressionEvaluationContext EECtx{
+ SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated, CSD};
+
+ if (!AreArgsDependent &&
+ CheckConstraintSatisfaction(
+ NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL,
+ SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
+ TemplateArgs->getRAngleLoc()),
+ Satisfaction))
+ return ExprError();
+ auto *CL = ConceptReference::Create(
+ Context,
+ SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
+ TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
+ ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs));
+ return ConceptSpecializationExpr::Create(
+ Context, CL, CSD, AreArgsDependent ? nullptr : &Satisfaction);
+}
+
+Decl *SemaConcept::ActOnConceptDefinition(
+ Scope *S, MultiTemplateParamsArg TemplateParameterLists,
+ const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr,
+ const ParsedAttributesView &Attrs) {
+ DeclContext *DC = SemaRef.CurContext;
+
+ if (!DC->getRedeclContext()->isFileContext()) {
+ Diag(NameLoc,
+ diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
+ return nullptr;
+ }
+
+ if (TemplateParameterLists.size() > 1) {
+ Diag(NameLoc, diag::err_concept_extra_headers);
+ return nullptr;
+ }
+
+ TemplateParameterList *Params = TemplateParameterLists.front();
+
+ if (Params->size() == 0) {
+ Diag(NameLoc, diag::err_concept_no_parameters);
+ return nullptr;
+ }
+
+ // Ensure that the parameter pack, if present, is the last parameter in the
+ // template.
+ for (TemplateParameterList::const_iterator ParamIt = Params->begin(),
+ ParamEnd = Params->end();
+ ParamIt != ParamEnd; ++ParamIt) {
+ Decl const *Param = *ParamIt;
+ if (Param->isParameterPack()) {
+ if (++ParamIt == ParamEnd)
+ break;
+ Diag(Param->getLocation(),
+ diag::err_template_param_pack_must_be_last_template_parameter);
+ return nullptr;
+ }
+ }
+
+ if (SemaRef.DiagnoseUnexpandedParameterPack(ConstraintExpr))
+ return nullptr;
+
+ ConceptDecl *NewDecl =
+ ConceptDecl::Create(SemaRef.Context, DC, NameLoc, Name, Params, ConstraintExpr);
+
+ if (NewDecl->hasAssociatedConstraints()) {
+ // C++2a [temp.concept]p4:
+ // A concept shall not have associated constraints.
+ Diag(NameLoc, diag::err_concept_no_associated_constraints);
+ NewDecl->setInvalidDecl();
+ }
+
+ // Check for conflicting previous declaration.
+ DeclarationNameInfo NameInfo(NewDecl->getDeclName(), NameLoc);
+ LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
+ SemaRef.forRedeclarationInCurContext());
+ SemaRef.LookupName(Previous, S);
+ SemaRef.FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false,
+ /*AllowInlineNamespace*/false);
+ bool AddToScope = true;
+ CheckConceptRedefinition(NewDecl, Previous, AddToScope);
+
+ SemaRef.ActOnDocumentableDecl(NewDecl);
+ if (AddToScope)
+ SemaRef.PushOnScopeChains(NewDecl, S);
+
+ SemaRef.ProcessDeclAttributeList(S, NewDecl, Attrs);
+
+ return NewDecl;
+}
+
+void SemaConcept::CheckConceptRedefinition(ConceptDecl *NewDecl,
+ LookupResult &Previous, bool &AddToScope) {
+ AddToScope = true;
+
+ if (Previous.empty())
+ return;
+
+ auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()->getUnderlyingDecl());
+ if (!OldConcept) {
+ auto *Old = Previous.getRepresentativeDecl();
+ Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind)
+ << NewDecl->getDeclName();
+ SemaRef.notePreviousDefinition(Old, NewDecl->getLocation());
+ AddToScope = false;
+ return;
+ }
+ // Check if we can merge with a concept declaration.
+ bool IsSame = SemaRef.Context.isSameEntity(NewDecl, OldConcept);
+ if (!IsSame) {
+ Diag(NewDecl->getLocation(), diag::err_redefinition_different_concept)
+ << NewDecl->getDeclName();
+ SemaRef.notePreviousDefinition(OldConcept, NewDecl->getLocation());
+ AddToScope = false;
+ return;
+ }
+ if (SemaRef.hasReachableDefinition(OldConcept) &&
+ SemaRef.IsRedefinitionInModule(NewDecl, OldConcept)) {
+ Diag(NewDecl->getLocation(), diag::err_redefinition)
+ << NewDecl->getDeclName();
+ SemaRef.notePreviousDefinition(OldConcept, NewDecl->getLocation());
+ AddToScope = false;
+ return;
+ }
+ if (!Previous.isSingleResult()) {
+ // FIXME: we should produce an error in case of ambig and failed lookups.
+ // Other decls (e.g. namespaces) also have this shortcoming.
+ return;
+ }
+ // We unwrap canonical decl late to check for module visibility.
+ SemaRef.Context.setPrimaryMergedDecl(NewDecl, OldConcept->getCanonicalDecl());
+}
+
+void SemaConcept::ActOnStartTrailingRequiresClause(Scope *S, Declarator &D) {
+ if (!D.isFunctionDeclarator())
+ return;
+ auto &FTI = D.getFunctionTypeInfo();
+ if (!FTI.Params)
+ return;
+ for (auto &Param : ArrayRef<DeclaratorChunk::ParamInfo>(FTI.Params,
+ FTI.NumParams)) {
+ auto *ParamDecl = cast<NamedDecl>(Param.Param);
+ if (ParamDecl->getDeclName())
+ SemaRef.PushOnScopeChains(ParamDecl, S, /*AddToContext=*/false);
+ }
+}
+
+ExprResult SemaConcept::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
+ return ActOnRequiresClause(ConstraintExpr);
+}
+
+ExprResult SemaConcept::ActOnRequiresClause(ExprResult ConstraintExpr) {
+ if (ConstraintExpr.isInvalid())
+ return ExprError();
+
+ ConstraintExpr = SemaRef.CorrectDelayedTyposInExpr(ConstraintExpr);
+ if (ConstraintExpr.isInvalid())
+ return ExprError();
+
+ if (SemaRef.DiagnoseUnexpandedParameterPack(ConstraintExpr.get(),
+ Sema::UPPC_RequiresClause))
+ return ExprError();
+
+ return ConstraintExpr;
+}
+
+void SemaConcept::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) {
+ if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) {
+ SemaRef.DiagnoseUseOfDecl(Decl, Loc);
+ }
+}
+
+FunctionDecl *SemaConcept::getMoreConstrainedFunction(FunctionDecl *FD1,
+ FunctionDecl *FD2) {
+ assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() &&
+ "not for function templates");
+ FunctionDecl *F1 = FD1;
+ if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+ F1 = MF;
+ FunctionDecl *F2 = FD2;
+ if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+ F2 = MF;
+ llvm::SmallVector<const Expr *, 1> AC1, AC2;
+ F1->getAssociatedConstraints(AC1);
+ F2->getAssociatedConstraints(AC2);
+ bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+ if (IsAtLeastAsConstrained(F1, AC1, F2, AC2, AtLeastAsConstrained1))
+ return nullptr;
+ if (IsAtLeastAsConstrained(F2, AC2, F1, AC1, AtLeastAsConstrained2))
+ return nullptr;
+ if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+ return nullptr;
+ return AtLeastAsConstrained1 ? FD1 : FD2;
+}
+
clang::SemaConcept::SemaConcept(Sema &S) : SemaBase(S), SatisfactionCache(S.Context) {}
clang::SemaConcept::~SemaConcept() {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 50715866b357d..1aeb6b87b680a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7575,7 +7575,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
/*DiagID=*/0);
if (const AutoType *AutoT = R->getAs<AutoType>())
- CheckConstrainedAuto(
+ SemaRef.Concept().CheckConstrainedAuto(
AutoT,
TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc());
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a087b8592bdb0..8d99f970118b4 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4195,39 +4195,6 @@ void Sema::ActOnStartCXXInClassMemberInitializer() {
PushFunctionScope();
}
-void Sema::ActOnStartTrailingRequiresClause(Scope *S, Declarator &D) {
- if (!D.isFunctionDeclarator())
- return;
- auto &FTI = D.getFunctionTypeInfo();
- if (!FTI.Params)
- return;
- for (auto &Param : ArrayRef<DeclaratorChunk::ParamInfo>(FTI.Params,
- FTI.NumParams)) {
- auto *ParamDecl = cast<NamedDecl>(Param.Param);
- if (ParamDecl->getDeclName())
- PushOnScopeChains(ParamDecl, S, /*AddToContext=*/false);
- }
-}
-
-ExprResult Sema::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
- return ActOnRequiresClause(ConstraintExpr);
-}
-
-ExprResult Sema::ActOnRequiresClause(ExprResult ConstraintExpr) {
- if (ConstraintExpr.isInvalid())
- return ExprError();
-
- ConstraintExpr = CorrectDelayedTyposInExpr(ConstraintExpr);
- if (ConstraintExpr.isInvalid())
- return ExprError();
-
- if (DiagnoseUnexpandedParameterPack(ConstraintExpr.get(),
- UPPC_RequiresClause))
- return ExprError();
-
- return ConstraintExpr;
-}
-
ExprResult Sema::ConvertMemberDefaultInitExpression(FieldDecl *FD,
Expr *InitExpr,
SourceLocation InitLoc) {
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index b75ff7f011ae8..b926383dccc4a 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -9226,230 +9226,3 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
}
-
-concepts::Requirement *Sema::ActOnSimpleRequirement(Expr *E) {
- return BuildExprRequirement(E, /*IsSimple=*/true,
- /*NoexceptLoc=*/SourceLocation(),
- /*ReturnTypeRequirement=*/{});
-}
-
-concepts::Requirement *Sema::ActOnTypeRequirement(
- SourceLocation TypenameKWLoc, CXXScopeSpec &SS, SourceLocation NameLoc,
- const IdentifierInfo *TypeName, TemplateIdAnnotation *TemplateId) {
- assert(((!TypeName && TemplateId) || (TypeName && !TemplateId)) &&
- "Exactly one of TypeName and TemplateId must be specified.");
- TypeSourceInfo *TSI = nullptr;
- if (TypeName) {
- QualType T =
- CheckTypenameType(ElaboratedTypeKeyword::Typename, TypenameKWLoc,
- SS.getWithLocInContext(Context), *TypeName, NameLoc,
- &TSI, /*DeducedTSTContext=*/false);
- if (T.isNull())
- return nullptr;
- } else {
- ASTTemplateArgsPtr ArgsPtr(TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- TypeResult T = ActOnTypenameType(CurScope, TypenameKWLoc, SS,
- TemplateId->TemplateKWLoc,
- TemplateId->Template, TemplateId->Name,
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc, ArgsPtr,
- TemplateId->RAngleLoc);
- if (T.isInvalid())
- return nullptr;
- if (GetTypeFromParser(T.get(), &TSI).isNull())
- return nullptr;
- }
- return BuildTypeRequirement(TSI);
-}
-
-concepts::Requirement *
-Sema::ActOnCompoundRequirement(Expr *E, SourceLocation NoexceptLoc) {
- return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc,
- /*ReturnTypeRequirement=*/{});
-}
-
-concepts::Requirement *
-Sema::ActOnCompoundRequirement(
- Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstraint, unsigned Depth) {
- // C++2a [expr.prim.req.compound] p1.3.3
- // [..] the expression is deduced against an invented function template
- // F [...] F is a void function template with a single type template
- // parameter T declared with the constrained-parameter. Form a new
- // cv-qualifier-seq cv by taking the union of const and volatile specifiers
- // around the constrained-parameter. F has a single parameter whose
- // type-specifier is cv T followed by the abstract-declarator. [...]
- //
- // The cv part is done in the calling function - we get the concept with
- // arguments and the abstract declarator with the correct CV qualification and
- // have to synthesize T and the single parameter of F.
- auto &II = Context.Idents.get("expr-type");
- auto *TParam = TemplateTypeParmDecl::Create(Context, CurContext,
- SourceLocation(),
- SourceLocation(), Depth,
- /*Index=*/0, &II,
- /*Typename=*/true,
- /*ParameterPack=*/false,
- /*HasTypeConstraint=*/true);
-
- if (BuildTypeConstraint(SS, TypeConstraint, TParam,
- /*EllipsisLoc=*/SourceLocation(),
- /*AllowUnexpandedPack=*/true))
- // Just produce a requirement with no type requirements.
- return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc, {});
-
- auto *TPL = TemplateParameterList::Create(Context, SourceLocation(),
- SourceLocation(),
- ArrayRef<NamedDecl *>(TParam),
- SourceLocation(),
- /*RequiresClause=*/nullptr);
- return BuildExprRequirement(
- E, /*IsSimple=*/false, NoexceptLoc,
- concepts::ExprRequirement::ReturnTypeRequirement(TPL));
-}
-
-concepts::ExprRequirement *
-Sema::BuildExprRequirement(
- Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
- concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
- auto Status = concepts::ExprRequirement::SS_Satisfied;
- ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr;
- if (E->isInstantiationDependent() || E->getType()->isPlaceholderType() ||
- ReturnTypeRequirement.isDependent())
- Status = concepts::ExprRequirement::SS_Dependent;
- else if (NoexceptLoc.isValid() && canThrow(E) == CanThrowResult::CT_Can)
- Status = concepts::ExprRequirement::SS_NoexceptNotMet;
- else if (ReturnTypeRequirement.isSubstitutionFailure())
- Status = concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure;
- else if (ReturnTypeRequirement.isTypeConstraint()) {
- // C++2a [expr.prim.req]p1.3.3
- // The immediately-declared constraint ([temp]) of decltype((E)) shall
- // be satisfied.
- TemplateParameterList *TPL =
- ReturnTypeRequirement.getTypeConstraintTemplateParameterList();
- QualType MatchedType =
- Context.getReferenceQualifiedType(E).getCanonicalType();
- llvm::SmallVector<TemplateArgument, 1> Args;
- Args.push_back(TemplateArgument(MatchedType));
-
- auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0));
-
- MultiLevelTemplateArgumentList MLTAL(Param, Args, /*Final=*/false);
- MLTAL.addOuterRetainedLevels(TPL->getDepth());
- const TypeConstraint *TC = Param->getTypeConstraint();
- assert(TC && "Type Constraint cannot be null here");
- auto *IDC = TC->getImmediatelyDeclaredConstraint();
- assert(IDC && "ImmediatelyDeclaredConstraint can't be null here.");
- ExprResult Constraint = SubstExpr(IDC, MLTAL);
- if (Constraint.isInvalid()) {
- return new (Context) concepts::ExprRequirement(
- concepts::createSubstDiagAt(*this, IDC->getExprLoc(),
- [&](llvm::raw_ostream &OS) {
- IDC->printPretty(OS, /*Helper=*/nullptr,
- getPrintingPolicy());
- }),
- IsSimple, NoexceptLoc, ReturnTypeRequirement);
- }
- SubstitutedConstraintExpr =
- cast<ConceptSpecializationExpr>(Constraint.get());
- if (!SubstitutedConstraintExpr->isSatisfied())
- Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
- }
- return new (Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc,
- ReturnTypeRequirement, Status,
- SubstitutedConstraintExpr);
-}
-
-concepts::ExprRequirement *
-Sema::BuildExprRequirement(
- concepts::Requirement::SubstitutionDiagnostic *ExprSubstitutionDiagnostic,
- bool IsSimple, SourceLocation NoexceptLoc,
- concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
- return new (Context) concepts::ExprRequirement(ExprSubstitutionDiagnostic,
- IsSimple, NoexceptLoc,
- ReturnTypeRequirement);
-}
-
-concepts::TypeRequirement *
-Sema::BuildTypeRequirement(TypeSourceInfo *Type) {
- return new (Context) concepts::TypeRequirement(Type);
-}
-
-concepts::TypeRequirement *
-Sema::BuildTypeRequirement(
- concepts::Requirement::SubstitutionDiagnostic *SubstDiag) {
- return new (Context) concepts::TypeRequirement(SubstDiag);
-}
-
-concepts::Requirement *Sema::ActOnNestedRequirement(Expr *Constraint) {
- return BuildNestedRequirement(Constraint);
-}
-
-concepts::NestedRequirement *
-Sema::BuildNestedRequirement(Expr *Constraint) {
- ConstraintSatisfaction Satisfaction;
- if (!Constraint->isInstantiationDependent() &&
- Concept().CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
- Constraint->getSourceRange(), Satisfaction))
- return nullptr;
- return new (Context) concepts::NestedRequirement(Context, Constraint,
- Satisfaction);
-}
-
-concepts::NestedRequirement *
-Sema::BuildNestedRequirement(StringRef InvalidConstraintEntity,
- const ASTConstraintSatisfaction &Satisfaction) {
- return new (Context) concepts::NestedRequirement(
- InvalidConstraintEntity,
- ASTConstraintSatisfaction::Rebuild(Context, Satisfaction));
-}
-
-RequiresExprBodyDecl *
-Sema::ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
- ArrayRef<ParmVarDecl *> LocalParameters,
- Scope *BodyScope) {
- assert(BodyScope);
-
- RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(Context, CurContext,
- RequiresKWLoc);
-
- PushDeclContext(BodyScope, Body);
-
- for (ParmVarDecl *Param : LocalParameters) {
- if (Param->hasDefaultArg())
- // C++2a [expr.prim.req] p4
- // [...] A local parameter of a requires-expression shall not have a
- // default argument. [...]
- Diag(Param->getDefaultArgRange().getBegin(),
- diag::err_requires_expr_local_parameter_default_argument);
- // Ignore default argument and move on
-
- Param->setDeclContext(Body);
- // If this has an identifier, add it to the scope stack.
- if (Param->getIdentifier()) {
- CheckShadow(BodyScope, Param);
- PushOnScopeChains(Param, BodyScope);
- }
- }
- return Body;
-}
-
-void Sema::ActOnFinishRequiresExpr() {
- assert(CurContext && "DeclContext imbalance!");
- CurContext = CurContext->getLexicalParent();
- assert(CurContext && "Popped translation unit!");
-}
-
-ExprResult Sema::ActOnRequiresExpr(
- SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
- SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
- SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
- SourceLocation ClosingBraceLoc) {
- auto *RE = RequiresExpr::Create(Context, RequiresKWLoc, Body, LParenLoc,
- LocalParameters, RParenLoc, Requirements,
- ClosingBraceLoc);
- if (DiagnoseUnexpandedParameterPackInRequiresExpr(RE))
- return ExprError();
- return RE;
-}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4dc433cc0b6c7..f138db5467030 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -10636,7 +10636,7 @@ bool clang::isBetterOverloadCandidate(
// parameter-type-lists, and F1 is more constrained than F2 [...],
if (!Cand1IsSpecialization && !Cand2IsSpecialization &&
sameFunctionParameterTypeLists(S, Cand1, Cand2) &&
- S.getMoreConstrainedFunction(Cand1.Function, Cand2.Function) ==
+ S.Concept().getMoreConstrainedFunction(Cand1.Function, Cand2.Function) ==
Cand1.Function)
return true;
@@ -13342,7 +13342,7 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
}
// FD has the same CUDA prefernece than Result. Continue check
// constraints.
- FunctionDecl *MoreConstrained = getMoreConstrainedFunction(FD, Result);
+ FunctionDecl *MoreConstrained = Concept().getMoreConstrainedFunction(FD, Result);
if (MoreConstrained != FD) {
if (!MoreConstrained) {
IsResultAmbiguous = true;
@@ -13368,7 +13368,7 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
// constraints.
if (getLangOpts().CUDA && CheckCUDAPreference(Skipped, Result) != 0)
continue;
- if (!getMoreConstrainedFunction(Skipped, Result))
+ if (!Concept().getMoreConstrainedFunction(Skipped, Result))
return nullptr;
}
Pair = DAP;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 57ab161549450..73abb59857a97 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1099,217 +1099,16 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
}
/// Convert the parser's template argument list representation into our form.
-static TemplateArgumentListInfo
-makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
+TemplateArgumentListInfo
+Sema::makeTemplateArgumentListInfo(TemplateIdAnnotation &TemplateId) {
TemplateArgumentListInfo TemplateArgs(TemplateId.LAngleLoc,
TemplateId.RAngleLoc);
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId.getTemplateArgs(),
TemplateId.NumArgs);
- S.translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+ translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
return TemplateArgs;
}
-bool Sema::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {
-
- TemplateName TN = TypeConstr->Template.get();
- ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
-
- // C++2a [temp.param]p4:
- // [...] The concept designated by a type-constraint shall be a type
- // concept ([temp.concept]).
- if (!CD->isTypeConcept()) {
- Diag(TypeConstr->TemplateNameLoc,
- diag::err_type_constraint_non_type_concept);
- return true;
- }
-
- bool WereArgsSpecified = TypeConstr->LAngleLoc.isValid();
-
- if (!WereArgsSpecified &&
- CD->getTemplateParameters()->getMinRequiredArguments() > 1) {
- Diag(TypeConstr->TemplateNameLoc,
- diag::err_type_constraint_missing_arguments)
- << CD;
- return true;
- }
- return false;
-}
-
-bool Sema::ActOnTypeConstraint(const CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstr,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc) {
- return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
- false);
-}
-
-bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstr,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc,
- bool AllowUnexpandedPack) {
-
- if (CheckTypeConstraint(TypeConstr))
- return true;
-
- TemplateName TN = TypeConstr->Template.get();
- ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
- UsingShadowDecl *USD = TN.getAsUsingShadowDecl();
-
- DeclarationNameInfo ConceptName(DeclarationName(TypeConstr->Name),
- TypeConstr->TemplateNameLoc);
-
- TemplateArgumentListInfo TemplateArgs;
- if (TypeConstr->LAngleLoc.isValid()) {
- TemplateArgs =
- makeTemplateArgumentListInfo(*this, *TypeConstr);
-
- if (EllipsisLoc.isInvalid() && !AllowUnexpandedPack) {
- for (TemplateArgumentLoc Arg : TemplateArgs.arguments()) {
- if (DiagnoseUnexpandedParameterPack(Arg, UPPC_TypeConstraint))
- return true;
- }
- }
- }
- return AttachTypeConstraint(
- SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc(),
- ConceptName, CD, /*FoundDecl=*/USD ? cast<NamedDecl>(USD) : CD,
- TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr,
- ConstrainedParameter, EllipsisLoc);
-}
-
-template <typename ArgumentLocAppender>
-static ExprResult formImmediatelyDeclaredConstraint(
- Sema &S, NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
- ConceptDecl *NamedConcept, NamedDecl *FoundDecl, SourceLocation LAngleLoc,
- SourceLocation RAngleLoc, QualType ConstrainedType,
- SourceLocation ParamNameLoc, ArgumentLocAppender Appender,
- SourceLocation EllipsisLoc) {
-
- TemplateArgumentListInfo ConstraintArgs;
- ConstraintArgs.addArgument(
- S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
- /*NTTPType=*/QualType(), ParamNameLoc));
-
- ConstraintArgs.setRAngleLoc(RAngleLoc);
- ConstraintArgs.setLAngleLoc(LAngleLoc);
- Appender(ConstraintArgs);
-
- // C++2a [temp.param]p4:
- // [...] This constraint-expression E is called the immediately-declared
- // constraint of T. [...]
- CXXScopeSpec SS;
- SS.Adopt(NS);
- ExprResult ImmediatelyDeclaredConstraint = S.CheckConceptTemplateId(
- SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo,
- /*FoundDecl=*/FoundDecl ? FoundDecl : NamedConcept, NamedConcept,
- &ConstraintArgs);
- if (ImmediatelyDeclaredConstraint.isInvalid() || !EllipsisLoc.isValid())
- return ImmediatelyDeclaredConstraint;
-
- // C++2a [temp.param]p4:
- // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
- //
- // We have the following case:
- //
- // template<typename T> concept C1 = true;
- // template<C1... T> struct s1;
- //
- // The constraint: (C1<T> && ...)
- //
- // Note that the type of C1<T> is known to be 'bool', so we don't need to do
- // any unqualified lookups for 'operator&&' here.
- return S.BuildCXXFoldExpr(/*UnqualifiedLookup=*/nullptr,
- /*LParenLoc=*/SourceLocation(),
- ImmediatelyDeclaredConstraint.get(), BO_LAnd,
- EllipsisLoc, /*RHS=*/nullptr,
- /*RParenLoc=*/SourceLocation(),
- /*NumExpansions=*/std::nullopt);
-}
-
-/// Attach a type-constraint to a template parameter.
-/// \returns true if an error occurred. This can happen if the
-/// immediately-declared constraint could not be formed (e.g. incorrect number
-/// of arguments for the named concept).
-bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS,
- DeclarationNameInfo NameInfo,
- ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
- const TemplateArgumentListInfo *TemplateArgs,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc) {
- // C++2a [temp.param]p4:
- // [...] If Q is of the form C<A1, ..., An>, then let E' be
- // C<T, A1, ..., An>. Otherwise, let E' be C<T>. [...]
- const ASTTemplateArgumentListInfo *ArgsAsWritten =
- TemplateArgs ? ASTTemplateArgumentListInfo::Create(Context,
- *TemplateArgs) : nullptr;
-
- QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);
-
- ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
- *this, NS, NameInfo, NamedConcept, FoundDecl,
- TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(),
- TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(),
- ParamAsArgument, ConstrainedParameter->getLocation(),
- [&](TemplateArgumentListInfo &ConstraintArgs) {
- if (TemplateArgs)
- for (const auto &ArgLoc : TemplateArgs->arguments())
- ConstraintArgs.addArgument(ArgLoc);
- },
- EllipsisLoc);
- if (ImmediatelyDeclaredConstraint.isInvalid())
- return true;
-
- auto *CL = ConceptReference::Create(Context, /*NNS=*/NS,
- /*TemplateKWLoc=*/SourceLocation{},
- /*ConceptNameInfo=*/NameInfo,
- /*FoundDecl=*/FoundDecl,
- /*NamedConcept=*/NamedConcept,
- /*ArgsWritten=*/ArgsAsWritten);
- ConstrainedParameter->setTypeConstraint(CL,
- ImmediatelyDeclaredConstraint.get());
- return false;
-}
-
-bool Sema::AttachTypeConstraint(AutoTypeLoc TL,
- NonTypeTemplateParmDecl *NewConstrainedParm,
- NonTypeTemplateParmDecl *OrigConstrainedParm,
- SourceLocation EllipsisLoc) {
- if (NewConstrainedParm->getType() != TL.getType() ||
- TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
- Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
- diag::err_unsupported_placeholder_constraint)
- << NewConstrainedParm->getTypeSourceInfo()
- ->getTypeLoc()
- .getSourceRange();
- return true;
- }
- // FIXME: Concepts: This should be the type of the placeholder, but this is
- // unclear in the wording right now.
- DeclRefExpr *Ref =
- BuildDeclRefExpr(OrigConstrainedParm, OrigConstrainedParm->getType(),
- VK_PRValue, OrigConstrainedParm->getLocation());
- if (!Ref)
- return true;
- ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
- *this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
- TL.getNamedConcept(), /*FoundDecl=*/TL.getFoundDecl(), TL.getLAngleLoc(),
- TL.getRAngleLoc(), BuildDecltypeType(Ref),
- OrigConstrainedParm->getLocation(),
- [&](TemplateArgumentListInfo &ConstraintArgs) {
- for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
- ConstraintArgs.addArgument(TL.getArgLoc(I));
- },
- EllipsisLoc);
- if (ImmediatelyDeclaredConstraint.isInvalid() ||
- !ImmediatelyDeclaredConstraint.isUsable())
- return true;
-
- NewConstrainedParm->setPlaceholderTypeConstraint(
- ImmediatelyDeclaredConstraint.get());
- return false;
-}
-
/// Check that the type of a non-type template parameter is
/// well-formed.
///
@@ -1586,7 +1385,7 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
if (AutoTypeLoc TL = TInfo->getTypeLoc().getContainedAutoTypeLoc())
if (TL.isConstrained())
- if (AttachTypeConstraint(TL, Param, Param, D.getEllipsisLoc()))
+ if (Concept().AttachTypeConstraint(TL, Param, Param, D.getEllipsisLoc()))
Invalid = true;
if (Invalid)
@@ -5262,7 +5061,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
TemplateArgumentListInfo TemplateArgs =
- makeTemplateArgumentListInfo(*this, *TemplateId);
+ makeTemplateArgumentListInfo(*TemplateId);
SourceLocation TemplateNameLoc = D.getIdentifierLoc();
SourceLocation LAngleLoc = TemplateId->LAngleLoc;
SourceLocation RAngleLoc = TemplateId->RAngleLoc;
@@ -5637,55 +5436,6 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
}
}
-ExprResult
-Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &ConceptNameInfo,
- NamedDecl *FoundDecl,
- ConceptDecl *NamedConcept,
- const TemplateArgumentListInfo *TemplateArgs) {
- assert(NamedConcept && "A concept template id without a template?");
-
- llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
- if (CheckTemplateArgumentList(
- NamedConcept, ConceptNameInfo.getLoc(),
- const_cast<TemplateArgumentListInfo &>(*TemplateArgs),
- /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted,
- /*UpdateArgsWithConversions=*/false))
- return ExprError();
-
- DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc());
-
- auto *CSD = ImplicitConceptSpecializationDecl::Create(
- Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
- CanonicalConverted);
- ConstraintSatisfaction Satisfaction;
- bool AreArgsDependent =
- TemplateSpecializationType::anyDependentTemplateArguments(
- *TemplateArgs, CanonicalConverted);
- MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted,
- /*Final=*/false);
- LocalInstantiationScope Scope(*this);
-
- EnterExpressionEvaluationContext EECtx{
- *this, ExpressionEvaluationContext::ConstantEvaluated, CSD};
-
- if (!AreArgsDependent &&
- Concept().CheckConstraintSatisfaction(
- NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL,
- SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
- TemplateArgs->getRAngleLoc()),
- Satisfaction))
- return ExprError();
- auto *CL = ConceptReference::Create(
- Context,
- SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
- TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
- ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs));
- return ConceptSpecializationExpr::Create(
- Context, CL, CSD, AreArgsDependent ? nullptr : &Satisfaction);
-}
-
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
@@ -5724,7 +5474,7 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
}
if (R.getAsSingle<ConceptDecl>()) {
- return CheckConceptTemplateId(SS, TemplateKWLoc, R.getLookupNameInfo(),
+ return Concept().CheckConceptTemplateId(SS, TemplateKWLoc, R.getLookupNameInfo(),
R.getRepresentativeDecl(),
R.getAsSingle<ConceptDecl>(), TemplateArgs);
}
@@ -9602,7 +9352,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs =
- makeTemplateArgumentListInfo(*this, TemplateId);
+ makeTemplateArgumentListInfo(TemplateId);
// Check for unexpanded parameter packs in any of the template arguments.
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -9860,119 +9610,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
return NewDecl;
}
-Decl *Sema::ActOnConceptDefinition(
- Scope *S, MultiTemplateParamsArg TemplateParameterLists,
- const IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr,
- const ParsedAttributesView &Attrs) {
- DeclContext *DC = CurContext;
-
- if (!DC->getRedeclContext()->isFileContext()) {
- Diag(NameLoc,
- diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
- return nullptr;
- }
-
- if (TemplateParameterLists.size() > 1) {
- Diag(NameLoc, diag::err_concept_extra_headers);
- return nullptr;
- }
-
- TemplateParameterList *Params = TemplateParameterLists.front();
-
- if (Params->size() == 0) {
- Diag(NameLoc, diag::err_concept_no_parameters);
- return nullptr;
- }
-
- // Ensure that the parameter pack, if present, is the last parameter in the
- // template.
- for (TemplateParameterList::const_iterator ParamIt = Params->begin(),
- ParamEnd = Params->end();
- ParamIt != ParamEnd; ++ParamIt) {
- Decl const *Param = *ParamIt;
- if (Param->isParameterPack()) {
- if (++ParamIt == ParamEnd)
- break;
- Diag(Param->getLocation(),
- diag::err_template_param_pack_must_be_last_template_parameter);
- return nullptr;
- }
- }
-
- if (DiagnoseUnexpandedParameterPack(ConstraintExpr))
- return nullptr;
-
- ConceptDecl *NewDecl =
- ConceptDecl::Create(Context, DC, NameLoc, Name, Params, ConstraintExpr);
-
- if (NewDecl->hasAssociatedConstraints()) {
- // C++2a [temp.concept]p4:
- // A concept shall not have associated constraints.
- Diag(NameLoc, diag::err_concept_no_associated_constraints);
- NewDecl->setInvalidDecl();
- }
-
- // Check for conflicting previous declaration.
- DeclarationNameInfo NameInfo(NewDecl->getDeclName(), NameLoc);
- LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
- forRedeclarationInCurContext());
- LookupName(Previous, S);
- FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false,
- /*AllowInlineNamespace*/false);
- bool AddToScope = true;
- CheckConceptRedefinition(NewDecl, Previous, AddToScope);
-
- ActOnDocumentableDecl(NewDecl);
- if (AddToScope)
- PushOnScopeChains(NewDecl, S);
-
- ProcessDeclAttributeList(S, NewDecl, Attrs);
-
- return NewDecl;
-}
-
-void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl,
- LookupResult &Previous, bool &AddToScope) {
- AddToScope = true;
-
- if (Previous.empty())
- return;
-
- auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()->getUnderlyingDecl());
- if (!OldConcept) {
- auto *Old = Previous.getRepresentativeDecl();
- Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind)
- << NewDecl->getDeclName();
- notePreviousDefinition(Old, NewDecl->getLocation());
- AddToScope = false;
- return;
- }
- // Check if we can merge with a concept declaration.
- bool IsSame = Context.isSameEntity(NewDecl, OldConcept);
- if (!IsSame) {
- Diag(NewDecl->getLocation(), diag::err_redefinition_different_concept)
- << NewDecl->getDeclName();
- notePreviousDefinition(OldConcept, NewDecl->getLocation());
- AddToScope = false;
- return;
- }
- if (hasReachableDefinition(OldConcept) &&
- IsRedefinitionInModule(NewDecl, OldConcept)) {
- Diag(NewDecl->getLocation(), diag::err_redefinition)
- << NewDecl->getDeclName();
- notePreviousDefinition(OldConcept, NewDecl->getLocation());
- AddToScope = false;
- return;
- }
- if (!Previous.isSingleResult()) {
- // FIXME: we should produce an error in case of ambig and failed lookups.
- // Other decls (e.g. namespaces) also have this shortcoming.
- return;
- }
- // We unwrap canonical decl late to check for module visibility.
- Context.setPrimaryMergedDecl(NewDecl, OldConcept->getCanonicalDecl());
-}
-
/// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D, bool MinGW) {
@@ -10574,7 +10211,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
continue;
Candidates.push_back(Method);
FunctionDecl *MoreConstrained =
- Instantiation ? getMoreConstrainedFunction(
+ Instantiation ? Concept().getMoreConstrainedFunction(
Method, cast<FunctionDecl>(Instantiation))
: Method;
if (!MoreConstrained) {
@@ -11438,7 +11075,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// Translate the parser's template argument list into our AST format.
TemplateArgumentListInfo TemplateArgs =
- makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
+ makeTemplateArgumentListInfo(*D.getName().TemplateId);
DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
D.getIdentifierLoc(), TemplateArgs);
@@ -11519,7 +11156,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo TemplateArgs;
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
- TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
+ TemplateArgs = makeTemplateArgumentListInfo(*D.getName().TemplateId);
HasExplicitTemplateArgs = true;
}
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 26c0f8472dde1..25a36706b8039 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5974,38 +5974,6 @@ UnresolvedSetIterator Sema::getMostSpecialized(
return SpecEnd;
}
-/// Returns the more constrained function according to the rules of
-/// partial ordering by constraints (C++ [temp.constr.order]).
-///
-/// \param FD1 the first function
-///
-/// \param FD2 the second function
-///
-/// \returns the more constrained function. If neither function is
-/// more constrained, returns NULL.
-FunctionDecl *Sema::getMoreConstrainedFunction(FunctionDecl *FD1,
- FunctionDecl *FD2) {
- assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() &&
- "not for function templates");
- FunctionDecl *F1 = FD1;
- if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
- F1 = MF;
- FunctionDecl *F2 = FD2;
- if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
- F2 = MF;
- llvm::SmallVector<const Expr *, 1> AC1, AC2;
- F1->getAssociatedConstraints(AC1);
- F2->getAssociatedConstraints(AC2);
- bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (Concept().IsAtLeastAsConstrained(F1, AC1, F2, AC2, AtLeastAsConstrained1))
- return nullptr;
- if (Concept().IsAtLeastAsConstrained(F2, AC2, F1, AC1, AtLeastAsConstrained2))
- return nullptr;
- if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
- return nullptr;
- return AtLeastAsConstrained1 ? FD1 : FD2;
-}
-
/// Determine whether one partial specialization, P1, is at least as
/// specialized than another, P2.
///
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 537982d94570e..c2b6d151cdf45 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3131,7 +3131,7 @@ bool Sema::SubstTypeConstraint(
InstArgs))
return true;
}
- return AttachTypeConstraint(
+ return Concept().AttachTypeConstraint(
TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
TC->getNamedConcept(),
/*FoundDecl=*/TC->getConceptReference()->getFoundDecl(), &InstArgs, Inst,
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 381d79b2fcd46..729f7442cbe06 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -27,6 +27,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenMP.h"
@@ -3111,7 +3112,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
// Note: We attach the uninstantiated constriant here, so that it can be
// instantiated relative to the top level, like all our other
// constraints.
- if (SemaRef.AttachTypeConstraint(AutoLoc, /*NewConstrainedParm=*/Param,
+ if (SemaRef.Concept().AttachTypeConstraint(AutoLoc, /*NewConstrainedParm=*/Param,
/*OrigConstrainedParm=*/D, EllipsisLoc))
Invalid = true;
}
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index ef0b6b701a52c..f9f0ee6d99c9a 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -34,6 +34,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenMP.h"
@@ -3089,7 +3090,7 @@ InventTemplateParameter(TypeProcessingState &state, QualType T,
}
if (!Invalid) {
- S.AttachTypeConstraint(
+ S.Concept().AttachTypeConstraint(
AutoLoc.getNestedNameSpecifierLoc(), AutoLoc.getConceptNameInfo(),
AutoLoc.getNamedConcept(), /*FoundDecl=*/AutoLoc.getFoundDecl(),
AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr,
@@ -3122,7 +3123,7 @@ InventTemplateParameter(TypeProcessingState &state, QualType T,
TemplateId->Template.get().getAsUsingShadowDecl();
auto *CD =
cast<ConceptDecl>(TemplateId->Template.get().getAsTemplateDecl());
- S.AttachTypeConstraint(
+ S.Concept().AttachTypeConstraint(
D.getDeclSpec().getTypeSpecScope().getWithLocInContext(S.Context),
DeclarationNameInfo(DeclarationName(TemplateId->Name),
TemplateId->TemplateNameLoc),
@@ -6393,7 +6394,7 @@ TypeResult Sema::ActOnTypeName(Declarator &D) {
}
if (const AutoType *AutoT = T->getAs<AutoType>())
- CheckConstrainedAuto(
+ SemaRef.Concept().CheckConstrainedAuto(
AutoT,
TInfo->getTypeLoc().getContainedAutoTypeLoc().getConceptNameLoc());
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 29444f0edc2ae..0172b49ced0cf 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -37,6 +37,7 @@
#include "clang/Sema/Ownership.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaObjC.h"
@@ -3662,7 +3663,7 @@ class TreeTransform {
TemplateArgumentListInfo *TALI) {
CXXScopeSpec SS;
SS.Adopt(NNS);
- ExprResult Result = getSema().CheckConceptTemplateId(SS, TemplateKWLoc,
+ ExprResult Result = getSema().Concept().CheckConceptTemplateId(SS, TemplateKWLoc,
ConceptNameInfo,
FoundDecl,
NamedConcept, TALI);
@@ -3690,11 +3691,11 @@ class TreeTransform {
concepts::TypeRequirement *
RebuildTypeRequirement(
concepts::Requirement::SubstitutionDiagnostic *SubstDiag) {
- return SemaRef.BuildTypeRequirement(SubstDiag);
+ return SemaRef.Concept().BuildTypeRequirement(SubstDiag);
}
concepts::TypeRequirement *RebuildTypeRequirement(TypeSourceInfo *T) {
- return SemaRef.BuildTypeRequirement(T);
+ return SemaRef.Concept().BuildTypeRequirement(T);
}
concepts::ExprRequirement *
@@ -3702,26 +3703,26 @@ class TreeTransform {
concepts::Requirement::SubstitutionDiagnostic *SubstDiag, bool IsSimple,
SourceLocation NoexceptLoc,
concepts::ExprRequirement::ReturnTypeRequirement Ret) {
- return SemaRef.BuildExprRequirement(SubstDiag, IsSimple, NoexceptLoc,
+ return SemaRef.Concept().BuildExprRequirement(SubstDiag, IsSimple, NoexceptLoc,
std::move(Ret));
}
concepts::ExprRequirement *
RebuildExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
concepts::ExprRequirement::ReturnTypeRequirement Ret) {
- return SemaRef.BuildExprRequirement(E, IsSimple, NoexceptLoc,
+ return SemaRef.Concept().BuildExprRequirement(E, IsSimple, NoexceptLoc,
std::move(Ret));
}
concepts::NestedRequirement *
RebuildNestedRequirement(StringRef InvalidConstraintEntity,
const ASTConstraintSatisfaction &Satisfaction) {
- return SemaRef.BuildNestedRequirement(InvalidConstraintEntity,
+ return SemaRef.Concept().BuildNestedRequirement(InvalidConstraintEntity,
Satisfaction);
}
concepts::NestedRequirement *RebuildNestedRequirement(Expr *Constraint) {
- return SemaRef.BuildNestedRequirement(Constraint);
+ return SemaRef.Concept().BuildNestedRequirement(Constraint);
}
/// \brief Build a new Objective-C boxed expression.
>From 354e8ff9f82d26b3611766d6b78b5da76ec87e69 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 18 May 2024 23:28:18 +0300
Subject: [PATCH 3/4] Run clang-format
---
clang/include/clang/Sema/Sema.h | 3 +-
clang/include/clang/Sema/SemaConcept.h | 10 +-
clang/lib/Parse/ParseDecl.cpp | 5 +-
clang/lib/Parse/ParseDeclCXX.cpp | 4 +-
clang/lib/Parse/ParseExpr.cpp | 10 +-
clang/lib/Parse/ParseExprCXX.cpp | 19 +-
clang/lib/Parse/ParseTemplate.cpp | 20 +-
clang/lib/Sema/SemaConcept.cpp | 366 +++++++++---------
clang/lib/Sema/SemaDecl.cpp | 6 +-
clang/lib/Sema/SemaExpr.cpp | 2 +-
clang/lib/Sema/SemaOverload.cpp | 19 +-
clang/lib/Sema/SemaTemplate.cpp | 39 +-
clang/lib/Sema/SemaTemplateDeduction.cpp | 24 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 3 +-
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +-
clang/lib/Sema/TreeTransform.h | 14 +-
16 files changed, 278 insertions(+), 271 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 06be666027742..be4aebf1d04e2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10287,8 +10287,7 @@ class Sema final : public SemaBase {
return CodeSynthesisContexts.size() > NonInstantiationEntries;
}
- private:
-
+private:
/// Introduce the instantiated captures of the lambda into the local
/// instantiation scope.
bool addInstantiatedCapturesToScope(
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 1e24921354cdc..7591f28acbd7b 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -190,13 +190,13 @@ class TemplateCompareNewDeclInfo {
public:
TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
- const DeclContext *LexicalDeclCtx,
- SourceLocation Loc)
+ const DeclContext *LexicalDeclCtx,
+ SourceLocation Loc)
: DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
assert(DC && LexicalDC &&
- "Constructor only for cases where we have the information to put "
- "in here");
+ "Constructor only for cases where we have the information to put "
+ "in here");
}
// If this was constructed with no information, we cannot do substitution
@@ -472,7 +472,7 @@ class SemaConcept : public SemaBase {
TemplateTypeParmDecl *ConstrainedParameter,
SourceLocation EllipsisLoc,
bool AllowUnexpandedPack);
-
+
bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
DeclarationNameInfo NameInfo,
ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index bd66ef5318c80..eb851091a14a7 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4083,8 +4083,9 @@ void Parser::ParseDeclarationSpecifiers(
if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
goto DoneWithDeclSpec;
- if (TemplateId && !isInvalid && Actions.Concept().CheckTypeConstraint(TemplateId))
- TemplateId = nullptr;
+ if (TemplateId && !isInvalid &&
+ Actions.Concept().CheckTypeConstraint(TemplateId))
+ TemplateId = nullptr;
ConsumeAnnotationToken();
SourceLocation AutoLoc = Tok.getLocation();
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index a658c03eda4bc..3a923a599af22 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4298,8 +4298,8 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) {
TrailingRequiresClause =
ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);
- TrailingRequiresClause =
- Actions.Concept().ActOnFinishTrailingRequiresClause(TrailingRequiresClause);
+ TrailingRequiresClause = Actions.Concept().ActOnFinishTrailingRequiresClause(
+ TrailingRequiresClause);
if (!D.isDeclarationOfFunction()) {
Diag(RequiresKWLoc,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 175e0bce683f7..c81a29549cb92 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -31,8 +31,8 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaCUDA.h"
-#include "clang/Sema/SemaConcept.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"
@@ -269,7 +269,8 @@ ExprResult Parser::ParseConstraintExpression() {
Actions, Sema::ExpressionEvaluationContext::Unevaluated);
ExprResult LHS(ParseCastExpression(AnyCastExpr));
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
- if (Res.isUsable() && !Actions.Concept().CheckConstraintExpression(Res.get())) {
+ if (Res.isUsable() &&
+ !Actions.Concept().CheckConstraintExpression(Res.get())) {
Actions.CorrectDelayedTyposInExpr(Res);
return ExprError();
}
@@ -330,9 +331,8 @@ Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
NotPrimaryExpression = false;
}
bool PossibleNonPrimary;
- bool IsConstraintExpr =
- Actions.Concept().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
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 224431846fc0f..2c240b4c20dbb 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1418,8 +1418,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
++CurTemplateDepthTracker;
ExprResult RequiresClause;
if (TryConsumeToken(tok::kw_requires)) {
- RequiresClause =
- Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
+ RequiresClause = Actions.Concept().ActOnRequiresClause(
+ ParseConstraintLogicalOrExpression(
/*IsTrailingRequiresClause=*/false));
if (RequiresClause.isInvalid())
SkipUntil({tok::l_brace, tok::l_paren}, StopAtSemi | StopBeforeMatch);
@@ -3670,7 +3670,8 @@ ExprResult Parser::ParseRequiresExpression() {
SourceLocation NoexceptLoc;
TryConsumeToken(tok::kw_noexcept, NoexceptLoc);
if (Tok.is(tok::semi)) {
- Req = Actions.Concept().ActOnCompoundRequirement(Expression.get(), NoexceptLoc);
+ Req = Actions.Concept().ActOnCompoundRequirement(Expression.get(),
+ NoexceptLoc);
if (Req)
Requirements.push_back(Req);
break;
@@ -3765,8 +3766,8 @@ ExprResult Parser::ParseRequiresExpression() {
SkipUntilFlags::StopBeforeMatch);
break;
}
- if (auto *Req =
- Actions.Concept().ActOnNestedRequirement(ConstraintExpr.get()))
+ if (auto *Req = Actions.Concept().ActOnNestedRequirement(
+ ConstraintExpr.get()))
Requirements.push_back(Req);
else {
SkipUntil(tok::semi, tok::r_brace,
@@ -3811,9 +3812,8 @@ ExprResult Parser::ParseRequiresExpression() {
break;
}
- if (auto *Req = Actions.Concept().ActOnTypeRequirement(TypenameKWLoc, SS,
- NameLoc, II,
- TemplateId)) {
+ if (auto *Req = Actions.Concept().ActOnTypeRequirement(
+ TypenameKWLoc, SS, NameLoc, II, TemplateId)) {
Requirements.push_back(Req);
}
break;
@@ -3834,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.Concept().ActOnSimpleRequirement(Expression.get()))
+ if (auto *Req =
+ Actions.Concept().ActOnSimpleRequirement(Expression.get()))
Requirements.push_back(Req);
else {
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index bd732dc50cf9d..5aeef7a8227bb 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -146,8 +146,9 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(
if (TryConsumeToken(tok::kw_requires)) {
OptionalRequiresClauseConstraintER =
- Actions.Concept().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);
@@ -340,9 +341,9 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
DeclEnd = Tok.getLocation();
ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
Expr *ConstraintExpr = ConstraintExprResult.get();
- return Actions.Concept().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
@@ -765,8 +766,8 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
if (TypeConstraint) {
Actions.Concept().ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,
- cast<TemplateTypeParmDecl>(NewDecl),
- EllipsisLoc);
+ cast<TemplateTypeParmDecl>(NewDecl),
+ EllipsisLoc);
}
return NewDecl;
@@ -801,8 +802,9 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
}
if (TryConsumeToken(tok::kw_requires)) {
OptionalRequiresClauseConstraintER =
- Actions.Concept().ActOnRequiresClause(ParseConstraintLogicalOrExpression(
- /*IsTrailingRequiresClause=*/false));
+ Actions.Concept().ActOnRequiresClause(
+ ParseConstraintLogicalOrExpression(
+ /*IsTrailingRequiresClause=*/false));
if (!OptionalRequiresClauseConstraintER.isUsable()) {
SkipUntil(tok::comma, tok::greater, tok::greatergreater,
StopAtSemi | StopBeforeMatch);
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 8957c1d658cb1..de7c83e353b21 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -89,8 +89,9 @@ class LogicalBinOp {
}
bool SemaConcept::CheckConstraintExpression(const Expr *ConstraintExpression,
- Token NextToken, bool *PossibleNonPrimary,
- bool IsTrailingRequiresClause) {
+ Token NextToken,
+ bool *PossibleNonPrimary,
+ bool IsTrailingRequiresClause) {
ASTContext &Context = getASTContext();
// C++2a [temp.constr.atomic]p1
// ..E shall be a constant expression of type bool.
@@ -167,8 +168,8 @@ struct SatisfactionStackRAII {
const llvm::FoldingSetNodeID &FSNID)
: SemaRef(SemaRef) {
if (ND) {
- SemaRef.Concept().PushSatisfactionStackEntry(ND, FSNID);
- Inserted = true;
+ SemaRef.Concept().PushSatisfactionStackEntry(ND, FSNID);
+ Inserted = true;
}
}
~SatisfactionStackRAII() {
@@ -536,8 +537,8 @@ bool SemaConcept::CheckConstraintSatisfaction(
return false;
}
-bool SemaConcept::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
- ConstraintSatisfaction &Satisfaction) {
+bool SemaConcept::CheckConstraintSatisfaction(
+ const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
return calculateConstraintSatisfaction(
SemaRef, ConstraintExpr, Satisfaction,
[this](const Expr *AtomicExpr) -> ExprResult {
@@ -585,8 +586,8 @@ bool SemaConcept::SetupConstraintScope(
PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
while (FromMemTempl->getInstantiatedFromMemberTemplate())
FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate();
- if (SemaRef.addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
- Scope, MLTAL))
+ if (SemaRef.addInstantiatedParametersToScope(
+ FD, FromMemTempl->getTemplatedDecl(), Scope, MLTAL))
return true;
}
@@ -610,7 +611,8 @@ bool SemaConcept::SetupConstraintScope(
// Case where this was not a template, but instantiated as a
// child-function.
- if (SemaRef.addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
+ if (SemaRef.addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope,
+ MLTAL))
return true;
}
@@ -623,20 +625,21 @@ bool SemaConcept::SetupConstraintScope(
/// lists, and calls SetupConstraintScope to set up the
/// LocalInstantiationScope to have the proper set of ParVarDecls configured.
static std::optional<MultiLevelTemplateArgumentList>
-SetupConstraintCheckingTemplateArgumentsAndScope(Sema &SemaRef,
- FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
+SetupConstraintCheckingTemplateArgumentsAndScope(
+ Sema &SemaRef, FunctionDecl *FD,
+ std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
LocalInstantiationScope &Scope) {
MultiLevelTemplateArgumentList MLTAL;
// Collect the list of template arguments relative to the 'primary' template.
// We need the entire list, since the constraint is completely uninstantiated
// at this point.
- MLTAL =
- SemaRef.getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
- /*Final=*/false, /*Innermost=*/std::nullopt,
- /*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr,
- /*ForConstraintInstantiation=*/true);
+ MLTAL = SemaRef.getTemplateInstantiationArgs(
+ FD, FD->getLexicalDeclContext(),
+ /*Final=*/false, /*Innermost=*/std::nullopt,
+ /*RelativeToPrimary=*/true,
+ /*Pattern=*/nullptr,
+ /*ForConstraintInstantiation=*/true);
if (SemaRef.Concept().SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
return std::nullopt;
@@ -644,9 +647,9 @@ SetupConstraintCheckingTemplateArgumentsAndScope(Sema &SemaRef,
}
bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
- ConstraintSatisfaction &Satisfaction,
- SourceLocation UsageLoc,
- bool ForOverloadResolution) {
+ ConstraintSatisfaction &Satisfaction,
+ SourceLocation UsageLoc,
+ bool ForOverloadResolution) {
// Don't check constraints if the function is dependent. Also don't check if
// this is a function template specialization, as the call to
// CheckinstantiatedFunctionTemplateConstraints after this will check it
@@ -683,8 +686,8 @@ bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
Sema::ContextRAII SavedContext{SemaRef, CtxToSave};
LocalInstantiationScope Scope(SemaRef, !ForOverloadResolution);
std::optional<MultiLevelTemplateArgumentList> MLTAL =
- SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef,
- const_cast<FunctionDecl *>(FD), {}, Scope);
+ SetupConstraintCheckingTemplateArgumentsAndScope(
+ SemaRef, const_cast<FunctionDecl *>(FD), {}, Scope);
if (!MLTAL)
return true;
@@ -695,7 +698,8 @@ bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
ThisQuals = Method->getMethodQualifiers();
Record = const_cast<CXXRecordDecl *>(Method->getParent());
}
- Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals, Record != nullptr);
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals,
+ Record != nullptr);
Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
SemaRef, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
@@ -707,7 +711,6 @@ bool SemaConcept::CheckFunctionConstraints(const FunctionDecl *FD,
Satisfaction);
}
-
// Figure out the to-translation-unit depth for this function declaration for
// the purpose of seeing if they differ by constraints. This isn't the same as
// getTemplateDepth, because it includes already instantiated parents.
@@ -804,10 +807,9 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
return SubstConstr.get();
}
-bool SemaConcept::AreConstraintExpressionsEqual(const NamedDecl *Old,
- const Expr *OldConstr,
- const TemplateCompareNewDeclInfo &New,
- const Expr *NewConstr) {
+bool SemaConcept::AreConstraintExpressionsEqual(
+ const NamedDecl *Old, const Expr *OldConstr,
+ const TemplateCompareNewDeclInfo &New, const Expr *NewConstr) {
if (OldConstr == NewConstr)
return true;
// C++ [temp.constr.decl]p4
@@ -833,7 +835,8 @@ bool SemaConcept::AreConstraintExpressionsEqual(const NamedDecl *Old,
return ID1 == ID2;
}
-bool SemaConcept::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
+bool SemaConcept::FriendConstraintsDependOnEnclosingTemplate(
+ const FunctionDecl *FD) {
assert(FD->getFriendObjectKind() && "Must be a friend!");
// The logic for non-templates is handled in ASTContext::isSameEntity, so we
@@ -847,8 +850,8 @@ bool SemaConcept::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl
unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(SemaRef, FD);
for (const Expr *Constraint : ACs)
- if (SemaRef.ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
- Constraint))
+ if (SemaRef.ConstraintExpressionDependsOnEnclosingTemplate(
+ FD, OldTemplateDepth, Constraint))
return true;
return false;
@@ -873,8 +876,8 @@ bool SemaConcept::EnsureTemplateArgumentListConstraints(
Diag(TemplateIDRange.getBegin(),
diag::err_template_arg_list_constraints_not_satisfied)
- << (int)SemaRef.getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
- << TemplateArgString << TemplateIDRange;
+ << (int)SemaRef.getTemplateNameKindForDiagnostics(TemplateName(TD))
+ << TD << TemplateArgString << TemplateIDRange;
DiagnoseUnsatisfiedConstraint(Satisfaction);
return true;
}
@@ -902,8 +905,8 @@ bool SemaConcept::CheckInstantiatedFunctionTemplateConstraints(
LocalInstantiationScope Scope(SemaRef);
std::optional<MultiLevelTemplateArgumentList> MLTAL =
- SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef, Decl, TemplateArgs,
- Scope);
+ SetupConstraintCheckingTemplateArgumentsAndScope(SemaRef, Decl,
+ TemplateArgs, Scope);
if (!MLTAL)
return true;
@@ -915,7 +918,8 @@ bool SemaConcept::CheckInstantiatedFunctionTemplateConstraints(
Record = Method->getParent();
}
- Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals, Record != nullptr);
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, Record, ThisQuals,
+ Record != nullptr);
Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
SemaRef, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
@@ -981,7 +985,8 @@ static void diagnoseUnsatisfiedRequirement(Sema &S,
diag::note_expr_requirement_constraints_not_satisfied)
<< (int)First << ConstraintExpr;
}
- S.Concept().DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
+ S.Concept().DiagnoseUnsatisfiedConstraint(
+ ConstraintExpr->getSatisfaction());
break;
}
case concepts::ExprRequirement::SS_Satisfied:
@@ -1158,9 +1163,8 @@ static void diagnoseUnsatisfiedConstraintExpr(
Record.template get<Expr *>(), First);
}
-void
-SemaConcept::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
- bool First) {
+void SemaConcept::DiagnoseUnsatisfiedConstraint(
+ const ConstraintSatisfaction &Satisfaction, bool First) {
assert(!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint");
for (auto &Pair : Satisfaction.Details) {
@@ -1170,8 +1174,7 @@ SemaConcept::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfa
}
void SemaConcept::DiagnoseUnsatisfiedConstraint(
- const ASTConstraintSatisfaction &Satisfaction,
- bool First) {
+ const ASTConstraintSatisfaction &Satisfaction, bool First) {
assert(!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint");
for (auto &Pair : Satisfaction) {
@@ -1180,8 +1183,7 @@ void SemaConcept::DiagnoseUnsatisfiedConstraint(
}
}
-const NormalizedConstraint *
-SemaConcept::getNormalizedAssociatedConstraints(
+const NormalizedConstraint *SemaConcept::getNormalizedAssociatedConstraints(
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'
@@ -1190,15 +1192,14 @@ SemaConcept::getNormalizedAssociatedConstraints(
auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
if (CacheEntry == NormalizationCache.end()) {
- auto Normalized =
- NormalizedConstraint::fromConstraintExprs(SemaRef, ConstrainedDecl,
- AssociatedConstraints);
+ auto Normalized = NormalizedConstraint::fromConstraintExprs(
+ SemaRef, ConstrainedDecl, AssociatedConstraints);
CacheEntry =
NormalizationCache
.try_emplace(ConstrainedDecl,
Normalized
- ? new (SemaRef.Context) NormalizedConstraint(
- std::move(*Normalized))
+ ? new (SemaRef.Context)
+ NormalizedConstraint(std::move(*Normalized))
: nullptr)
.first;
}
@@ -1344,8 +1345,8 @@ NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
// expression, the program is ill-formed; no diagnostic is required.
// [...]
ConceptDecl *CD = CSE->getNamedConcept();
- SubNF = S.Concept().getNormalizedAssociatedConstraints(CD,
- {CD->getConstraintExpr()});
+ SubNF = S.Concept().getNormalizedAssociatedConstraints(
+ CD, {CD->getConstraintExpr()});
if (!SubNF)
return std::nullopt;
}
@@ -1478,10 +1479,10 @@ static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
}
bool SemaConcept::IsAtLeastAsConstrained(NamedDecl *D1,
- MutableArrayRef<const Expr *> AC1,
- NamedDecl *D2,
- MutableArrayRef<const Expr *> AC2,
- bool &Result) {
+ MutableArrayRef<const Expr *> AC1,
+ NamedDecl *D2,
+ MutableArrayRef<const Expr *> AC2,
+ bool &Result) {
if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
auto IsExpectedEntity = [](const FunctionDecl *FD) {
FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
@@ -1530,16 +1531,17 @@ bool SemaConcept::IsAtLeastAsConstrained(NamedDecl *D1,
}
if (subsumes(SemaRef, D1, AC1, D2, AC2, Result,
- [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
- return A.subsumes(SemaRef.Context, B);
- }))
+ [this](const AtomicConstraint &A, const AtomicConstraint &B) {
+ return A.subsumes(SemaRef.Context, B);
+ }))
return true;
SubsumptionCache.try_emplace(Key, Result);
return false;
}
-bool SemaConcept::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
- ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
+bool SemaConcept::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+ NamedDecl *D1, ArrayRef<const Expr *> AC1, NamedDecl *D2,
+ ArrayRef<const Expr *> AC2) {
if (SemaRef.isSFINAEContext())
// No need to work here because our notes would be discarded.
return false;
@@ -1547,32 +1549,32 @@ bool SemaConcept::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
if (AC1.empty() || AC2.empty())
return false;
- auto NormalExprEvaluator =
- [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
- return A.subsumes(SemaRef.Context, B);
- };
+ auto NormalExprEvaluator = [this](const AtomicConstraint &A,
+ const AtomicConstraint &B) {
+ return A.subsumes(SemaRef.Context, B);
+ };
const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
- auto IdenticalExprEvaluator =
- [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
- if (!A.hasMatchingParameterMapping(SemaRef.Context, B))
- return false;
- const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
- if (EA == EB)
- return true;
+ auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
+ const AtomicConstraint &B) {
+ if (!A.hasMatchingParameterMapping(SemaRef.Context, B))
+ return false;
+ const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
+ if (EA == EB)
+ return true;
- // Not the same source level expression - are the expressions
- // identical?
- llvm::FoldingSetNodeID IDA, IDB;
- EA->Profile(IDA, SemaRef.Context, /*Canonical=*/true);
- EB->Profile(IDB, SemaRef.Context, /*Canonical=*/true);
- if (IDA != IDB)
- return false;
+ // Not the same source level expression - are the expressions
+ // identical?
+ llvm::FoldingSetNodeID IDA, IDB;
+ EA->Profile(IDA, SemaRef.Context, /*Canonical=*/true);
+ EB->Profile(IDB, SemaRef.Context, /*Canonical=*/true);
+ if (IDA != IDB)
+ return false;
- AmbiguousAtomic1 = EA;
- AmbiguousAtomic2 = EB;
- return true;
- };
+ AmbiguousAtomic1 = EA;
+ AmbiguousAtomic2 = EB;
+ return true;
+ };
{
// The subsumption checks might cause diagnostics
@@ -1670,12 +1672,12 @@ concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
RequiresExprBodyDecl *
SemaConcept::ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
- ArrayRef<ParmVarDecl *> LocalParameters,
- Scope *BodyScope) {
+ ArrayRef<ParmVarDecl *> LocalParameters,
+ Scope *BodyScope) {
assert(BodyScope);
- RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(SemaRef.Context, SemaRef.CurContext,
- RequiresKWLoc);
+ RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(
+ SemaRef.Context, SemaRef.CurContext, RequiresKWLoc);
SemaRef.PushDeclContext(BodyScope, Body);
@@ -1717,21 +1719,19 @@ concepts::Requirement *SemaConcept::ActOnTypeRequirement(
"Exactly one of TypeName and TemplateId must be specified.");
TypeSourceInfo *TSI = nullptr;
if (TypeName) {
- QualType T =
- SemaRef.CheckTypenameType(ElaboratedTypeKeyword::Typename, TypenameKWLoc,
- SS.getWithLocInContext(SemaRef.Context), *TypeName, NameLoc,
- &TSI, /*DeducedTSTContext=*/false);
+ QualType T = SemaRef.CheckTypenameType(
+ ElaboratedTypeKeyword::Typename, TypenameKWLoc,
+ SS.getWithLocInContext(SemaRef.Context), *TypeName, NameLoc, &TSI,
+ /*DeducedTSTContext=*/false);
if (T.isNull())
return nullptr;
} else {
ASTTemplateArgsPtr ArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- TypeResult T = SemaRef.ActOnTypenameType(SemaRef.getCurScope(), TypenameKWLoc, SS,
- TemplateId->TemplateKWLoc,
- TemplateId->Template, TemplateId->Name,
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc, ArgsPtr,
- TemplateId->RAngleLoc);
+ TypeResult T = SemaRef.ActOnTypenameType(
+ SemaRef.getCurScope(), TypenameKWLoc, SS, TemplateId->TemplateKWLoc,
+ TemplateId->Template, TemplateId->Name, TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc, ArgsPtr, TemplateId->RAngleLoc);
if (T.isInvalid())
return nullptr;
if (SemaRef.GetTypeFromParser(T.get(), &TSI).isNull())
@@ -1746,8 +1746,7 @@ SemaConcept::ActOnCompoundRequirement(Expr *E, SourceLocation NoexceptLoc) {
/*ReturnTypeRequirement=*/{});
}
-concepts::Requirement *
-SemaConcept::ActOnCompoundRequirement(
+concepts::Requirement *SemaConcept::ActOnCompoundRequirement(
Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
TemplateIdAnnotation *TypeConstraint, unsigned Depth) {
// C++2a [expr.prim.req.compound] p1.3.3
@@ -1762,13 +1761,13 @@ SemaConcept::ActOnCompoundRequirement(
// arguments and the abstract declarator with the correct CV qualification and
// have to synthesize T and the single parameter of F.
auto &II = SemaRef.Context.Idents.get("expr-type");
- auto *TParam = TemplateTypeParmDecl::Create(SemaRef.Context, SemaRef.CurContext,
- SourceLocation(),
- SourceLocation(), Depth,
- /*Index=*/0, &II,
- /*Typename=*/true,
- /*ParameterPack=*/false,
- /*HasTypeConstraint=*/true);
+ auto *TParam =
+ TemplateTypeParmDecl::Create(SemaRef.Context, SemaRef.CurContext,
+ SourceLocation(), SourceLocation(), Depth,
+ /*Index=*/0, &II,
+ /*Typename=*/true,
+ /*ParameterPack=*/false,
+ /*HasTypeConstraint=*/true);
if (BuildTypeConstraint(SS, TypeConstraint, TParam,
/*EllipsisLoc=*/SourceLocation(),
@@ -1776,18 +1775,16 @@ SemaConcept::ActOnCompoundRequirement(
// Just produce a requirement with no type requirements.
return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc, {});
- auto *TPL = TemplateParameterList::Create(SemaRef.Context, SourceLocation(),
- SourceLocation(),
- ArrayRef<NamedDecl *>(TParam),
- SourceLocation(),
- /*RequiresClause=*/nullptr);
+ auto *TPL = TemplateParameterList::Create(
+ SemaRef.Context, SourceLocation(), SourceLocation(),
+ ArrayRef<NamedDecl *>(TParam), SourceLocation(),
+ /*RequiresClause=*/nullptr);
return BuildExprRequirement(
E, /*IsSimple=*/false, NoexceptLoc,
concepts::ExprRequirement::ReturnTypeRequirement(TPL));
}
-concepts::ExprRequirement *
-SemaConcept::BuildExprRequirement(
+concepts::ExprRequirement *SemaConcept::BuildExprRequirement(
Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
auto Status = concepts::ExprRequirement::SS_Satisfied;
@@ -1795,7 +1792,8 @@ SemaConcept::BuildExprRequirement(
if (E->isInstantiationDependent() || E->getType()->isPlaceholderType() ||
ReturnTypeRequirement.isDependent())
Status = concepts::ExprRequirement::SS_Dependent;
- else if (NoexceptLoc.isValid() && SemaRef.canThrow(E) == CanThrowResult::CT_Can)
+ else if (NoexceptLoc.isValid() &&
+ SemaRef.canThrow(E) == CanThrowResult::CT_Can)
Status = concepts::ExprRequirement::SS_NoexceptNotMet;
else if (ReturnTypeRequirement.isSubstitutionFailure())
Status = concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure;
@@ -1823,8 +1821,9 @@ SemaConcept::BuildExprRequirement(
return new (SemaRef.Context) concepts::ExprRequirement(
concepts::createSubstDiagAt(SemaRef, IDC->getExprLoc(),
[&](llvm::raw_ostream &OS) {
- IDC->printPretty(OS, /*Helper=*/nullptr,
- SemaRef.getPrintingPolicy());
+ IDC->printPretty(
+ OS, /*Helper=*/nullptr,
+ SemaRef.getPrintingPolicy());
}),
IsSimple, NoexceptLoc, ReturnTypeRequirement);
}
@@ -1833,19 +1832,17 @@ SemaConcept::BuildExprRequirement(
if (!SubstitutedConstraintExpr->isSatisfied())
Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
}
- return new (SemaRef.Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc,
- ReturnTypeRequirement, Status,
- SubstitutedConstraintExpr);
+ return new (SemaRef.Context)
+ concepts::ExprRequirement(E, IsSimple, NoexceptLoc, ReturnTypeRequirement,
+ Status, SubstitutedConstraintExpr);
}
-concepts::ExprRequirement *
-SemaConcept::BuildExprRequirement(
+concepts::ExprRequirement *SemaConcept::BuildExprRequirement(
concepts::Requirement::SubstitutionDiagnostic *ExprSubstitutionDiagnostic,
bool IsSimple, SourceLocation NoexceptLoc,
concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) {
- return new (SemaRef.Context) concepts::ExprRequirement(ExprSubstitutionDiagnostic,
- IsSimple, NoexceptLoc,
- ReturnTypeRequirement);
+ return new (SemaRef.Context) concepts::ExprRequirement(
+ ExprSubstitutionDiagnostic, IsSimple, NoexceptLoc, ReturnTypeRequirement);
}
concepts::TypeRequirement *
@@ -1853,8 +1850,7 @@ SemaConcept::BuildTypeRequirement(TypeSourceInfo *Type) {
return new (SemaRef.Context) concepts::TypeRequirement(Type);
}
-concepts::TypeRequirement *
-SemaConcept::BuildTypeRequirement(
+concepts::TypeRequirement *SemaConcept::BuildTypeRequirement(
concepts::Requirement::SubstitutionDiagnostic *SubstDiag) {
return new (SemaRef.Context) concepts::TypeRequirement(SubstDiag);
}
@@ -1870,13 +1866,13 @@ SemaConcept::BuildNestedRequirement(Expr *Constraint) {
CheckConstraintSatisfaction(nullptr, {Constraint}, /*TemplateArgs=*/{},
Constraint->getSourceRange(), Satisfaction))
return nullptr;
- return new (SemaRef.Context) concepts::NestedRequirement(SemaRef.Context, Constraint,
- Satisfaction);
+ return new (SemaRef.Context)
+ concepts::NestedRequirement(SemaRef.Context, Constraint, Satisfaction);
}
-concepts::NestedRequirement *
-SemaConcept::BuildNestedRequirement(StringRef InvalidConstraintEntity,
- const ASTConstraintSatisfaction &Satisfaction) {
+concepts::NestedRequirement *SemaConcept::BuildNestedRequirement(
+ StringRef InvalidConstraintEntity,
+ const ASTConstraintSatisfaction &Satisfaction) {
return new (SemaRef.Context) concepts::NestedRequirement(
InvalidConstraintEntity,
ASTConstraintSatisfaction::Rebuild(SemaRef.Context, Satisfaction));
@@ -1887,9 +1883,9 @@ ExprResult SemaConcept::ActOnRequiresExpr(
SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
SourceLocation ClosingBraceLoc) {
- auto *RE = RequiresExpr::Create(SemaRef.Context, RequiresKWLoc, Body, LParenLoc,
- LocalParameters, RParenLoc, Requirements,
- ClosingBraceLoc);
+ auto *RE = RequiresExpr::Create(SemaRef.Context, RequiresKWLoc, Body,
+ LParenLoc, LocalParameters, RParenLoc,
+ Requirements, ClosingBraceLoc);
if (SemaRef.DiagnoseUnexpandedParameterPackInRequiresExpr(RE))
return ExprError();
return RE;
@@ -1921,19 +1917,17 @@ bool SemaConcept::CheckTypeConstraint(TemplateIdAnnotation *TypeConstr) {
return false;
}
-bool SemaConcept::ActOnTypeConstraint(const CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstr,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc) {
+bool SemaConcept::ActOnTypeConstraint(
+ const CXXScopeSpec &SS, TemplateIdAnnotation *TypeConstr,
+ TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc) {
return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
false);
}
-bool SemaConcept::BuildTypeConstraint(const CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstr,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc,
- bool AllowUnexpandedPack) {
+bool SemaConcept::BuildTypeConstraint(
+ const CXXScopeSpec &SS, TemplateIdAnnotation *TypeConstr,
+ TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc,
+ bool AllowUnexpandedPack) {
if (CheckTypeConstraint(TypeConstr))
return true;
@@ -1947,18 +1941,19 @@ bool SemaConcept::BuildTypeConstraint(const CXXScopeSpec &SS,
TemplateArgumentListInfo TemplateArgs;
if (TypeConstr->LAngleLoc.isValid()) {
- TemplateArgs =
- SemaRef.makeTemplateArgumentListInfo(*TypeConstr);
+ TemplateArgs = SemaRef.makeTemplateArgumentListInfo(*TypeConstr);
if (EllipsisLoc.isInvalid() && !AllowUnexpandedPack) {
for (TemplateArgumentLoc Arg : TemplateArgs.arguments()) {
- if (SemaRef.DiagnoseUnexpandedParameterPack(Arg, Sema::UPPC_TypeConstraint))
+ if (SemaRef.DiagnoseUnexpandedParameterPack(Arg,
+ Sema::UPPC_TypeConstraint))
return true;
}
}
}
return AttachTypeConstraint(
- SS.isSet() ? SS.getWithLocInContext(SemaRef.Context) : NestedNameSpecifierLoc(),
+ SS.isSet() ? SS.getWithLocInContext(SemaRef.Context)
+ : NestedNameSpecifierLoc(),
ConceptName, CD, /*FoundDecl=*/USD ? cast<NamedDecl>(USD) : CD,
TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr,
ConstrainedParameter, EllipsisLoc);
@@ -1974,8 +1969,8 @@ static ExprResult formImmediatelyDeclaredConstraint(
TemplateArgumentListInfo ConstraintArgs;
ConstraintArgs.addArgument(
- S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
- /*NTTPType=*/QualType(), ParamNameLoc));
+ S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType),
+ /*NTTPType=*/QualType(), ParamNameLoc));
ConstraintArgs.setRAngleLoc(RAngleLoc);
ConstraintArgs.setLAngleLoc(LAngleLoc);
@@ -2017,18 +2012,18 @@ static ExprResult formImmediatelyDeclaredConstraint(
/// \returns true if an error occurred. This can happen if the
/// immediately-declared constraint could not be formed (e.g. incorrect number
/// of arguments for the named concept).
-bool SemaConcept::AttachTypeConstraint(NestedNameSpecifierLoc NS,
- DeclarationNameInfo NameInfo,
- ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
- const TemplateArgumentListInfo *TemplateArgs,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc) {
+bool SemaConcept::AttachTypeConstraint(
+ NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo,
+ ConceptDecl *NamedConcept, NamedDecl *FoundDecl,
+ const TemplateArgumentListInfo *TemplateArgs,
+ TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc) {
// C++2a [temp.param]p4:
// [...] If Q is of the form C<A1, ..., An>, then let E' be
// C<T, A1, ..., An>. Otherwise, let E' be C<T>. [...]
const ASTTemplateArgumentListInfo *ArgsAsWritten =
- TemplateArgs ? ASTTemplateArgumentListInfo::Create(SemaRef.Context,
- *TemplateArgs) : nullptr;
+ TemplateArgs
+ ? ASTTemplateArgumentListInfo::Create(SemaRef.Context, *TemplateArgs)
+ : nullptr;
QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0);
@@ -2057,10 +2052,9 @@ bool SemaConcept::AttachTypeConstraint(NestedNameSpecifierLoc NS,
return false;
}
-bool SemaConcept::AttachTypeConstraint(AutoTypeLoc TL,
- NonTypeTemplateParmDecl *NewConstrainedParm,
- NonTypeTemplateParmDecl *OrigConstrainedParm,
- SourceLocation EllipsisLoc) {
+bool SemaConcept::AttachTypeConstraint(
+ AutoTypeLoc TL, NonTypeTemplateParmDecl *NewConstrainedParm,
+ NonTypeTemplateParmDecl *OrigConstrainedParm, SourceLocation EllipsisLoc) {
if (NewConstrainedParm->getType() != TL.getType() ||
TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
@@ -2072,9 +2066,9 @@ bool SemaConcept::AttachTypeConstraint(AutoTypeLoc TL,
}
// FIXME: Concepts: This should be the type of the placeholder, but this is
// unclear in the wording right now.
- DeclRefExpr *Ref =
- SemaRef.BuildDeclRefExpr(OrigConstrainedParm, OrigConstrainedParm->getType(),
- VK_PRValue, OrigConstrainedParm->getLocation());
+ DeclRefExpr *Ref = SemaRef.BuildDeclRefExpr(
+ OrigConstrainedParm, OrigConstrainedParm->getType(), VK_PRValue,
+ OrigConstrainedParm->getLocation());
if (!Ref)
return true;
ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
@@ -2096,13 +2090,10 @@ bool SemaConcept::AttachTypeConstraint(AutoTypeLoc TL,
return false;
}
-ExprResult
-SemaConcept::CheckConceptTemplateId(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &ConceptNameInfo,
- NamedDecl *FoundDecl,
- ConceptDecl *NamedConcept,
- const TemplateArgumentListInfo *TemplateArgs) {
+ExprResult SemaConcept::CheckConceptTemplateId(
+ const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl,
+ ConceptDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs) {
assert(NamedConcept && "A concept template id without a template?");
ASTContext &Context = getASTContext();
@@ -2154,7 +2145,7 @@ Decl *SemaConcept::ActOnConceptDefinition(
if (!DC->getRedeclContext()->isFileContext()) {
Diag(NameLoc,
- diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
+ diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
return nullptr;
}
@@ -2188,8 +2179,8 @@ Decl *SemaConcept::ActOnConceptDefinition(
if (SemaRef.DiagnoseUnexpandedParameterPack(ConstraintExpr))
return nullptr;
- ConceptDecl *NewDecl =
- ConceptDecl::Create(SemaRef.Context, DC, NameLoc, Name, Params, ConstraintExpr);
+ ConceptDecl *NewDecl = ConceptDecl::Create(SemaRef.Context, DC, NameLoc, Name,
+ Params, ConstraintExpr);
if (NewDecl->hasAssociatedConstraints()) {
// C++2a [temp.concept]p4:
@@ -2204,7 +2195,7 @@ Decl *SemaConcept::ActOnConceptDefinition(
SemaRef.forRedeclarationInCurContext());
SemaRef.LookupName(Previous, S);
SemaRef.FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false,
- /*AllowInlineNamespace*/false);
+ /*AllowInlineNamespace*/ false);
bool AddToScope = true;
CheckConceptRedefinition(NewDecl, Previous, AddToScope);
@@ -2218,13 +2209,15 @@ Decl *SemaConcept::ActOnConceptDefinition(
}
void SemaConcept::CheckConceptRedefinition(ConceptDecl *NewDecl,
- LookupResult &Previous, bool &AddToScope) {
+ LookupResult &Previous,
+ bool &AddToScope) {
AddToScope = true;
if (Previous.empty())
return;
- auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()->getUnderlyingDecl());
+ auto *OldConcept = dyn_cast<ConceptDecl>(
+ Previous.getRepresentativeDecl()->getUnderlyingDecl());
if (!OldConcept) {
auto *Old = Previous.getRepresentativeDecl();
Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind)
@@ -2265,15 +2258,16 @@ void SemaConcept::ActOnStartTrailingRequiresClause(Scope *S, Declarator &D) {
auto &FTI = D.getFunctionTypeInfo();
if (!FTI.Params)
return;
- for (auto &Param : ArrayRef<DeclaratorChunk::ParamInfo>(FTI.Params,
- FTI.NumParams)) {
+ for (auto &Param :
+ ArrayRef<DeclaratorChunk::ParamInfo>(FTI.Params, FTI.NumParams)) {
auto *ParamDecl = cast<NamedDecl>(Param.Param);
if (ParamDecl->getDeclName())
SemaRef.PushOnScopeChains(ParamDecl, S, /*AddToContext=*/false);
}
}
-ExprResult SemaConcept::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
+ExprResult
+SemaConcept::ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr) {
return ActOnRequiresClause(ConstraintExpr);
}
@@ -2286,20 +2280,21 @@ ExprResult SemaConcept::ActOnRequiresClause(ExprResult ConstraintExpr) {
return ExprError();
if (SemaRef.DiagnoseUnexpandedParameterPack(ConstraintExpr.get(),
- Sema::UPPC_RequiresClause))
+ Sema::UPPC_RequiresClause))
return ExprError();
return ConstraintExpr;
}
-void SemaConcept::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) {
+void SemaConcept::CheckConstrainedAuto(const AutoType *AutoT,
+ SourceLocation Loc) {
if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) {
SemaRef.DiagnoseUseOfDecl(Decl, Loc);
}
}
FunctionDecl *SemaConcept::getMoreConstrainedFunction(FunctionDecl *FD1,
- FunctionDecl *FD2) {
+ FunctionDecl *FD2) {
assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() &&
"not for function templates");
FunctionDecl *F1 = FD1;
@@ -2321,7 +2316,8 @@ FunctionDecl *SemaConcept::getMoreConstrainedFunction(FunctionDecl *FD1,
return AtLeastAsConstrained1 ? FD1 : FD2;
}
-clang::SemaConcept::SemaConcept(Sema &S) : SemaBase(S), SatisfactionCache(S.Context) {}
+clang::SemaConcept::SemaConcept(Sema &S)
+ : SemaBase(S), SatisfactionCache(S.Context) {}
clang::SemaConcept::~SemaConcept() {
// Delete cached satisfactions.
@@ -2333,7 +2329,9 @@ clang::SemaConcept::~SemaConcept() {
delete Node;
}
-clang::SemaConcept::SatisfactionStackResetRAII::SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
+clang::SemaConcept::SatisfactionStackResetRAII::SatisfactionStackResetRAII(
+ Sema &S)
+ : SemaRef(S) {
SemaRef.Concept().SwapSatisfactionStack(BackupSatisfactionStack);
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1aeb6b87b680a..b4560bd41052c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -19013,9 +19013,9 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
AnotherMethodIsMoreConstrained = true;
break;
}
- if (S.Concept().IsAtLeastAsConstrained(OtherMethod, {OtherConstraints}, OrigMethod,
- {Constraints},
- AnotherMethodIsMoreConstrained)) {
+ if (S.Concept().IsAtLeastAsConstrained(OtherMethod, {OtherConstraints},
+ OrigMethod, {Constraints},
+ AnotherMethodIsMoreConstrained)) {
// There was an error with the constraints comparison. Exit the loop
// and don't consider this function eligible.
AnotherMethodIsMoreConstrained = true;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b9ab327d37247..63d579266ba16 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -296,7 +296,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
if (!SkipTrailingRequiresClause && FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (Concept().CheckFunctionConstraints(FD, Satisfaction, Loc,
- /*ForOverloadResolution*/ true))
+ /*ForOverloadResolution*/ true))
// A diagnostic will have already been generated (non-constant
// constraint expression, for example)
return true;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index f138db5467030..7947c061d6a9c 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1518,8 +1518,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
*OldRC = Old->getTrailingRequiresClause();
if ((NewRC != nullptr) != (OldRC != nullptr))
return true;
- if (NewRC &&
- !SemaRef.Concept().AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
+ if (NewRC && !SemaRef.Concept().AreConstraintExpressionsEqual(
+ OldDecl, OldRC, NewDecl, NewRC))
return true;
}
@@ -7095,7 +7095,7 @@ void Sema::AddOverloadCandidate(
if (Function->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (Concept().CheckFunctionConstraints(Function, Satisfaction, /*Loc*/ {},
- /*ForOverloadResolution*/ true) ||
+ /*ForOverloadResolution*/ true) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -7613,7 +7613,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
if (Method->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (Concept().CheckFunctionConstraints(Method, Satisfaction, /*Loc*/ {},
- /*ForOverloadResolution*/ true) ||
+ /*ForOverloadResolution*/ true) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -8326,7 +8326,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
if (Conversion->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (Concept().CheckFunctionConstraints(Conversion, Satisfaction, /*Loc*/ {},
- /*ForOverloadResolution*/ true) ||
+ /*ForOverloadResolution*/ true) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -11221,8 +11221,8 @@ MaybeDiagnoseAmbiguousConstraints(Sema &S, ArrayRef<OverloadCandidate> Cands) {
return;
// The diagnostic can only happen if there are associated constraints on
// both sides (there needs to be some identical atomic constraint).
- if (S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(FirstCand, FirstAC,
- SecondCand, SecondAC))
+ if (S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+ FirstCand, FirstAC, SecondCand, SecondAC))
// Just show the user one diagnostic, they'll probably figure it out
// from here.
return;
@@ -11748,7 +11748,7 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
<< TemplateArgString;
S.Concept().DiagnoseUnsatisfiedConstraint(
- static_cast<CNSInfo*>(DeductionFailure.Data)->Satisfaction);
+ static_cast<CNSInfo *>(DeductionFailure.Data)->Satisfaction);
return;
}
case TemplateDeductionResult::TooManyArguments:
@@ -13342,7 +13342,8 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
}
// FD has the same CUDA prefernece than Result. Continue check
// constraints.
- FunctionDecl *MoreConstrained = Concept().getMoreConstrainedFunction(FD, Result);
+ FunctionDecl *MoreConstrained =
+ Concept().getMoreConstrainedFunction(FD, Result);
if (MoreConstrained != FD) {
if (!MoreConstrained) {
IsResultAmbiguous = true;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 73abb59857a97..3083a0909a35f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4966,8 +4966,8 @@ static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) {
SmallVector<const Expr *, 3> PartialAC, TemplateAC;
Template->getAssociatedConstraints(TemplateAC);
Partial->getAssociatedConstraints(PartialAC);
- S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Partial, PartialAC, Template,
- TemplateAC);
+ S.Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+ Partial, PartialAC, Template, TemplateAC);
}
static void
@@ -5474,9 +5474,9 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
}
if (R.getAsSingle<ConceptDecl>()) {
- return Concept().CheckConceptTemplateId(SS, TemplateKWLoc, R.getLookupNameInfo(),
- R.getRepresentativeDecl(),
- R.getAsSingle<ConceptDecl>(), TemplateArgs);
+ return Concept().CheckConceptTemplateId(
+ SS, TemplateKWLoc, R.getLookupNameInfo(), R.getRepresentativeDecl(),
+ R.getAsSingle<ConceptDecl>(), TemplateArgs);
}
// We don't want lookup warnings at this point.
@@ -8296,8 +8296,9 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
Template->getAssociatedConstraints(TemplateAC);
bool IsParamAtLeastAsConstrained;
- if (Concept().IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
- IsParamAtLeastAsConstrained))
+ if (Concept().IsAtLeastAsConstrained(Param, ParamsAC, Template,
+ TemplateAC,
+ IsParamAtLeastAsConstrained))
return true;
if (!IsParamAtLeastAsConstrained) {
Diag(Arg.getLocation(),
@@ -8306,8 +8307,8 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
Diag(Template->getLocation(), diag::note_entity_declared_at)
<< Template;
- Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
- TemplateAC);
+ Concept().MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+ Param, ParamsAC, Template, TemplateAC);
return true;
}
return false;
@@ -8634,9 +8635,8 @@ Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
/// Match two template parameters within template parameter lists.
static bool MatchTemplateParameterKind(
- Sema &S, NamedDecl *New,
- const TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old,
- const NamedDecl *OldInstFrom, bool Complain,
+ Sema &S, NamedDecl *New, const TemplateCompareNewDeclInfo &NewInstFrom,
+ NamedDecl *Old, const NamedDecl *OldInstFrom, bool Complain,
Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
// Check the actual kind (type, non-type, template).
if (Old->getKind() != New->getKind()) {
@@ -8770,8 +8770,8 @@ static bool MatchTemplateParameterKind(
}
if (NewC) {
- if (!S.Concept().AreConstraintExpressionsEqual(OldInstFrom, OldC, NewInstFrom,
- NewC)) {
+ if (!S.Concept().AreConstraintExpressionsEqual(OldInstFrom, OldC,
+ NewInstFrom, NewC)) {
if (Complain)
Diagnose();
return false;
@@ -8912,8 +8912,8 @@ bool Sema::TemplateParameterListsAreEqual(
}
if (NewRC) {
- if (!Concept().AreConstraintExpressionsEqual(OldInstFrom, OldRC, NewInstFrom,
- NewRC)) {
+ if (!Concept().AreConstraintExpressionsEqual(OldInstFrom, OldRC,
+ NewInstFrom, NewRC)) {
if (Complain)
Diagnose();
return false;
@@ -10204,9 +10204,10 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
continue;
if (ConstraintSatisfaction Satisfaction;
Method->getTrailingRequiresClause() &&
- (Concept().CheckFunctionConstraints(Method, Satisfaction,
- /*UsageLoc=*/Member->getLocation(),
- /*ForOverloadResolution=*/true) ||
+ (Concept().CheckFunctionConstraints(
+ Method, Satisfaction,
+ /*UsageLoc=*/Member->getLocation(),
+ /*ForOverloadResolution=*/true) ||
!Satisfaction.IsSatisfied))
continue;
Candidates.push_back(Method);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 25a36706b8039..dacfa18cfb467 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3089,9 +3089,9 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
if (!Innermost)
MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
- if (S.Concept().CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
- Info.getLocation(),
- Info.AssociatedConstraintsSatisfaction) ||
+ if (S.Concept().CheckConstraintSatisfaction(
+ Template, AssociatedConstraints, MLTAL, Info.getLocation(),
+ Info.AssociatedConstraintsSatisfaction) ||
!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
Info.reset(
TemplateArgumentList::CreateCopy(S.Context, SugaredDeducedArgs),
@@ -5101,9 +5101,9 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
return true;
MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted,
/*Final=*/false);
- if (S.Concept().CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
- MLTAL, TypeLoc.getLocalSourceRange(),
- Satisfaction))
+ if (S.Concept().CheckConstraintSatisfaction(
+ Concept, {Concept->getConstraintExpr()}, MLTAL,
+ TypeLoc.getLocalSourceRange(), Satisfaction))
return true;
if (!Satisfaction.IsSatisfied) {
std::string Buf;
@@ -5854,9 +5854,11 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
FT1->getAssociatedConstraints(AC1);
FT2->getAssociatedConstraints(AC2);
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (Concept().IsAtLeastAsConstrained(FT1, AC1, FT2, AC2, AtLeastAsConstrained1))
+ if (Concept().IsAtLeastAsConstrained(FT1, AC1, FT2, AC2,
+ AtLeastAsConstrained1))
return nullptr;
- if (Concept().IsAtLeastAsConstrained(FT2, AC2, FT1, AC1, AtLeastAsConstrained2))
+ if (Concept().IsAtLeastAsConstrained(FT2, AC2, FT1, AC1,
+ AtLeastAsConstrained2))
return nullptr;
if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
return nullptr;
@@ -6200,10 +6202,12 @@ getMoreSpecialized(Sema &S, QualType T1, QualType T2, TemplateLikeDecl *P1,
P1->getAssociatedConstraints(AC1);
P2->getAssociatedConstraints(AC2);
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (S.Concept().IsAtLeastAsConstrained(P1, AC1, P2, AC2, AtLeastAsConstrained1) ||
+ if (S.Concept().IsAtLeastAsConstrained(P1, AC1, P2, AC2,
+ AtLeastAsConstrained1) ||
(IsMoreSpecialThanPrimaryCheck && !AtLeastAsConstrained1))
return nullptr;
- if (S.Concept().IsAtLeastAsConstrained(P2, AC2, P1, AC1, AtLeastAsConstrained2))
+ if (S.Concept().IsAtLeastAsConstrained(P2, AC2, P1, AC1,
+ AtLeastAsConstrained2))
return nullptr;
if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
return nullptr;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index c2b6d151cdf45..2bb7b1f99af50 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -4662,7 +4662,8 @@ bool Sema::addInstantiatedCapturesToScope(
} else {
Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
std::optional<unsigned> NumArgumentsInExpansion =
- SemaRef.getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
+ SemaRef.getNumArgumentsInExpansion(CapturedPattern->getType(),
+ TemplateArgs);
if (!NumArgumentsInExpansion)
continue;
for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 729f7442cbe06..e13f5ecfe724e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3112,8 +3112,9 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
// Note: We attach the uninstantiated constriant here, so that it can be
// instantiated relative to the top level, like all our other
// constraints.
- if (SemaRef.Concept().AttachTypeConstraint(AutoLoc, /*NewConstrainedParm=*/Param,
- /*OrigConstrainedParm=*/D, EllipsisLoc))
+ if (SemaRef.Concept().AttachTypeConstraint(
+ AutoLoc, /*NewConstrainedParm=*/Param,
+ /*OrigConstrainedParm=*/D, EllipsisLoc))
Invalid = true;
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 0172b49ced0cf..f063030937837 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3663,10 +3663,8 @@ class TreeTransform {
TemplateArgumentListInfo *TALI) {
CXXScopeSpec SS;
SS.Adopt(NNS);
- ExprResult Result = getSema().Concept().CheckConceptTemplateId(SS, TemplateKWLoc,
- ConceptNameInfo,
- FoundDecl,
- NamedConcept, TALI);
+ ExprResult Result = getSema().Concept().CheckConceptTemplateId(
+ SS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, TALI);
if (Result.isInvalid())
return ExprError();
return Result;
@@ -3703,22 +3701,22 @@ class TreeTransform {
concepts::Requirement::SubstitutionDiagnostic *SubstDiag, bool IsSimple,
SourceLocation NoexceptLoc,
concepts::ExprRequirement::ReturnTypeRequirement Ret) {
- return SemaRef.Concept().BuildExprRequirement(SubstDiag, IsSimple, NoexceptLoc,
- std::move(Ret));
+ return SemaRef.Concept().BuildExprRequirement(SubstDiag, IsSimple,
+ NoexceptLoc, std::move(Ret));
}
concepts::ExprRequirement *
RebuildExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
concepts::ExprRequirement::ReturnTypeRequirement Ret) {
return SemaRef.Concept().BuildExprRequirement(E, IsSimple, NoexceptLoc,
- std::move(Ret));
+ std::move(Ret));
}
concepts::NestedRequirement *
RebuildNestedRequirement(StringRef InvalidConstraintEntity,
const ASTConstraintSatisfaction &Satisfaction) {
return SemaRef.Concept().BuildNestedRequirement(InvalidConstraintEntity,
- Satisfaction);
+ Satisfaction);
}
concepts::NestedRequirement *RebuildNestedRequirement(Expr *Constraint) {
>From 02bce366b11c44e214b4cd11e2aaa99b8dc15a27 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 18 May 2024 23:41:05 +0300
Subject: [PATCH 4/4] Remove duplicated include
---
clang/include/clang/Sema/SemaConcept.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 7591f28acbd7b..96e36dc8a188c 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -21,7 +21,6 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprConcepts.h"
-#include "clang/AST/DeclTemplate.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
More information about the cfe-commits
mailing list