[clang] [Clang] Correctly handle callees whose type is a Record type when classifying expressions (PR #68078)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 3 10:38:12 PDT 2023
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 <corentinjabot at 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 <corentinjabot at 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 <corentinjabot at 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 <aaron at 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)) {
More information about the cfe-commits
mailing list