[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From 11ceaed39b3f0c60c5a44c3b3a2b5856e7ee9a8d Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/7] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc28bb567f6932a..d9980694de40f6f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 91a4211a5cf5cce..daed24be0a86d11 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik edited https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik approved this pull request.

I just want to make sure we have enough testing in place for this change but 
overall I think I am happy.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Shafik Yaghmour via cfe-commits


@@ -3553,6 +3553,48 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`,
+// we'll try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred(
+Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList &SubstArgs,
+TemplateDeductionInfo &Info, FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *ExplicitExpr = ES.getExpr();
+  if (!ExplicitExpr)
+return Sema::TDK_Success;
+  if (!ExplicitExpr->isValueDependent())
+return Sema::TDK_Success;
+
+  Sema::InstantiatingTemplate Inst(
+  S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+  Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+  if (Inst.isInvalid())
+return Sema::TDK_InstantiationDepth;
+  Sema::SFINAETrap Trap(S);
+  const ExplicitSpecifier InstantiatedES =
+  S.instantiateExplicitSpecifier(SubstArgs, ES);
+  if (InstantiatedES.isInvalid() || Trap.hasErrorOccurred()) {

shafik wrote:

Do we have a test that checks this case at all? Same for the other failures, if 
we know how to test them we should write a test to verify them.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits

https://github.com/erichkeane approved this pull request.


https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From b62beb7553f098488e64c81995558c19cd36d785 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/7] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc28bb567f6932a..d9980694de40f6f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 91a4211a5cf5cce..daed24be0a86d11 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,47 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`,
+// we'll try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred(
+Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList &SubstArgs,
+TemplateDeductionInfo &Info, FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr)
+return Sema::TDK_Success;
+  if (!Expr->isValueDependent())
+return Sema::TDK_Success;
+
+  Sema::InstantiatingTemplate Inst(
+  S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+  Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+  if (Inst.isInvalid())
+return Sema::TDK_InstantiationDepth;
+  Sema::SFINAETrap Trap(S);
+  const auto Instantiated = S.instantiateExplicitSpecifier(SubstArgs, ES);

erichkeane wrote:

I think this is a case where we don't permit `auto`, though this is an argument 
that has happened before.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

LYP951018 wrote:

ok :)

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits

https://github.com/erichkeane edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits

https://github.com/erichkeane commented:

Did a better run-through again, so these are all thats left for me.  Thanks for 
the patience!

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,47 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`,
+// we'll try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred(
+Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList &SubstArgs,
+TemplateDeductionInfo &Info, FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr)

erichkeane wrote:

perhaps value in combining these two `if` statements, don't feel strongly 
though.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,47 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`,
+// we'll try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred(
+Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList &SubstArgs,
+TemplateDeductionInfo &Info, FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();

erichkeane wrote:

```suggestion
  Expr *SpecifierExpr = ES.getExpr();
```

We don't typically use const-pointers in clang, particularly for local 
variables.  Also, a better name would be appreciated.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits


