[clang] [Clang] Do not try to classify dependant call expression (PR #68078)

via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 3 06:28:09 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/2] [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/2] 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);
     }
 



More information about the cfe-commits mailing list