diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 8413090e7ebd1..11d2d5c3938c1 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -264,14 +264,6 @@ class HashParameterMapping : public RecursiveASTVisitor { UnsignedOrNone OuterPackSubstIndex; - TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) { - assert(*SemaRef.ArgPackSubstIndex < Arg.pack_size()); - Arg = Arg.pack_begin()[*SemaRef.ArgPackSubstIndex]; - if (Arg.isPackExpansion()) - Arg = Arg.getPackExpansionPattern(); - return Arg; - } - bool shouldVisitTemplateInstantiations() const { return true; } public: @@ -294,7 +286,7 @@ class HashParameterMapping : public RecursiveASTVisitor { assert(Arg.getKind() == TemplateArgument::Pack && "Missing argument pack"); - Arg = getPackSubstitutedTemplateArgument(Arg); + Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg); } UsedTemplateArgs.push_back( @@ -312,7 +304,7 @@ class HashParameterMapping : public RecursiveASTVisitor { if (NTTP->isParameterPack() && SemaRef.ArgPackSubstIndex) { assert(Arg.getKind() == TemplateArgument::Pack && "Missing argument pack"); - Arg = getPackSubstitutedTemplateArgument(Arg); + Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg); } UsedTemplateArgs.push_back( @@ -325,8 +317,11 @@ class HashParameterMapping : public RecursiveASTVisitor { } bool TraverseDecl(Decl *D) { - if (auto *VD = dyn_cast(D)) + if (auto *VD = dyn_cast(D)) { + if (auto *Var = dyn_cast(VD)) + TraverseStmt(Var->getInit()); return TraverseType(VD->getType()); + } return inherited::TraverseDecl(D); } @@ -363,6 +358,14 @@ class HashParameterMapping : public RecursiveASTVisitor { return inherited::TraverseTemplateArgument(Arg); } + bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) { + return TraverseDecl(SOPE->getPack()); + } + + bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) { + return inherited::TraverseStmt(E->getReplacement()); + } + void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) { if (!Constraint.hasParameterMapping()) { for (const auto &List : TemplateArgs) @@ -2083,8 +2086,8 @@ bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) { /*UpdateArgsWithConversions=*/false)) return true; auto TemplateArgs = *MLTAL; - TemplateArgs.replaceOutermostTemplateArguments( - TemplateArgs.getAssociatedDecl(0).first, CTAI.SugaredConverted); + TemplateArgs.replaceOutermostTemplateArguments(CSE->getNamedConcept(), + CTAI.SugaredConverted); return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten, InFoldExpr) .substitute(CC.getNormalizedConstraint()); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 6bba505ece07d..3baa9775a49e4 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -6718,6 +6718,10 @@ struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor { } return true; } + + bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) override { + return TraverseDecl(SOPE->getPack()); + } }; } diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 6d29f8b798e73..e5e081ffb9d0f 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1333,4 +1333,75 @@ static_assert(__cpp17_iterator); \ // expected-note@#is_move_constructible_v {{because 'is_move_constructible_v' evaluated to false}} } +namespace case4 { + +template +concept bool_ = b; + +template +concept unary = bool_; + +static_assert(!unary<>); +static_assert(unary); + +} + +namespace case5 { + +template +concept true1 = size == size; + +template +concept true2 = true1; + +template +concept true3 = true2; + +static_assert(true3); + +} + +namespace case6 { + +namespace std { +template +struct integral_constant { + static const int value = __v; +}; + +template +constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...); + +template +constexpr bool is_convertible_v = __is_convertible(_From, _To); + +template +struct tuple_size; + +template +constexpr decltype(sizeof(int)) tuple_size_v = tuple_size<_Tp>::value; +} // namespace std + +template +concept FixedExtentConstructibleFromExtent = X == N; + +template +struct span { + int static constexpr extent = Extent; + template > + requires(FixedExtentConstructibleFromExtent) + span(R); +}; + +template +struct array {}; + +template +struct std::tuple_size> : integral_constant<_Size> {}; + +static_assert(std::is_convertible_v, span<3>>); +static_assert(!std::is_constructible_v, array>); + +} + }