Skip to content

Commit

Permalink
[clang] Mark ill-formed partial specialization as invalid (#89536)
Browse files Browse the repository at this point in the history
Fixes #89374
Solution suggested by @cor3ntin
  • Loading branch information
Endilll committed Apr 24, 2024
1 parent 6493da7 commit 805d563
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 0 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,9 @@ Bug Fixes in This Version
operator.
Fixes (#GH83267).

- Fix crash on ill-formed partial specialization with CRTP.
Fixes (#GH89374).

- Clang now correctly generates overloads for bit-precise integer types for
builtin operators in C++. Fixes #GH82998.

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9460,6 +9460,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< ClassTemplate->getDeclName();
isPartialSpecialization = false;
Invalid = true;
}
}

Expand Down Expand Up @@ -9675,6 +9676,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
if (SkipBody && SkipBody->ShouldSkip)
return SkipBody->Previous;

Specialization->setInvalidDecl(Invalid);
return Specialization;
}

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1914,6 +1914,9 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
if (!S.isCompleteType(Info.getLocation(), A))
return Result;

if (getCanonicalRD(A)->isInvalidDecl())
return Result;

// Reset the incorrectly deduced argument from above.
Deduced = DeducedOrig;

Expand Down
28 changes: 28 additions & 0 deletions clang/test/SemaCXX/template-specialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,31 @@ void instantiate() {
}

}

namespace GH89374 {

struct A {};

template <typename Derived>
struct MatrixBase { // #GH89374-MatrixBase
template <typename OtherDerived>
Derived &operator=(const MatrixBase<OtherDerived> &); // #GH89374-copy-assignment
};

template <typename>
struct solve_retval;

template <typename Rhs>
struct solve_retval<int> : MatrixBase<solve_retval<Rhs> > {};
// expected-error@-1 {{partial specialization of 'solve_retval' does not use any of its template parameters}}

void ApproximateChebyshev() {
MatrixBase<int> c;
c = solve_retval<int>();
// expected-error@-1 {{no viable overloaded '='}}
// expected-note@#GH89374-copy-assignment {{candidate template ignored: could not match 'MatrixBase' against 'solve_retval'}}
// expected-note@#GH89374-MatrixBase {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'solve_retval<int>' to 'const MatrixBase<int>' for 1st argument}}
// expected-note@#GH89374-MatrixBase {{candidate function (the implicit move assignment operator) not viable: no known conversion from 'solve_retval<int>' to 'MatrixBase<int>' for 1st argument}}
}

} // namespace GH89374

0 comments on commit 805d563

Please sign in to comment.