Unverified Commit 9f3e3405 authored by Congcong Cai's avatar Congcong Cai Committed by GitHub
Browse files

[clang]Transform uninstantiated ExceptionSpec in TemplateInstantiator (#68878)

Fixes #68543, #42496
parent 7c651a1f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -474,6 +474,10 @@ Bug Fixes in This Version
  cannot be used with ``Release`` mode builds. (`#68237 <https://github.com/llvm/llvm-project/issues/68237>`_).
- Fix crash in evaluating ``constexpr`` value for invalid template function.
  Fixes (`#68542 <https://github.com/llvm/llvm-project/issues/68542>`_)
- 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>`_)
- 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.
+8 −1
Original line number Diff line number Diff line
@@ -3367,7 +3367,14 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments(
    SmallVector<QualType, 4> ExceptionStorage;
    if (getLangOpts().CPlusPlus17 &&
        SubstExceptionSpec(Function->getLocation(), EPI.ExceptionSpec,
                           ExceptionStorage, MLTAL))
                           ExceptionStorage,
                           getTemplateInstantiationArgs(
                               FunctionTemplate, nullptr, /*Final=*/true,
                               /*Innermost=*/SugaredExplicitArgumentList,
                               /*RelativeToPrimary=*/false,
                               /*Pattern=*/nullptr,
                               /*ForConstraintInstantiation=*/false,
                               /*SkipForSpecialization=*/true)))
      return TDK_SubstitutionFailure;

    *FunctionType = BuildFunctionType(ResultType, ParamTypes,
+17 −2
Original line number Diff line number Diff line
@@ -1335,6 +1335,11 @@ namespace {
    /// declaration.
    NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);

    bool TransformExceptionSpec(SourceLocation Loc,
                                FunctionProtoType::ExceptionSpecInfo &ESI,
                                SmallVectorImpl<QualType> &Exceptions,
                                bool &Changed);

    /// Rebuild the exception declaration and register the declaration
    /// as an instantiated local.
    VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
@@ -1617,6 +1622,18 @@ Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
  return Inst;
}

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;
    Changed = true;
  }
  return inherited::TransformExceptionSpec(Loc, ESI, Exceptions, Changed);
}

NamedDecl *
TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
                                                     SourceLocation Loc) {
@@ -2684,8 +2701,6 @@ bool Sema::SubstExceptionSpec(SourceLocation Loc,
                              FunctionProtoType::ExceptionSpecInfo &ESI,
                              SmallVectorImpl<QualType> &ExceptionStorage,
                              const MultiLevelTemplateArgumentList &Args) {
  assert(ESI.Type != EST_Uninstantiated);

  bool Changed = false;
  TemplateInstantiator Instantiator(*this, Args, Loc, DeclarationName());
  return Instantiator.TransformExceptionSpec(Loc, ESI, ExceptionStorage,
+11 −0
Original line number Diff line number Diff line
// RUN: %clang_cc1 -fsyntax-only -std=c++17 %s
// expected-no-diagnostics

using A = int;
using B = char;

template <class T> struct C {
  template <class V> void f0() noexcept(sizeof(T) == sizeof(A) && sizeof(V) == sizeof(B)) {}
};

void (C<int>::*tmp1)() noexcept = &C<A>::f0<B>;