[clang] [clang]Transform uninstantiated ExceptionSpec in `TemplateInstantiator` (PR #77073)

Congcong Cai via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 5 02:16:15 PST 2024


https://github.com/HerrCai0907 created https://github.com/llvm/llvm-project/pull/77073

Fixes: #77071
`SubstituteDeducedTypeTransform` will transform type and it will visit uninstantiated `ExceptionSpecInfo`, which will cause odd behavior

>From 04ef8fd566491024c8163ad3b901f8c4cebaf890 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Fri, 5 Jan 2024 18:15:24 +0800
Subject: [PATCH] [clang]Transform uninstantiated ExceptionSpec in
 TemplateInstantiator

Fixes: #77071
SubstituteDeducedTypeTransform will transform type and it will visit uninstantiated ExceptionSpecInfo which will odd behavior
---
 clang/docs/ReleaseNotes.rst                           |  3 ++-
 clang/include/clang/AST/Type.h                        |  2 ++
 clang/lib/AST/Type.cpp                                |  7 +++++++
 clang/lib/Sema/SemaTemplateDeduction.cpp              | 11 +++++++++++
 clang/lib/Sema/SemaTemplateInstantiate.cpp            |  4 +---
 .../SemaCXX/dependent-noexcept-uninstantiated.cpp     |  4 +++-
 6 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ee211c16a48ac8..f750587ad12271 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -607,7 +607,8 @@ Bug Fixes in This Version
 - Clang will correctly evaluate ``noexcept`` expression for template functions
   of template classes. Fixes
   (`#68543 <https://github.com/llvm/llvm-project/issues/68543>`_,
-  `#42496 <https://github.com/llvm/llvm-project/issues/42496>`_)
+  `#42496 <https://github.com/llvm/llvm-project/issues/42496>`_,
+  `#77071 <https://github.com/llvm/llvm-project/issues/77071>`_)
 - Fixed an issue when a shift count larger than ``__INT64_MAX__``, in a right
   shift operation, could result in missing warnings about
   ``shift count >= width of type`` or internal compiler error.
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index b3ae66e6e769d0..0fcf331dd79bc6 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -4228,6 +4228,8 @@ class FunctionProtoType final
     ExceptionSpecInfo() = default;
 
     ExceptionSpecInfo(ExceptionSpecificationType EST) : Type(EST) {}
+
+    void instantiate();
   };
 
   /// Extra information about a function prototype. ExtProtoInfo is not
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 160a725939ccd4..a894d3289eb185 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3414,6 +3414,13 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
   llvm_unreachable("Invalid calling convention.");
 }
 
+void FunctionProtoType::ExceptionSpecInfo::instantiate() {
+  assert(Type == EST_Uninstantiated);
+  NoexceptExpr =
+      cast<FunctionProtoType>(SourceTemplate->getType())->getNoexceptExpr();
+  Type = EST_DependentNoexcept;
+}
+
 FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
                                      QualType canonical,
                                      const ExtProtoInfo &epi)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 699e0985e595b6..015b0abaf0e5ee 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -4737,6 +4737,7 @@ namespace {
     QualType Replacement;
     bool ReplacementIsPack;
     bool UseTypeSugar;
+    using inherited = TreeTransform<SubstituteDeducedTypeTransform>;
 
   public:
     SubstituteDeducedTypeTransform(Sema &SemaRef, DependentAuto DA)
@@ -4797,6 +4798,16 @@ namespace {
       // Lambdas never need to be transformed.
       return E;
     }
+    bool TransformExceptionSpec(SourceLocation Loc,
+                                FunctionProtoType::ExceptionSpecInfo &ESI,
+                                SmallVectorImpl<QualType> &Exceptions,
+                                bool &Changed) {
+      if (ESI.Type == EST_Uninstantiated) {
+        ESI.instantiate();
+        Changed = true;
+      }
+      return inherited::TransformExceptionSpec(Loc, ESI, Exceptions, Changed);
+    }
 
     QualType Apply(TypeLoc TL) {
       // Create some scratch storage for the transformed type locations.
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index df6b40999e645c..2c452404459a5d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1630,9 +1630,7 @@ bool TemplateInstantiator::TransformExceptionSpec(
     SourceLocation Loc, FunctionProtoType::ExceptionSpecInfo &ESI,
     SmallVectorImpl<QualType> &Exceptions, bool &Changed) {
   if (ESI.Type == EST_Uninstantiated) {
-    ESI.NoexceptExpr = cast<FunctionProtoType>(ESI.SourceTemplate->getType())
-                           ->getNoexceptExpr();
-    ESI.Type = EST_DependentNoexcept;
+    ESI.instantiate();
     Changed = true;
   }
   return inherited::TransformExceptionSpec(Loc, ESI, Exceptions, Changed);
diff --git a/clang/test/SemaCXX/dependent-noexcept-uninstantiated.cpp b/clang/test/SemaCXX/dependent-noexcept-uninstantiated.cpp
index ddb26989022753..3821f18e7bf276 100644
--- a/clang/test/SemaCXX/dependent-noexcept-uninstantiated.cpp
+++ b/clang/test/SemaCXX/dependent-noexcept-uninstantiated.cpp
@@ -6,6 +6,8 @@ using B = char;
 
 template <class T> struct C {
   template <class V> void f0() noexcept(sizeof(T) == sizeof(A) && sizeof(V) == sizeof(B)) {}
+  template <class V> auto f1(V a) noexcept(1) {return a;}
 };
 
-void (C<int>::*tmp1)() noexcept = &C<A>::f0<B>;
+void (C<int>::*tmp0)() noexcept = &C<A>::f0<B>;
+int (C<int>::*tmp1)(int) noexcept = &C<A>::f1;



More information about the cfe-commits mailing list