From b8064374b217db061213c561ec8f3376681ff9c8 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Sun, 23 Oct 2022 11:37:20 +0200 Subject: [PATCH] [clang] Instantiate concepts with sugared template arguments Since we don't unique specializations for concepts, we can just instantiate them with the sugared template arguments, at negligible cost. If we don't track their specializations, we can't resugar them later anyway, and that would be more expensive than just instantiating them sugared in the first place since it would require an additional pass. Signed-off-by: Matheus Izvekov Differential Revision: https://reviews.llvm.org/D136566 --- clang/lib/Sema/SemaConcept.cpp | 2 +- clang/lib/Sema/SemaExprCXX.cpp | 204 +++++++++++---------- clang/lib/Sema/SemaTemplate.cpp | 12 +- clang/lib/Sema/SemaTemplateDeduction.cpp | 10 +- clang/lib/Serialization/ASTReaderDecl.cpp | 2 +- clang/test/AST/ast-dump-concepts.cpp | 10 +- .../expr.prim.req/compound-requirement.cpp | 10 +- .../expr.prim/expr.prim.req/nested-requirement.cpp | 2 +- .../expr.prim/expr.prim.req/simple-requirement.cpp | 4 +- .../expr.prim/expr.prim.req/type-requirement.cpp | 12 +- .../CXX/temp/temp.constr/temp.constr.normal/p1.cpp | 2 +- clang/test/CXX/temp/temp.param/p10-2a.cpp | 4 +- .../test/SemaTemplate/cxx2a-constraint-caching.cpp | 12 +- .../SemaTemplate/instantiate-requires-expr.cpp | 16 +- clang/test/SemaTemplate/pr52970.cpp | 2 +- 15 files changed, 160 insertions(+), 144 deletions(-) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 83b23b2..ff1f650 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1077,7 +1077,7 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, TemplateArgumentList TAL{TemplateArgumentList::OnStack, CSE->getTemplateArguments()}; MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( - CSE->getNamedConcept(), /*Final=*/false, &TAL, + CSE->getNamedConcept(), /*Final=*/true, &TAL, /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 25eeab3..bb9cfe3 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1475,53 +1475,57 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, // C++2b: // Otherwise, if the type contains a placeholder type, it is replaced by the // type determined by placeholder type deduction. - DeducedType *Deduced = Ty->getContainedDeducedType(); - if (Deduced && isa(Deduced)) { - Ty = DeduceTemplateSpecializationFromInitializer(TInfo, Entity, - Kind, Exprs); - if (Ty.isNull()) - return ExprError(); - Entity = InitializedEntity::InitializeTemporary(TInfo, Ty); - } else if (Deduced) { - MultiExprArg Inits = Exprs; - if (ListInitialization) { - auto *ILE = cast(Exprs[0]); - Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits()); - } + if (const DeducedType *Deduced = Ty->getContainedDeducedType(); + Deduced && !Deduced->isDeduced()) { + if (isa(Deduced)) { + Ty = DeduceTemplateSpecializationFromInitializer(TInfo, Entity, Kind, + Exprs); + if (Ty.isNull()) + return ExprError(); + Entity = InitializedEntity::InitializeTemporary(TInfo, Ty); + } else { + assert(isa(Deduced)); + MultiExprArg Inits = Exprs; + if (ListInitialization) { + auto *ILE = cast(Exprs[0]); + Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits()); + } - if (Inits.empty()) - return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_init_no_expression) - << Ty << FullRange); - if (Inits.size() > 1) { - Expr *FirstBad = Inits[1]; - return ExprError(Diag(FirstBad->getBeginLoc(), - diag::err_auto_expr_init_multiple_expressions) - << Ty << FullRange); - } - if (getLangOpts().CPlusPlus2b) { - if (Ty->getAs()) - Diag(TyBeginLoc, diag::warn_cxx20_compat_auto_expr) << FullRange; - } - Expr *Deduce = Inits[0]; - if (isa(Deduce)) - return ExprError( - Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces) - << ListInitialization << Ty << FullRange); - QualType DeducedType; - TemplateDeductionInfo Info(Deduce->getExprLoc()); - TemplateDeductionResult Result = - DeduceAutoType(TInfo->getTypeLoc(), Deduce, DeducedType, Info); - if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) - return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_deduction_failure) - << Ty << Deduce->getType() << FullRange - << Deduce->getSourceRange()); - if (DeducedType.isNull()) { - assert(Result == TDK_AlreadyDiagnosed); - return ExprError(); - } + if (Inits.empty()) + return ExprError( + Diag(TyBeginLoc, diag::err_auto_expr_init_no_expression) + << Ty << FullRange); + if (Inits.size() > 1) { + Expr *FirstBad = Inits[1]; + return ExprError(Diag(FirstBad->getBeginLoc(), + diag::err_auto_expr_init_multiple_expressions) + << Ty << FullRange); + } + if (getLangOpts().CPlusPlus2b) { + if (Ty->getAs()) + Diag(TyBeginLoc, diag::warn_cxx20_compat_auto_expr) << FullRange; + } + Expr *Deduce = Inits[0]; + if (isa(Deduce)) + return ExprError( + Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces) + << ListInitialization << Ty << FullRange); + QualType DeducedType; + TemplateDeductionInfo Info(Deduce->getExprLoc()); + TemplateDeductionResult Result = + DeduceAutoType(TInfo->getTypeLoc(), Deduce, DeducedType, Info); + if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) + return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_deduction_failure) + << Ty << Deduce->getType() << FullRange + << Deduce->getSourceRange()); + if (DeducedType.isNull()) { + assert(Result == TDK_AlreadyDiagnosed); + return ExprError(); + } - Ty = DeducedType; - Entity = InitializedEntity::InitializeTemporary(TInfo, Ty); + Ty = DeducedType; + Entity = InitializedEntity::InitializeTemporary(TInfo, Ty); + } } if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) { @@ -2011,59 +2015,62 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, DirectInitRange.getEnd()); // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for. - auto *Deduced = AllocType->getContainedDeducedType(); - if (Deduced && isa(Deduced)) { - if (ArraySize) - return ExprError( - Diag(*ArraySize ? (*ArraySize)->getExprLoc() : TypeRange.getBegin(), - diag::err_deduced_class_template_compound_type) - << /*array*/ 2 - << (*ArraySize ? (*ArraySize)->getSourceRange() : TypeRange)); + if (const DeducedType *Deduced = AllocType->getContainedDeducedType(); + Deduced && !Deduced->isDeduced()) { + if (isa(Deduced)) { + if (ArraySize) + return ExprError( + Diag(*ArraySize ? (*ArraySize)->getExprLoc() : TypeRange.getBegin(), + diag::err_deduced_class_template_compound_type) + << /*array*/ 2 + << (*ArraySize ? (*ArraySize)->getSourceRange() : TypeRange)); + + InitializedEntity Entity = + InitializedEntity::InitializeNew(StartLoc, AllocType); + AllocType = DeduceTemplateSpecializationFromInitializer( + AllocTypeInfo, Entity, Kind, Exprs); + if (AllocType.isNull()) + return ExprError(); + } else { + assert(isa(Deduced)); + MultiExprArg Inits = Exprs; + bool Braced = (initStyle == CXXNewExpr::ListInit); + if (Braced) { + auto *ILE = cast(Exprs[0]); + Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits()); + } - InitializedEntity Entity - = InitializedEntity::InitializeNew(StartLoc, AllocType); - AllocType = DeduceTemplateSpecializationFromInitializer( - AllocTypeInfo, Entity, Kind, Exprs); - if (AllocType.isNull()) - return ExprError(); - } else if (Deduced) { - MultiExprArg Inits = Exprs; - bool Braced = (initStyle == CXXNewExpr::ListInit); - if (Braced) { - auto *ILE = cast(Exprs[0]); - Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits()); - } - - if (initStyle == CXXNewExpr::NoInit || Inits.empty()) - return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) - << AllocType << TypeRange); - if (Inits.size() > 1) { - Expr *FirstBad = Inits[1]; - return ExprError(Diag(FirstBad->getBeginLoc(), - diag::err_auto_new_ctor_multiple_expressions) - << AllocType << TypeRange); - } - if (Braced && !getLangOpts().CPlusPlus17) - Diag(Initializer->getBeginLoc(), diag::ext_auto_new_list_init) - << AllocType << TypeRange; - Expr *Deduce = Inits[0]; - if (isa(Deduce)) - return ExprError( - Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces) - << Braced << AllocType << TypeRange); - QualType DeducedType; - TemplateDeductionInfo Info(Deduce->getExprLoc()); - TemplateDeductionResult Result = - DeduceAutoType(AllocTypeInfo->getTypeLoc(), Deduce, DeducedType, Info); - if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) - return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) - << AllocType << Deduce->getType() << TypeRange - << Deduce->getSourceRange()); - if (DeducedType.isNull()) { - assert(Result == TDK_AlreadyDiagnosed); - return ExprError(); + if (initStyle == CXXNewExpr::NoInit || Inits.empty()) + return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) + << AllocType << TypeRange); + if (Inits.size() > 1) { + Expr *FirstBad = Inits[1]; + return ExprError(Diag(FirstBad->getBeginLoc(), + diag::err_auto_new_ctor_multiple_expressions) + << AllocType << TypeRange); + } + if (Braced && !getLangOpts().CPlusPlus17) + Diag(Initializer->getBeginLoc(), diag::ext_auto_new_list_init) + << AllocType << TypeRange; + Expr *Deduce = Inits[0]; + if (isa(Deduce)) + return ExprError( + Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces) + << Braced << AllocType << TypeRange); + QualType DeducedType; + TemplateDeductionInfo Info(Deduce->getExprLoc()); + TemplateDeductionResult Result = DeduceAutoType( + AllocTypeInfo->getTypeLoc(), Deduce, DeducedType, Info); + if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) + return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) + << AllocType << Deduce->getType() << TypeRange + << Deduce->getSourceRange()); + if (DeducedType.isNull()) { + assert(Result == TDK_AlreadyDiagnosed); + return ExprError(); + } + AllocType = DeducedType; } - AllocType = DeducedType; } // Per C++0x [expr.new]p5, the type being constructed may be a @@ -8956,8 +8963,7 @@ Sema::BuildExprRequirement( // be satisfied. TemplateParameterList *TPL = ReturnTypeRequirement.getTypeConstraintTemplateParameterList(); - QualType MatchedType = - Context.getReferenceQualifiedType(E).getCanonicalType(); + QualType MatchedType = Context.getReferenceQualifiedType(E); llvm::SmallVector Args; Args.push_back(TemplateArgument(MatchedType)); @@ -8965,7 +8971,7 @@ Sema::BuildExprRequirement( TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args); MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray(), - /*Final=*/false); + /*Final=*/true); MLTAL.addOuterRetainedLevels(TPL->getDepth()); Expr *IDC = Param->getTypeConstraint()->getImmediatelyDeclaredConstraint(); ExprResult Constraint = SubstExpr(IDC, MLTAL); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c5a8648..5cdc0ba 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4861,13 +4861,13 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, auto *CSD = ImplicitConceptSpecializationDecl::Create( Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(), - CanonicalConverted); + SugaredConverted); ConstraintSatisfaction Satisfaction; bool AreArgsDependent = TemplateSpecializationType::anyDependentTemplateArguments( - *TemplateArgs, CanonicalConverted); - MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted, - /*Final=*/false); + *TemplateArgs, SugaredConverted); + MultiLevelTemplateArgumentList MLTAL(NamedConcept, SugaredConverted, + /*Final=*/true); LocalInstantiationScope Scope(*this); EnterExpressionEvaluationContext EECtx{ @@ -6098,7 +6098,7 @@ bool Sema::CheckTemplateArgumentList( if (!PartialTemplateArgs) { TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack, - CanonicalConverted); + SugaredConverted); // Setup the context/ThisScope for the case where we are needing to // re-instantiate constraints outside of normal instantiation. DeclContext *NewContext = Template->getDeclContext(); @@ -6118,7 +6118,7 @@ bool Sema::CheckTemplateArgumentList( CXXThisScopeRAII(*this, RD, ThisQuals, RD != nullptr); MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs( - Template, /*Final=*/false, &StackTemplateArgs, + Template, /*Final=*/true, &StackTemplateArgs, /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConceptInstantiation=*/true); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index e078d3d..17c0e2f 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2886,10 +2886,10 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, bool NeedsReplacement = DeducedArgsNeedReplacement(Template); TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack, - CanonicalDeducedArgs}; + SugaredDeducedArgs}; MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( - Template, /*Final=*/false, + Template, /*Final=*/true, /*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL, /*RelativeToPrimary=*/true, /*Pattern=*/ nullptr, /*ForConstraintInstantiation=*/true); @@ -2899,7 +2899,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, // not class-scope explicit specialization, so replace with Deduced Args // instead of adding to inner-most. if (NeedsReplacement) - MLTAL.replaceInnermostTemplateArguments(CanonicalDeducedArgs); + MLTAL.replaceInnermostTemplateArguments(SugaredDeducedArgs); if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL, Info.getLocation(), @@ -4672,8 +4672,8 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type, /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted)) return true; - MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted, - /*Final=*/false); + MultiLevelTemplateArgumentList MLTAL(Concept, SugaredConverted, + /*Final=*/true); if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()}, MLTAL, TypeLoc.getLocalSourceRange(), Satisfaction)) diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 94a1d24..cabf06d 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2243,7 +2243,7 @@ void ASTDeclReader::VisitImplicitConceptSpecializationDecl( VisitDecl(D); llvm::SmallVector Args; for (unsigned I = 0; I < D->NumTemplateArgs; ++I) - Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/true)); + Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/false)); D->setTemplateArguments(Args); } diff --git a/clang/test/AST/ast-dump-concepts.cpp b/clang/test/AST/ast-dump-concepts.cpp index 06518a7..b835ab5 100644 --- a/clang/test/AST/ast-dump-concepts.cpp +++ b/clang/test/AST/ast-dump-concepts.cpp @@ -20,8 +20,9 @@ struct Foo { // CHECK: TemplateTypeParmDecl {{.*}} referenced Concept {{.*}} 'binary_concept' // CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} 'bool' Concept {{.*}} 'binary_concept' // CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} col:9 - // CHECK-NEXT: | |-TemplateArgument type 'type-parameter-1-0' - // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent {{.*}}depth 1 index 0 + // CHECK-NEXT: | |-TemplateArgument type 'R' + // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'R' dependent {{.*}}depth 1 index 0 + // CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'R' // CHECK-NEXT: | `-TemplateArgument type 'int' // CHECK-NEXT: | `-BuiltinType {{.*}} 'int' // CHECK-NEXT: |-TemplateArgument {{.*}} type 'R' @@ -35,8 +36,9 @@ struct Foo { // CHECK: TemplateTypeParmDecl {{.*}} referenced Concept {{.*}} 'unary_concept' // CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} 'bool' // CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} col:9 - // CHECK-NEXT: | `-TemplateArgument type 'type-parameter-1-0' - // CHECK-NEXT: | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent {{.*}}depth 1 index 0 + // CHECK-NEXT: | `-TemplateArgument type 'R' + // CHECK-NEXT: | `-TemplateTypeParmType {{.*}} 'R' dependent {{.*}}depth 1 index 0 + // CHECK-NEXT: | `-TemplateTypeParm {{.*}} 'R' template Foo(R); diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp index b736620..7f5bbc5 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp @@ -35,14 +35,14 @@ using r2i2 = r2; // expected-error{{constraints not satisfied for class templ using r2i3 = r2; using r2i4 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}} -template requires requires { { sizeof(T) }; } // expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}} +template requires requires { { sizeof(T) }; } // expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'class nonexistent'}} struct r3 {}; using r3i1 = r3; using r3i2 = r3; using r3i3 = r3; using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}} -using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}} +using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = class nonexistent]}} // Non-dependent expressions @@ -149,7 +149,7 @@ namespace std_example { template constexpr bool is_same_v = true; template concept same_as = is_same_v; - // expected-note@-1 {{because 'is_same_v' evaluated to false}} + // expected-note@-1 {{because 'is_same_v' evaluated to false}} static_assert(C1); static_assert(C1); @@ -173,9 +173,9 @@ namespace std_example { int operator *() { return 0; } }; static_assert(C2); - template struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'std_example::T2' does not satisfy 'C2'}} + template struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'T2' does not satisfy 'C2'}} using c2c1 = C2_check; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = int]}} - using c2c2 = C2_check; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::T2]}} + using c2c2 = C2_check; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = T2]}} template void g(T t) noexcept(sizeof(T) == 1) {} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp index da4c169..7be1429 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp @@ -27,7 +27,7 @@ using r4i = X::r4; // expected-error{{constraints not satisfied for c // C++ [expr.prim.req.nested] Examples namespace std_example { - template concept C1 = sizeof(U) == 1; // expected-note{{because 'sizeof(int) == 1' (4 == 1) evaluated to false}} + template concept C1 = sizeof(U) == 1; // expected-note{{because 'sizeof(decltype(+t)) == 1' (4 == 1) evaluated to false}} template concept D = requires (T t) { requires C1; // expected-note{{because 'decltype(+t)' (aka 'int') does not satisfy 'C1'}} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp index 624c905..e491e03 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp @@ -39,14 +39,14 @@ using r2i4 = r2; // expected-error{{constraints not satisfied for class template requires requires { sizeof(T); } // expected-note@-1{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} -// expected-note@-2{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}} +// expected-note@-2{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'class nonexistent'}} struct r3 {}; using r3i1 = r3; using r3i2 = r3; using r3i3 = r3; using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}} -using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}} +using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = class nonexistent]}} template requires requires (T t) { 0; "a"; (void)'a'; } struct r4 {}; diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp index 5433cfb..28dff33 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp @@ -182,14 +182,14 @@ namespace std_example { static_assert(C1 && C2 && C3); template struct C1_check {}; // expected-note@-1 {{because 'int' does not satisfy 'C1'}} - // expected-note@-2 {{because 'std_example::has_type' does not satisfy 'C1'}} + // expected-note@-2 {{because 'has_type' does not satisfy 'C1'}} template struct C2_check {}; - // expected-note@-1 {{because 'std_example::has_inner' does not satisfy 'C2'}} + // expected-note@-1 {{because 'has_inner' does not satisfy 'C2'}} template struct C3_check {}; // expected-note@-1 {{because 'void' does not satisfy 'C3'}} using c1 = C1_check; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = int]}} - using c2 = C1_check; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = std_example::has_type]}} - using c3 = C2_check; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::has_inner]}} + using c2 = C1_check; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = has_type]}} + using c3 = C2_check; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = has_inner]}} using c4 = C3_check; // expected-error{{constraints not satisfied for class template 'C3_check' [with T = void]}} } @@ -199,10 +199,10 @@ template concept C = requires { requires requires { T::a; }; }; // expected-note@-1 {{because 'T::a' would be invalid: no member named 'a' in 'PR48656::T1'}} template struct A {}; -// expected-note@-1 {{because 'PR48656::T1' does not satisfy 'C'}} +// expected-note@-1 {{because 'T1' does not satisfy 'C'}} struct T1 {}; -template struct A; // expected-error {{constraints not satisfied for class template 'A' [with $0 = ]}} +template struct A; // expected-error {{constraints not satisfied for class template 'A' [with $0 = ]}} struct T2 { static constexpr bool a = false; }; template struct A; diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp index d807109..02c97b4 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp @@ -8,7 +8,7 @@ template requires Bar && true struct S { }; template concept True2 = sizeof(T) >= 0; template concept Foo2 = True2; -// expected-error@-1{{'type name' declared as a pointer to a reference of type 'type-parameter-0-0 &'}} +// expected-error@-1{{'type name' declared as a pointer to a reference of type 'T &'}} template concept Bar2 = Foo2; // expected-note@-1{{while substituting into concept arguments here; substitution failures not allowed in concept arguments}} template requires Bar2 struct S2 { }; diff --git a/clang/test/CXX/temp/temp.param/p10-2a.cpp b/clang/test/CXX/temp/temp.param/p10-2a.cpp index 4f5fdd3..97e0ef3 100644 --- a/clang/test/CXX/temp/temp.param/p10-2a.cpp +++ b/clang/test/CXX/temp/temp.param/p10-2a.cpp @@ -94,8 +94,8 @@ concept OneOf = (is_same_v || ...); // expected-note@-5 {{and 'is_same_v' evaluated to false}} // expected-note@-6 3{{because 'is_same_v' evaluated to false}} // expected-note@-7 3{{and 'is_same_v' evaluated to false}} -// expected-note@-8 2{{because 'is_same_v' evaluated to false}} -// expected-note@-9 2{{and 'is_same_v' evaluated to false}} +// expected-note@-8 2{{because 'is_same_v' evaluated to false}} +// expected-note@-9 2{{and 'is_same_v' evaluated to false}} template T, OneOf U> // expected-note@-1 2{{because 'OneOf' evaluated to false}} diff --git a/clang/test/SemaTemplate/cxx2a-constraint-caching.cpp b/clang/test/SemaTemplate/cxx2a-constraint-caching.cpp index d44a429..6b6db37 100644 --- a/clang/test/SemaTemplate/cxx2a-constraint-caching.cpp +++ b/clang/test/SemaTemplate/cxx2a-constraint-caching.cpp @@ -14,15 +14,13 @@ constexpr bool foo() requires (f(T()), true) { return true; } namespace a { struct A {}; constexpr void f(A a) {} -} -static_assert(C); -static_assert(foo()); + static_assert(C); + static_assert(foo()); -namespace a { // This makes calls to f ambiguous, but the second check will still succeed // because the constraint satisfaction results are cached. constexpr void f(A a, int = 2) {} -} -static_assert(C); -static_assert(foo()); + static_assert(C); + static_assert(foo()); +} // namespace a diff --git a/clang/test/SemaTemplate/instantiate-requires-expr.cpp b/clang/test/SemaTemplate/instantiate-requires-expr.cpp index ba82fc1..a9d8b8b 100644 --- a/clang/test/SemaTemplate/instantiate-requires-expr.cpp +++ b/clang/test/SemaTemplate/instantiate-requires-expr.cpp @@ -76,8 +76,8 @@ namespace type_requirement { // expected-note@-2 {{because 'false_v::temp >; }>' evaluated to false}} struct r2 {}; - using r2i1 = r2>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template]}} - using r2i2 = r2>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template]}} + using r2i1 = r2>; // expected-error{{constraints not satisfied for class template 'r2' [with T = contains_template]}} + using r2i2 = r2>; // expected-error{{constraints not satisfied for class template 'r2' [with T = contains_template]}} // substitution error occurs, then requires expr is instantiated again @@ -108,7 +108,7 @@ namespace type_requirement { // expected-note@-1 {{because 'false_v>; } && requires { <>; }>' evaluated to false}} struct r7 {}; - using r7i = r7; // expected-error{{constraints not satisfied for class template 'r7' [with Ts = ]}} + using r7i = r7; // expected-error{{constraints not satisfied for class template 'r7' [with Ts = ]}} } namespace expr_requirement { @@ -227,3 +227,13 @@ struct r6 {}; using r6i = r6; // expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}} + +namespace sugared_instantiation { + template concept C = requires { C1{}; }; + template concept D = requires { new D1; }; + + // Test that 'deduced auto' doesn't get confused with 'undeduced auto'. + auto f() { return 0; } + static_assert(requires { { f() } -> C; }); + static_assert(requires { { f() } -> D; }); +} // namespace sugared_instantiation diff --git a/clang/test/SemaTemplate/pr52970.cpp b/clang/test/SemaTemplate/pr52970.cpp index 7aac5ee..6aabc41 100644 --- a/clang/test/SemaTemplate/pr52970.cpp +++ b/clang/test/SemaTemplate/pr52970.cpp @@ -53,7 +53,7 @@ static_assert(!DotFollowingPointer::f(Bad{}), ""); #if __cplusplus >= 202002L template concept C = requires(T t) { t.begin(); }; - // cxx20-note@-1 {{because 't.begin()' would be invalid: member reference type 'Holder *' is a pointer}} + // cxx20-note@-1 {{because 't.begin()' would be invalid: member reference type 'Bad' (aka 'Holder *') is a pointer}} static_assert(C); static_assert(!C); -- 2.7.4