Author: Younan Zhang Date: 2026-09-13T12:09:55Z New Revision: db65ace07649b2beb8cdbdfd6af4901809df9966
URL: https://github.com/llvm/llvm-project/commit/db65ace07649b2beb8cdbdfd6af4901809df9966 DIFF: https://github.com/llvm/llvm-project/commit/db65ace07649b2beb8cdbdfd6af4901809df9966.diff LOG: Revert "[Clang] Refactor instantiation of declarations within concepts" (#223235) This reverts llvm/llvm-project#221707 This broke std::map as reported in https://github.com/llvm/llvm-project/issues/223220 Added: Modified: clang/docs/ReleaseNotes.md clang/include/clang/Sema/Sema.h clang/include/clang/Sema/Template.h clang/lib/Sema/SemaConcept.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/test/SemaCXX/cxx2c-fold-exprs.cpp clang/test/SemaTemplate/concepts-lambda.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index fc7ab3efa9731..043a0ddae2a6c 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -589,9 +589,6 @@ features cannot lower the translation-unit ABI level; - Fixed a crash when module directive export module foo not following a semicolon and there are no rest pp-tokens in current module file. (#GH187771) -- Fixed concept evaluation bugs where some declarations were not added to - the current instantiation scope. (#GH198052), (#GH209632) - - Fixed a crash when a lambda parameter pack was given a default argument that is a pack expansion referencing an enclosing function's parameter pack (e.g. `[](Types... = args...) {}`). Clang now diagnoses the illegal default diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fc8da0ed56005..4ff4c669a6b70 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -15129,17 +15129,11 @@ class Sema final : public SemaBase { const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1, const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2); -private: - friend class ConstraintSatisfactionChecker; - friend class SubstituteParameterMappings; - - UnsignedOrNone EvaluateFoldExpandedConstraintSize( - const Expr *Pattern, const MultiLevelTemplateArgumentList &MLTAL); - /// Cache the satisfaction of an atomic constraint. /// The key is based on the unsubstituted expression and the parameter /// mapping. This lets us not substituting the mapping more than once, /// which is (very!) expensive. + /// FIXME: this should be private. llvm::DenseMap<llvm::FoldingSetNodeID, UnsubstitutedConstraintSatisfactionCacheResult> UnsubstitutedConstraintSatisfactionCache; @@ -15151,6 +15145,7 @@ class Sema final : public SemaBase { llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc> *CurrentCachedTemplateArgs = nullptr; +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. @@ -15171,6 +15166,23 @@ class Sema final : public SemaBase { // The current stack of constraint satisfactions, so we can exit-early. llvm::SmallVector<SatisfactionStackEntryTy, 10> SatisfactionStack; + /// Used by SetupConstraintCheckingTemplateArgumentsAndScope to set up the + /// LocalInstantiationScope of the current non-lambda function. For lambdas, + /// use LambdaScopeForCallOperatorInstantiationRAII. + 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); + ///@} // diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 818528744511d..50e950e56c6ca 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -540,8 +540,6 @@ enum class TemplateSubstitutionKind : char { llvm::PointerUnion<Decl *, DeclArgumentPack *> * getInstantiationOfIfExists(const Decl *D); - LocalInstantiationScope *getOuterScope() const { return Outer; } - void InstantiatedLocal(const Decl *D, Decl *Inst); void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst); void MakeInstantiatedLocalArgPack(const Decl *D); diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 0122e920e5d89..ee17f826dc32c 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -549,9 +549,7 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> { } } }; -} // namespace -namespace clang { class ConstraintSatisfactionChecker { Sema &S; const NamedDecl *Template; @@ -654,6 +652,10 @@ class ConstraintSatisfactionChecker { EvaluateAtomicConstraint(const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL); + UnsignedOrNone EvaluateFoldExpandedConstraintSize( + const FoldExpandedConstraint &FE, + const MultiLevelTemplateArgumentList &MLTAL); + // XXX: It is SLOW! Use it very carefully. std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments( const NormalizedConstraintWithParamMapping &Constraint, @@ -698,7 +700,7 @@ class ConstraintSatisfactionChecker { const MultiLevelTemplateArgumentList &MLTAL); }; -} // namespace clang +} // namespace ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint( const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) { @@ -946,6 +948,31 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( return PMCache.cache(EvaluateSlow(Constraint, MLTAL)); } +UnsignedOrNone +ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize( + const FoldExpandedConstraint &FE, + const MultiLevelTemplateArgumentList &MLTAL) { + + Expr *Pattern = const_cast<Expr *>(FE.getPattern()); + + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + S.collectUnexpandedParameterPacks(Pattern, Unexpanded); + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); + bool Expand = true; + bool RetainExpansion = false; + UnsignedOrNone NumExpansions(std::nullopt); + if (S.CheckParameterPacksForExpansion( + Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL, + /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion, + NumExpansions, /*Diagnose=*/false) || + !Expand || RetainExpansion) + return std::nullopt; + + if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions) + return std::nullopt; + return NumExpansions; +} + ExprResult ConstraintSatisfactionChecker::EvaluateSlow( const FoldExpandedConstraint &Constraint, const MultiLevelTemplateArgumentList &MLTAL) { @@ -966,15 +993,9 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow( return ExprError(); } - UnsignedOrNone NumExpansions(std::nullopt); - { - Sema::InstantiatingTemplate InstTemplate( - S, TemplateNameLoc, - Sema::InstantiatingTemplate::ConstraintSubstitution{}, - const_cast<NamedDecl *>(Template), Constraint.getSourceRange()); - NumExpansions = S.EvaluateFoldExpandedConstraintSize( - Constraint.getPattern(), *SubstitutedArgs); - } + ExprResult Out; + UnsignedOrNone NumExpansions = + EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs); if (!NumExpansions) return ExprEmpty(); @@ -983,7 +1004,6 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow( return ExprEmpty(); } - ExprResult Out; for (unsigned I = 0; I < *NumExpansions; I++) { Sema::ArgPackSubstIndexRAII SubstIndex(S, I); Satisfaction.IsSatisfied = false; @@ -1392,6 +1412,98 @@ SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D, MLTAL); } +bool Sema::SetupConstraintScope( + FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, + const MultiLevelTemplateArgumentList &MLTAL, + LocalInstantiationScope &Scope) { + assert(!isLambdaCallOperator(FD) && + "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda " + "instantiations"); + if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { + FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); + InstantiatingTemplate Inst( + *this, FD->getPointOfInstantiation(), + Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate, + TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, + SourceRange()); + if (Inst.isInvalid()) + return true; + + // addInstantiatedParametersToScope creates a map of 'uninstantiated' to + // 'instantiated' parameters and adds it to the context. For the case where + // this function is a template being instantiated NOW, we also need to add + // the list of current template arguments to the list so that they also can + // be picked out of the map. + if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) { + MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(), + /*Final=*/false); + if (addInstantiatedParametersToScope( + FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs)) + return true; + } + + // If this is a member function, make sure we get the parameters that + // reference the original primary template. + if (FunctionTemplateDecl *FromMemTempl = + PrimaryTemplate->getInstantiatedFromMemberTemplate()) { + if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(), + Scope, MLTAL)) + return true; + } + + return false; + } + + if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || + FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) { + FunctionDecl *InstantiatedFrom = + FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization + ? FD->getInstantiatedFromMemberFunction() + : FD->getInstantiatedFromDecl(); + + InstantiatingTemplate Inst( + *this, FD->getPointOfInstantiation(), + Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom, + TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, + SourceRange()); + if (Inst.isInvalid()) + return true; + + // Case where this was not a template, but instantiated as a + // child-function. + if (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( + 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 = + getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), + /*Final=*/false, /*Innermost=*/std::nullopt, + /*RelativeToPrimary=*/true, + /*Pattern=*/nullptr, + /*ForConstraintInstantiation=*/true); + // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII. + if (isLambdaCallOperator(FD)) + return MLTAL; + if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) + return std::nullopt; + + return MLTAL; +} + bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc, @@ -1431,12 +1543,12 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, ContextRAII SavedContext{*this, CtxToSave}; LocalInstantiationScope Scope(*this, !ForOverloadResolution); - MultiLevelTemplateArgumentList MLTAL = - getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), - /*Final=*/false, /*Innermost=*/std::nullopt, - /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, - /*ForConstraintInstantiation=*/true); + std::optional<MultiLevelTemplateArgumentList> MLTAL = + SetupConstraintCheckingTemplateArgumentsAndScope( + const_cast<FunctionDecl *>(FD), {}, Scope); + + if (!MLTAL) + return true; Qualifiers ThisQuals; CXXRecordDecl *Record = nullptr; @@ -1447,11 +1559,11 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); LambdaScopeForCallOperatorInstantiationRAII LambdaScope( - *this, const_cast<FunctionDecl *>(FD), MLTAL, Scope, + *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope, ForOverloadResolution); return CheckConstraintSatisfaction( - FD, FD->getTrailingRequiresClause(), MLTAL, + FD, FD->getTrailingRequiresClause(), *MLTAL, SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), Satisfaction); } @@ -1684,12 +1796,12 @@ bool Sema::CheckFunctionTemplateConstraints( Sema::ContextRAII savedContext(*this, Decl); LocalInstantiationScope Scope(*this); - MultiLevelTemplateArgumentList MLTAL = - getTemplateInstantiationArgs(Decl, Decl->getLexicalDeclContext(), - /*Final=*/false, /*Innermost=*/std::nullopt, - /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, - /*ForConstraintInstantiation=*/true); + std::optional<MultiLevelTemplateArgumentList> MLTAL = + SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs, + Scope); + + if (!MLTAL) + return true; Qualifiers ThisQuals; CXXRecordDecl *Record = nullptr; @@ -1699,10 +1811,10 @@ bool Sema::CheckFunctionTemplateConstraints( } CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); - LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, MLTAL, + LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL, Scope); - return CheckConstraintSatisfaction(Template, TemplateAC, MLTAL, + return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL, PointOfInstantiation, Satisfaction); } @@ -1975,7 +2087,7 @@ void Sema::DiagnoseUnsatisfiedConstraint( ConstraintExpr->getBeginLoc(), First); } -namespace clang { +namespace { class SubstituteParameterMappings { Sema &SemaRef; @@ -2013,8 +2125,6 @@ class SubstituteParameterMappings { bool substitute(NormalizedConstraint &N); }; -} // namespace clang - void SubstituteParameterMappings::buildParameterMapping( NormalizedConstraintWithParamMapping &N) { TemplateParameterList *TemplateParams = @@ -2308,6 +2418,8 @@ bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) { llvm_unreachable("Unknown ConstraintKind enum"); } +} // namespace + NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints( Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) { assert(ACs.size() != 0); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index cadc5689cebc2..ffbe8bb0506bc 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1324,10 +1324,11 @@ namespace { bool BailOutOnIncomplete; std::optional<llvm::FoldingSetNodeID> TemplateArgsHashValue; - llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc> - *CurrentCachedTemplateArgs = nullptr; - bool instantiateMissingDeclsToScopeForConcepts(Decl *D); + // CWG2770: Function parameters should be instantiated when they are + // needed by a satisfaction check of an atomic constraint or + // (recursively) by another function parameter. + bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm); public: typedef TreeTransform<TemplateInstantiator> inherited; @@ -1357,14 +1358,12 @@ namespace { inline static struct ForConstraintSubstitution_t { } ForConstraintSubstitution; - TemplateInstantiator( - ForParameterMappingSubstitution_t, Sema &SemaRef, SourceLocation Loc, - const MultiLevelTemplateArgumentList &TemplateArgs, - llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc> *Cache) + TemplateInstantiator(ForParameterMappingSubstitution_t, Sema &SemaRef, + SourceLocation Loc, + const MultiLevelTemplateArgumentList &TemplateArgs) : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc), - EvaluateLambdaConstraint(true), BailOutOnIncomplete(false), - CurrentCachedTemplateArgs(Cache) { - if (!Cache) + EvaluateLambdaConstraint(true), BailOutOnIncomplete(false) { + if (!SemaRef.CurrentCachedTemplateArgs) return; auto &V = TemplateArgsHashValue.emplace(); for (auto &Level : TemplateArgs) @@ -1411,18 +1410,22 @@ namespace { ArrayRef<UnexpandedParameterPack> Unexpanded, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, - UnsignedOrNone &NumExpansions, - bool Diagnose = true) { - for (UnexpandedParameterPack ParmPack : Unexpanded) { - if (instantiateMissingDeclsToScopeForConcepts( - dyn_cast<NamedDecl *>(ParmPack.first))) - return true; + UnsignedOrNone &NumExpansions) { + if (SemaRef.CurrentInstantiationScope && + (SemaRef.inConstraintSubstitution() || + SemaRef.inParameterMappingSubstitution())) { + for (UnexpandedParameterPack ParmPack : Unexpanded) { + NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>(); + if (auto *PVD = dyn_cast_if_present<ParmVarDecl>(VD); + PVD && maybeInstantiateFunctionParameterToScope(PVD)) + return true; + } } return getSema().CheckParameterPacksForExpansion( EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, FailOnPackProducingTemplates, ShouldExpand, RetainExpansion, - NumExpansions, Diagnose); + NumExpansions); } void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { @@ -1634,7 +1637,7 @@ namespace { TemplateArgumentLoc &Output, bool Uneval = false) { const TemplateArgument &Arg = Input.getArgument(); - if (auto *Cache = CurrentCachedTemplateArgs; + if (auto *Cache = SemaRef.CurrentCachedTemplateArgs; Cache && TemplateArgsHashValue) { llvm::FoldingSetNodeID ID = *TemplateArgsHashValue; ID.AddInteger(SemaRef.ArgPackSubstIndex.toInternalRepresentation()); @@ -1977,7 +1980,11 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { // template parameter. } - if (instantiateMissingDeclsToScopeForConcepts(D)) + if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D); + PVD && SemaRef.CurrentInstantiationScope && + (SemaRef.inConstraintSubstitution() || + SemaRef.inParameterMappingSubstitution()) && + maybeInstantiateFunctionParameterToScope(PVD)) return nullptr; if (isa<CXXExpansionStmtDecl>(D)) { @@ -1989,39 +1996,9 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs); } -bool TemplateInstantiator::instantiateMissingDeclsToScopeForConcepts(Decl *D) { - if (!(D && (SemaRef.inConstraintSubstitution() || - SemaRef.inParameterMappingSubstitution()))) - return false; - - auto *Current = SemaRef.CurrentInstantiationScope; - if (!Current) - return false; - if (Current->getInstantiationOfIfExists(D)) - return false; - - for (auto *Outer = Current->getOuterScope(); Outer; - Outer = Outer->getOuterScope()) { - auto *Pair = Outer->getInstantiationOfIfExists(D); - if (!Pair) - continue; - - if (auto *InstD = dyn_cast<Decl *>(*Pair)) { - Current->InstantiatedLocal(D, InstD); - } else { - Current->MakeInstantiatedLocalArgPack(D); - auto *Pack = cast<LocalInstantiationScope::DeclArgumentPack *>(*Pair); - for (auto *VD : *Pack) - Current->InstantiatedLocal(D, VD); - } - return false; - } - - // CWG2770: Function parameters should be instantiated when they are - // needed by a satisfaction check of an atomic constraint or - // (recursively) by another function parameter. - auto *OldParm = dyn_cast<ParmVarDecl>(D); - if (!OldParm) +bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope( + ParmVarDecl *OldParm) { + if (SemaRef.CurrentInstantiationScope->getInstantiationOfIfExists(OldParm)) return false; if (!OldParm->isParameterPack()) @@ -2482,7 +2459,11 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { // Handle references to function parameter packs. if (VarDecl *PD = dyn_cast<VarDecl>(D)) if (PD->isParameterPack()) { - if (instantiateMissingDeclsToScopeForConcepts(PD)) + if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(PD); + PVD && SemaRef.CurrentInstantiationScope && + (SemaRef.inConstraintSubstitution() || + SemaRef.inParameterMappingSubstitution()) && + maybeInstantiateFunctionParameterToScope(PVD)) return ExprError(); return TransformFunctionParmPackRefExpr(E, PD); @@ -4505,35 +4486,10 @@ bool Sema::SubstTemplateArgumentsInParameterMapping( TemplateArgumentListInfo &Out) { TemplateInstantiator Instantiator( TemplateInstantiator::ForParameterMappingSubstitution, *this, BaseLoc, - TemplateArgs, CurrentCachedTemplateArgs); + TemplateArgs); return Instantiator.TransformTemplateArguments(Args.begin(), Args.end(), Out); } -UnsignedOrNone Sema::EvaluateFoldExpandedConstraintSize( - const Expr *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs) { - TemplateInstantiator Instantiator( - TemplateInstantiator::ForConstraintSubstitution, *this, TemplateArgs, - SourceLocation(), DeclarationName()); - - SmallVector<UnexpandedParameterPack, 2> Unexpanded; - collectUnexpandedParameterPacks(const_cast<Expr *>(Pattern), Unexpanded); - assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); - - bool Expand = true; - bool RetainExpansion = false; - UnsignedOrNone NumExpansions(std::nullopt); - if (Instantiator.TryExpandParameterPacks( - Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, - /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion, - NumExpansions, /*Diagnose=*/false) || - !Expand || RetainExpansion) - return std::nullopt; - - if (NumExpansions && getLangOpts().BracketDepth < *NumExpansions) - return std::nullopt; - return NumExpansions; -} - ExprResult Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) { if (!E) diff --git a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp index b4f763f7fdb7d..d3e681f22ab26 100644 --- a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp +++ b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp @@ -692,29 +692,3 @@ void g() { } } - -namespace GH198052 { - -template <class T, class U> -concept is_same = __is_same(T, U); - -constexpr int NumberOfTrueInstances(auto... booleans) - requires (is_same<bool, decltype(booleans)> && ...) -{ - bool the_booleans[] = {booleans...}; - int nrvo = 0; - for (bool a_boolean : the_booleans) { - if (a_boolean) nrvo += 1; - } - return nrvo; -} - -constexpr bool a = true; -constexpr bool b = false; -constexpr bool c = true; -constexpr bool d = false; -constexpr int count = NumberOfTrueInstances(a, b, c, d); -static_assert(count == 2); - -} - diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp index 26deec7ad7777..2010a028fce4a 100644 --- a/clang/test/SemaTemplate/concepts-lambda.cpp +++ b/clang/test/SemaTemplate/concepts-lambda.cpp @@ -493,19 +493,3 @@ static_assert(count_if_v_bad_2<L, double> == 111); static_assert(count_if_v_bad_2<L, char> == 111); } - -namespace GH209632 { - -template <class A, class B> concept same_as = __is_same(A, B); - -template <class NR> void f(NR) { - using N = NR; - auto inner = [](same_as<N> auto) {}; - inner(N{}); -} - -void main() { - f(0); -} - -} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