@@ -3580,16 +3580,12 @@ static Sema::TemplateDeductionResult 
instantiateExplicitSpecifierDeferred(
   if (!Expr->isValueDependent()) {
 return Sema::TDK_Success;
   }
-  // The `InstantiatingTemplate` here is used to restore `ActiveInstType` to
-  // `DeducedTemplateArgumentSubstitution` because ActiveInstType was set to
-  // `TemplateInstantiation` in
-  // `TemplateDeclInstantiator::InitFunctionInstantiation`. The real depth of
-  // instantiation should be the same as the depth in
-  // `FinishTemplateArgumentDeduction`.
-  // So we don't check `InstantiatingTemplate::IsValid` here.
   Sema::InstantiatingTemplate Inst(
   S, Info.getLocation(), FunctionTemplate, DeducedArgs,
   Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+  if (Inst.isInvalid()) {

LYP951018 wrote:

Thanks for catching this! I’m still adapting to the LLVM coding style :(
I've fixed all similar cases.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From b62beb7553f098488e64c81995558c19cd36d785 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/6] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc28bb567f6932a..d9980694de40f6f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 91a4211a5cf5cce..daed24be0a86d11 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From b62beb7553f098488e64c81995558c19cd36d785 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/5] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc28bb567f6932a..d9980694de40f6f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 91a4211a5cf5cce..daed24be0a86d11 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits


@@ -3580,16 +3580,12 @@ static Sema::TemplateDeductionResult 
instantiateExplicitSpecifierDeferred(
   if (!Expr->isValueDependent()) {
 return Sema::TDK_Success;
   }
-  // The `InstantiatingTemplate` here is used to restore `ActiveInstType` to
-  // `DeducedTemplateArgumentSubstitution` because ActiveInstType was set to
-  // `TemplateInstantiation` in
-  // `TemplateDeclInstantiator::InitFunctionInstantiation`. The real depth of
-  // instantiation should be the same as the depth in
-  // `FinishTemplateArgumentDeduction`.
-  // So we don't check `InstantiatingTemplate::IsValid` here.
   Sema::InstantiatingTemplate Inst(
   S, Info.getLocation(), FunctionTemplate, DeducedArgs,
   Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
+  if (Inst.isInvalid()) {

erichkeane wrote:

This is a single-line block, so per style guide, don't use curley braces.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From b62beb7553f098488e64c81995558c19cd36d785 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/5] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc28bb567f6932a..d9980694de40f6f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 91a4211a5cf5cce..daed24be0a86d11 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

erichkeane wrote:

Right, there is quite a bit that it checks, so we  ALWAYS check it (or at least 
should).

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

LYP951018 wrote:

The instantiation depth in `instantiateExplicitSpecifierDeferred` is the depth 
in `FinishTemplateArgumentDeduction` plus one, but I think, actually, their 
depths should be equal ... If the depth in `FinishTemplateArgumentDeduction` is 
valid, the depth in `instantiateExplicitSpecifierDeferred` should be valid, 
too. So, I didn't check `IsValid`: If I check it, the available depth will be 
subtracted by one

But it seems that `IsValid` not only check the instantiation depth ... :(

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

erichkeane wrote:

Sorry, why do not have to check `Inst.isInvalid`?  We do it everywhere, and it 
is a good 'catch' for mistakes.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From b62beb7553f098488e64c81995558c19cd36d785 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/4] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc28bb567f6932a..d9980694de40f6f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 91a4211a5cf5cce..daed24be0a86d11 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

LYP951018 wrote:

> So we don't have to check Inst.isInvalid()?

comments added

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From a5929ddc33057416cee75d91f13a1252f4357524 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/4] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2595737e8b3b143..203111b829bd0c6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e9752345ffd173..93fd6507db3d78a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 39b939555f959b93061b3c4c8fffc13a63737074 
991212294aefaff304610213baaee927634a6c55 -- 
clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp 
clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaTemplateDeduction.cpp 
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index a1f43e213f81..76f3c1f19fc4 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3556,8 +3556,7 @@ static unsigned getPackIndexForParam(Sema &S,
 // if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`,
 // we'll try to instantiate and update its explicit specifier after constraint
 // checking.
-static Sema::TemplateDeductionResult
-instantiateExplicitSpecifierDeferred(
+static Sema::TemplateDeductionResult instantiateExplicitSpecifierDeferred(
 Sema &S, FunctionDecl *Specialization,
 const MultiLevelTemplateArgumentList &SubstArgs,
 TemplateDeductionInfo &Info, FunctionTemplateDecl *FunctionTemplate,

``




https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From a5929ddc33057416cee75d91f13a1252f4357524 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/4] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2595737e8b3b143..203111b829bd0c6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e9752345ffd173..93fd6507db3d78a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

LYP951018 wrote:

Thanks for your reminder! I've added the `hasErrorOccurred` check.
Also I renamed the function because I found a function named 
`tryResolveExplicitSpecifier` and I want to make them distinct.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From a5929ddc33057416cee75d91f13a1252f4357524 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/4] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2595737e8b3b143..203111b829bd0c6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e9752345ffd173..93fd6507db3d78a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

erichkeane wrote:

And yet, as soon as I said that, I remembered:  a `RecoveryExpr` (or other 
attempts at error recovery) can result in an error happening, but a valid 
expression being returned.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

erichkeane wrote:

I would suggest checking both?  But I cannot come up with a reason why just the 
ExprResult's validity wouldn't be sufficient.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-31 Thread via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

LYP951018 wrote:

I'm a bit confused here. Do I need to check `SFINAETrap::hasErrorOccurred`? Is 
`ExprResult::IsValid` enough?

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

LYP951018 wrote:

Thanks for reminding :)
I think you are right,`SFINAETrap` seems do the trick here. I'll take a deeper 
look at this.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread Younan Zhang via cfe-commits

https://github.com/zyn0217 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread Younan Zhang via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

zyn0217 wrote:

> the InstantiatingTemplate here is only used to enable SFINAE...

I'm wondering if 
[`SFINAETrap`](https://github.com/llvm/llvm-project/blob/e6971e5a41fe30264af9a13c8f387c06f93c6d9c/clang/include/clang/Sema/Sema.h#L10006-L10007)
 does the trick for you.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits

https://github.com/LYP951018 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread Shafik Yaghmour via cfe-commits


@@ -3682,6 +3725,17 @@ Sema::TemplateDeductionResult 
Sema::FinishTemplateArgumentDeduction(
 }
   }
 
+  // We skipped the instantiation of the explicit-specifier during subst the

shafik wrote:

This sentence is not super clear, can we spell out `subst` and `FD` as well.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread Shafik Yaghmour via cfe-commits


@@ -3553,6 +3553,49 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+resolveExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef DeducedArgs) {
+  auto GetExplicitSpecifier = [](FunctionDecl *D) {
+return isa(D)
+   ? cast(D)->getExplicitSpecifier()
+   : cast(D)->getExplicitSpecifier();
+  };
+  auto SetExplicitSpecifier = [](FunctionDecl *D, ExplicitSpecifier ES) {
+isa(D)
+? cast(D)->setExplicitSpecifier(ES)
+: cast(D)->setExplicitSpecifier(ES);
+  };
+
+  ExplicitSpecifier ES = GetExplicitSpecifier(Specialization);
+  Expr *const Expr = ES.getExpr();
+  if (!Expr) {
+return Sema::TDK_Success;
+  }
+  if (!Expr->isValueDependent()) {
+return Sema::TDK_Success;
+  }
+  // TemplateDeclInstantiator::InitFunctionInstantiation set the
+  // ActiveInstType to TemplateInstantiation, but we need
+  // to enable SFINAE when instantiating an explicit specifier.
+  Sema::InstantiatingTemplate Inst(

shafik wrote:

So we don't have to check `Inst.isInvalid()`?

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread Erich Keane via cfe-commits

https://github.com/erichkeane approved this pull request.

This is fine to me, please give other reviewers another day to take a look 
before merging though.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From a5929ddc33057416cee75d91f13a1252f4357524 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/3] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2595737e8b3b143..203111b829bd0c6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e9752345ffd173..93fd6507db3d78a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,

LYP951018 wrote:

Since this function isn't reused, I prefer to leave it `static` :)

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits

https://github.com/LYP951018 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;

LYP951018 wrote:

I've refactored the code here. If `Specialization` is not either constructor or 
conversion function, `cast` will `assert`.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.

LYP951018 wrote:

I've added `an`.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {

LYP951018 wrote:

Thanks for the advice, I’ve refactored the code. ;)

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits

https://github.com/LYP951018 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From a5929ddc33057416cee75d91f13a1252f4357524 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH 1/2] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2595737e8b3b143..203111b829bd0c6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e9752345ffd173..93fd6507db3d78a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template spec

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {

erichkeane wrote:

Ah, I missed that. Hmm... Perhaps keep it inline and just extract the calls to 
the two functions (get and set ExplicitSpecifier) into their own little 
functions that 'do the right thing'.  So:

```
 auto getExplicitSpecifier(FunctionDecl *FD) {
   return isa(FD) ? 
cast(FD)->getExplicitSpecifier() : 
cast(FD)->getExplicitSpecifier;
}
```


https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits

https://github.com/LYP951018 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.

LYP951018 wrote:

Should the `set` here be past tense or present tense here? 
`TemplateDeclInstantiator::InitFunctionInstantiation` is called before this 
function and I think it should be past tense... I'm not good at English :(

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {

LYP951018 wrote:

Thanks for reviewing ;)
Sadly, the type itself is required, because I need to call 
`CXXConversionDecl/CXXConstructorDecl::getExplicitSpecifier`/`setExplicitSpecifier`
 to get or set the explicit specifier.
I could not think of a better way to handle this without a template... 
If I put the function into `Sema` as a member function, I need to put two 
functions (one of them is the templated function) to `Sema`. Is that ok?

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {

erichkeane wrote:

Side note, it is now supposed to be `dyn_cast_if_present`, but yes, we don't 
seem to wish to support this in the `nullptr` case, so just `dyn_cast` is 
sufficient.

That said, the type itself isn't really used, right?  Rather than do the 
lambda/etc, it seems we should  just do:

```
if (isa(Specialization)) {
  
 }
```

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-30 Thread Erich Keane via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {

erichkeane wrote:

This lambda is sufficiently large I think it needs to be its own static 
function. Please make it no longer a lambda.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-29 Thread Younan Zhang via cfe-commits

https://github.com/zyn0217 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-29 Thread Younan Zhang via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;

zyn0217 wrote:

Rather than returning `clang::Sema::TDK_Success` silently, shall we add an 
assertion that the `Specialization` is either a constructor or a conversion 
function?

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-29 Thread Younan Zhang via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {

zyn0217 wrote:

nit: use `dyn_cast` since we have ensured that `Specialization` is non-null at 
the caller site `FinishTemplateArgumentDeduction`.

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-29 Thread Younan Zhang via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.

zyn0217 wrote:

```suggestion
// TemplateDeclInstantiator::InitFunctionInstantiation sets the
// ActiveInstType to TemplateInstantiation, but we need
// to enable SFINAE when instantiating an explicit specifier.
```

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-29 Thread Younan Zhang via cfe-commits


@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,

zyn0217 wrote:

nit: Do you think we should make this function a (private) member of `Sema` 
instead of a static function?

https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-29 Thread Younan Zhang via cfe-commits

https://github.com/zyn0217 commented:

Thank you for working on this! Some nit comments, hope you don't mind.
(Also invited some clang folks to have a detailed look at this. :=)


https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-28 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From a5929ddc33057416cee75d91f13a1252f4357524 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 59 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2595737e8b3b143..203111b829bd0c6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e9752345ffd173..93fd6507db3d78a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..f06332770f51d1f 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+// TemplateDeclInstantiator::InitFunctionInstantiation set the
+// ActiveInstType to TemplateInstantiation, but we need
+// to enable SFINAE when instantiating explicit specifier.
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template speciali

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-28 Thread via cfe-commits

https://github.com/LYP951018 updated 
https://github.com/llvm/llvm-project/pull/70548

From 4f8111b58324d5b670311717d36654f64e6dac01 Mon Sep 17 00:00:00 2001
From: letrec 
Date: Sat, 28 Oct 2023 18:05:36 +0800
Subject: [PATCH] Defer the instantiation of explicit-specifier after
 constraint checking

---
 clang/docs/ReleaseNotes.rst   |  4 ++
 clang/include/clang/Sema/Sema.h   |  3 +
 clang/lib/Sema/SemaTemplateDeduction.cpp  | 56 +++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 40 -
 .../SemaCXX/cxx2a-explicit-bool-deferred.cpp  | 31 ++
 5 files changed, 120 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2a-explicit-bool-deferred.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2595737e8b3b143..203111b829bd0c6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -670,6 +670,10 @@ Bug Fixes to C++ Support
   default initializing a base class in a constant expression context. Fixes:
   (`#69890 `_)
 
+- Clang now defers the instantiation of explicit specifier until constraint 
checking
+  completes (except deduction guides). Fixes:
+  (`#59827 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e9752345ffd173..93fd6507db3d78a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10430,6 +10430,9 @@ class Sema final {
   const CXXConstructorDecl *Tmpl,
 const MultiLevelTemplateArgumentList 
&TemplateArgs);
 
+  ExplicitSpecifier instantiateExplicitSpecifier(
+  const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier 
ES);
+
   NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   const MultiLevelTemplateArgumentList &TemplateArgs,
   bool FindingInstantiatedContext = false);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0b3f0247ea3bee3..e75e46aa5228812 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3553,6 +3553,53 @@ static unsigned getPackIndexForParam(Sema &S,
   llvm_unreachable("parameter index would not be produced from template");
 }
 
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+const MultiLevelTemplateArgumentList 
&SubstArgs,
+TemplateDeductionInfo &Info,
+FunctionTemplateDecl *FunctionTemplate,
+ArrayRef DeducedArgs) {
+
+  const auto TryInstantiateExplicitSpecifierForSingleDecl =
+  [&](auto *ExplicitDecl) {
+ExplicitSpecifier ExplicitSpecifier =
+ExplicitDecl->getExplicitSpecifier();
+Expr *const Expr = ExplicitSpecifier.getExpr();
+if (!Expr) {
+  return Sema::TDK_Success;
+}
+if (!Expr->isValueDependent()) {
+  return Sema::TDK_Success;
+}
+Sema::InstantiatingTemplate Inst(
+S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+Info);
+const auto Instantiated =
+S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+if (Instantiated.isInvalid()) {
+  ExplicitDecl->setInvalidDecl(true);
+  return clang::Sema::TDK_SubstitutionFailure;
+}
+ExplicitDecl->setExplicitSpecifier(Instantiated);
+return clang::Sema::TDK_Success;
+  };
+  Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+  if (CXXConstructorDecl *ConstructorDecl =
+  dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+  } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null(Specialization)) {
+DeductionResult =
+TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+  }
+  return DeductionResult;
+}
+
 /// Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template specialization.
@@ -3682,6 +3729,15 @@ Sema::TemplateDeductionResult 
Sema::FinishTemplateArgumentDeduction(
 }
   }
 
+  // We skipped the instantiation of the explicit-specifier during subst the
+  // decl b

[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)

2023-10-28 Thread via cfe-commits

https://github.com/LYP951018 edited 
https://github.com/llvm/llvm-project/pull/70548
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits