summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCongcong Cai <congcongcai0907@163.com>2024-01-05 23:37:58 +0800
committerGitHub <noreply@github.com>2024-01-05 23:37:58 +0800
commitde5039545ee4e9f5aa7023632d5c4baa5e782e51 (patch)
tree9434b2f8718bc7b7d6bac6f828507557dc4b1859
parent922b7b8bf465ddc292fa91bd6a860510a1eea6e2 (diff)
[clang]Transform uninstantiated ExceptionSpec in `TemplateInstantiator` (#77073)
Fixes: #77071 `SubstituteDeducedTypeTransform` will transform type and it will visit uninstantiated `ExceptionSpecInfo`, which will cause odd behavior.
-rw-r--r--clang/docs/ReleaseNotes.rst3
-rw-r--r--clang/include/clang/AST/Type.h2
-rw-r--r--clang/lib/AST/Type.cpp7
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp11
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp4
-rw-r--r--clang/test/SemaCXX/dependent-noexcept-uninstantiated.cpp4
6 files changed, 26 insertions, 5 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f5159cdc8a3b..9b6e00b23121 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -609,7 +609,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 1afa69367286..9e9f896ebef7 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -4224,6 +4224,8 @@ public:
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 160a725939cc..a894d3289eb1 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 699e0985e595..015b0abaf0e5 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 27a4b68fd59a..09dd119ed1b9 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1639,9 +1639,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 ddb269890227..3821f18e7bf2 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;