https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/68078
>From a14d189cfd513d4b2c8353fbab1a53927d2feaf5 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <corentinja...@gmail.com> Date: Tue, 3 Oct 2023 09:55:08 +0200 Subject: [PATCH 1/3] [Clang] Do not try to classify dependant call expression when the callee is an object. When implementing deducing this, we changed `DeduceTemplateArgumentsFromCallArgument` to take an argument classification because we need to deduce the type of argument for which we might not have an expression yet. However classifying a dependent call expression whose type is just some sort of record or elaborated type is not supported. We avoid that by adding a `DeduceTemplateArgumentsFromCallArgument` that takes a `IsLvalue` boolean so that we don't have to call `Classify`. The alternative might be to change `getCallReturnType` to support callees with type is a record type. Fixes #68024 --- clang/lib/Sema/SemaTemplateDeduction.cpp | 58 +++++++++++++------ .../SemaTemplate/temp_arg_nontype_cxx1z.cpp | 12 ++++ 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 69b857d3510dc63..53975068751e128 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3877,9 +3877,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, /// overloaded function set that could not be resolved. static bool AdjustFunctionParmAndArgTypesForDeduction( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType &ParamType, QualType &ArgType, - Expr::Classification ArgClassification, Expr *Arg, unsigned &TDF, - TemplateSpecCandidateSet *FailedTSC = nullptr) { + QualType &ParamType, QualType &ArgType, bool IsLValue, Expr *Arg, + unsigned &TDF, TemplateSpecCandidateSet *FailedTSC = nullptr) { // C++0x [temp.deduct.call]p3: // If P is a cv-qualified type, the top level cv-qualifiers of P's type // are ignored for type deduction. @@ -3914,7 +3913,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction( // If P is a forwarding reference and the argument is an lvalue, the type // "lvalue reference to A" is used in place of A for type deduction. if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) && - ArgClassification.isLValue()) { + IsLValue) { if (S.getLangOpts().OpenCL && !ArgType.hasAddressSpace()) ArgType = S.Context.getAddrSpaceQualType( ArgType, S.Context.getDefaultOpenCLPointeeAddrSpace()); @@ -3973,6 +3972,15 @@ static bool hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate, QualType T); +static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( + Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, + QualType ParamType, QualType ArgType, bool IsLValue, Expr *Arg, + TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, + bool DecomposedParam, unsigned ArgIdx, unsigned TDF, + TemplateSpecCandidateSet *FailedTSC = nullptr); + static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, QualType ParamType, QualType ArgType, @@ -4022,9 +4030,8 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( if (ElTy->isDependentType()) { for (Expr *E : ILE->inits()) { if (auto Result = DeduceTemplateArgumentsFromCallArgument( - S, TemplateParams, 0, ElTy, E->getType(), - E->Classify(S.getASTContext()), E, Info, Deduced, - OriginalCallArgs, true, ArgIdx, TDF)) + S, TemplateParams, 0, ElTy, E->getType(), E->isLValue(), E, Info, + Deduced, OriginalCallArgs, true, ArgIdx, TDF)) return Result; } } @@ -4055,8 +4062,7 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( /// single parameter / argument pair. static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType ParamType, QualType ArgType, - Expr::Classification ArgClassification, Expr *Arg, + QualType ParamType, QualType ArgType, bool IsLValue, Expr *Arg, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, @@ -4068,8 +4074,8 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( // If P is a reference type [...] // If P is a cv-qualified type [...] if (AdjustFunctionParmAndArgTypesForDeduction( - S, TemplateParams, FirstInnerIndex, ParamType, ArgType, - ArgClassification, Arg, TDF, FailedTSC)) + S, TemplateParams, FirstInnerIndex, ParamType, ArgType, IsLValue, Arg, + TDF, FailedTSC)) return Sema::TDK_Success; // If [...] the argument is a non-empty initializer list [...] @@ -4089,6 +4095,22 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( ArgType, Info, Deduced, TDF); } +static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( + Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, + QualType ParamType, QualType ArgType, + Expr::Classification ArgClassification, Expr *Arg, + TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, + bool DecomposedParam, unsigned ArgIdx, unsigned TDF, + TemplateSpecCandidateSet *FailedTSC) { + + return DeduceTemplateArgumentsFromCallArgument( + S, TemplateParams, FirstInnerIndex, ParamType, ArgType, + ArgClassification.isLValue(), Arg, Info, Deduced, OriginalCallArgs, + DecomposedParam, ArgIdx, TDF, FailedTSC); +} + /// Perform template argument deduction from a function call /// (C++ [temp.deduct.call]). /// @@ -4200,9 +4222,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // ... with the type of the corresponding argument return DeduceTemplateArgumentsFromCallArgument( *this, TemplateParams, FirstInnerIndex, ParamType, - Args[ArgIdx]->getType(), Args[ArgIdx]->Classify(getASTContext()), - Args[ArgIdx], Info, Deduced, OriginalCallArgs, /*Decomposed*/ false, - ArgIdx, /*TDF*/ 0); + Args[ArgIdx]->getType(), Args[ArgIdx]->isLValue(), Args[ArgIdx], Info, + Deduced, OriginalCallArgs, /*Decomposed*/ false, ArgIdx, /*TDF*/ 0); }; // Deduce template arguments from the function parameters. @@ -4904,8 +4925,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, return TDK_Invalid; if (auto TDK = DeduceTemplateArgumentsFromCallArgument( *this, TemplateParamsSt.get(), 0, TemplArg, Init->getType(), - Init->Classify(getASTContext()), Init, Info, Deduced, - OriginalCallArgs, /*Decomposed=*/true, + Init->isLValue(), Init, Info, Deduced, OriginalCallArgs, + /*Decomposed=*/true, /*ArgIdx=*/0, /*TDF=*/0)) { if (TDK == TDK_Inconsistent) { Diag(Info.getLocation(), diag::err_auto_inconsistent_deduction) @@ -4931,9 +4952,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, "substituting template parameter for 'auto' failed"); if (auto TDK = DeduceTemplateArgumentsFromCallArgument( *this, TemplateParamsSt.get(), 0, FuncParam, Init->getType(), - Init->Classify(getASTContext()), Init, Info, Deduced, - OriginalCallArgs, /*Decomposed=*/false, /*ArgIdx=*/0, /*TDF=*/0, - FailedTSC)) + Init->isLValue(), Init, Info, Deduced, OriginalCallArgs, + /*Decomposed=*/false, /*ArgIdx=*/0, /*TDF=*/0, FailedTSC)) return DeductionFailed(TDK); } diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp index 6ab9ecbfd573b25..22788e1c1ffb3ac 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp @@ -603,3 +603,15 @@ namespace PR47792 { template void bar<>(); // expected-note {{previous explicit instantiation is here}} template void bar<foo>(); // expected-error {{duplicate explicit instantiation of 'bar<&PR47792::foo>'}} } + +namespace GH68024 { +template<auto> +struct s {}; + +struct { + void operator()(int); +} f; + +template<typename T> +using a = s<f(T::x)>; +} >From 5dbe5bb9ed9e93a58d7c5231e211f0ceb78df4b5 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <corentinja...@gmail.com> Date: Tue, 3 Oct 2023 15:27:29 +0200 Subject: [PATCH 2/3] Try another, cleaner approach. --- clang/lib/AST/Expr.cpp | 4 ++ clang/lib/Sema/SemaTemplateDeduction.cpp | 58 ++++++++---------------- 2 files changed, 23 insertions(+), 39 deletions(-) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 99e89aeafc24217..e66dd532ce7488d 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1621,6 +1621,10 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { // This should never be overloaded and so should never return null. CalleeType = Expr::findBoundMemberType(Callee); assert(!CalleeType.isNull()); + } else if (CalleeType->isRecordType()) { + // If the Callee is a record type, then it is a not-yet-resolved + // dependent call to call operator of that type. + return Ctx.DependentTy; } else if (CalleeType->isDependentType() || CalleeType->isSpecificPlaceholderType(BuiltinType::Overload)) { return Ctx.DependentTy; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 53975068751e128..69b857d3510dc63 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3877,8 +3877,9 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, /// overloaded function set that could not be resolved. static bool AdjustFunctionParmAndArgTypesForDeduction( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType &ParamType, QualType &ArgType, bool IsLValue, Expr *Arg, - unsigned &TDF, TemplateSpecCandidateSet *FailedTSC = nullptr) { + QualType &ParamType, QualType &ArgType, + Expr::Classification ArgClassification, Expr *Arg, unsigned &TDF, + TemplateSpecCandidateSet *FailedTSC = nullptr) { // C++0x [temp.deduct.call]p3: // If P is a cv-qualified type, the top level cv-qualifiers of P's type // are ignored for type deduction. @@ -3913,7 +3914,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction( // If P is a forwarding reference and the argument is an lvalue, the type // "lvalue reference to A" is used in place of A for type deduction. if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) && - IsLValue) { + ArgClassification.isLValue()) { if (S.getLangOpts().OpenCL && !ArgType.hasAddressSpace()) ArgType = S.Context.getAddrSpaceQualType( ArgType, S.Context.getDefaultOpenCLPointeeAddrSpace()); @@ -3972,15 +3973,6 @@ static bool hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate, QualType T); -static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( - Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType ParamType, QualType ArgType, bool IsLValue, Expr *Arg, - TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, - bool DecomposedParam, unsigned ArgIdx, unsigned TDF, - TemplateSpecCandidateSet *FailedTSC = nullptr); - static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, QualType ParamType, QualType ArgType, @@ -4030,8 +4022,9 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( if (ElTy->isDependentType()) { for (Expr *E : ILE->inits()) { if (auto Result = DeduceTemplateArgumentsFromCallArgument( - S, TemplateParams, 0, ElTy, E->getType(), E->isLValue(), E, Info, - Deduced, OriginalCallArgs, true, ArgIdx, TDF)) + S, TemplateParams, 0, ElTy, E->getType(), + E->Classify(S.getASTContext()), E, Info, Deduced, + OriginalCallArgs, true, ArgIdx, TDF)) return Result; } } @@ -4062,7 +4055,8 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( /// single parameter / argument pair. static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType ParamType, QualType ArgType, bool IsLValue, Expr *Arg, + QualType ParamType, QualType ArgType, + Expr::Classification ArgClassification, Expr *Arg, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, @@ -4074,8 +4068,8 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( // If P is a reference type [...] // If P is a cv-qualified type [...] if (AdjustFunctionParmAndArgTypesForDeduction( - S, TemplateParams, FirstInnerIndex, ParamType, ArgType, IsLValue, Arg, - TDF, FailedTSC)) + S, TemplateParams, FirstInnerIndex, ParamType, ArgType, + ArgClassification, Arg, TDF, FailedTSC)) return Sema::TDK_Success; // If [...] the argument is a non-empty initializer list [...] @@ -4095,22 +4089,6 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( ArgType, Info, Deduced, TDF); } -static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( - Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType ParamType, QualType ArgType, - Expr::Classification ArgClassification, Expr *Arg, - TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, - bool DecomposedParam, unsigned ArgIdx, unsigned TDF, - TemplateSpecCandidateSet *FailedTSC) { - - return DeduceTemplateArgumentsFromCallArgument( - S, TemplateParams, FirstInnerIndex, ParamType, ArgType, - ArgClassification.isLValue(), Arg, Info, Deduced, OriginalCallArgs, - DecomposedParam, ArgIdx, TDF, FailedTSC); -} - /// Perform template argument deduction from a function call /// (C++ [temp.deduct.call]). /// @@ -4222,8 +4200,9 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // ... with the type of the corresponding argument return DeduceTemplateArgumentsFromCallArgument( *this, TemplateParams, FirstInnerIndex, ParamType, - Args[ArgIdx]->getType(), Args[ArgIdx]->isLValue(), Args[ArgIdx], Info, - Deduced, OriginalCallArgs, /*Decomposed*/ false, ArgIdx, /*TDF*/ 0); + Args[ArgIdx]->getType(), Args[ArgIdx]->Classify(getASTContext()), + Args[ArgIdx], Info, Deduced, OriginalCallArgs, /*Decomposed*/ false, + ArgIdx, /*TDF*/ 0); }; // Deduce template arguments from the function parameters. @@ -4925,8 +4904,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, return TDK_Invalid; if (auto TDK = DeduceTemplateArgumentsFromCallArgument( *this, TemplateParamsSt.get(), 0, TemplArg, Init->getType(), - Init->isLValue(), Init, Info, Deduced, OriginalCallArgs, - /*Decomposed=*/true, + Init->Classify(getASTContext()), Init, Info, Deduced, + OriginalCallArgs, /*Decomposed=*/true, /*ArgIdx=*/0, /*TDF=*/0)) { if (TDK == TDK_Inconsistent) { Diag(Info.getLocation(), diag::err_auto_inconsistent_deduction) @@ -4952,8 +4931,9 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, "substituting template parameter for 'auto' failed"); if (auto TDK = DeduceTemplateArgumentsFromCallArgument( *this, TemplateParamsSt.get(), 0, FuncParam, Init->getType(), - Init->isLValue(), Init, Info, Deduced, OriginalCallArgs, - /*Decomposed=*/false, /*ArgIdx=*/0, /*TDF=*/0, FailedTSC)) + Init->Classify(getASTContext()), Init, Info, Deduced, + OriginalCallArgs, /*Decomposed=*/false, /*ArgIdx=*/0, /*TDF=*/0, + FailedTSC)) return DeductionFailed(TDK); } >From 1211e2dffda7c6295e03b4db01086dd933195a5a Mon Sep 17 00:00:00 2001 From: cor3ntin <corentinja...@gmail.com> Date: Tue, 3 Oct 2023 19:38:04 +0200 Subject: [PATCH 3/3] Update clang/lib/AST/Expr.cpp Co-authored-by: Aaron Ballman <aa...@aaronballman.com> --- clang/lib/AST/Expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index e66dd532ce7488d..4bfc4f082cd6a69 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1623,7 +1623,7 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { assert(!CalleeType.isNull()); } else if (CalleeType->isRecordType()) { // If the Callee is a record type, then it is a not-yet-resolved - // dependent call to call operator of that type. + // dependent call to the call operator of that type. return Ctx.DependentTy; } else if (CalleeType->isDependentType() || CalleeType->isSpecificPlaceholderType(BuiltinType::Overload)) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits