[clang] 6170072 - Improve modeling of variable template specializations with dependent

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 11 00:50:05 PDT 2020


On Tue, 11 Aug 2020 at 00:29, Martin Storsjö <martin at martin.st> wrote:

> On Sun, 9 Aug 2020, Richard Smith via cfe-commits wrote:
>
> >
> > Author: Richard Smith
> > Date: 2020-08-09T23:22:26-07:00
> > New Revision: 617007240cbfb97c8ccf6d61b0c4ca0bb62d43c9
> >
> > URL:
> https://github.com/llvm/llvm-project/commit/617007240cbfb97c8ccf6d61b0c4ca0bb62d43c9
> > DIFF:
> https://github.com/llvm/llvm-project/commit/617007240cbfb97c8ccf6d61b0c4ca0bb62d43c9.diff
> >
> > LOG: Improve modeling of variable template specializations with dependent
> > arguments.
> >
> > Don't build a variable template specialization declaration until its
> > scope and template arguments are non-dependent.
> >
> > No functionality change intended, but the AST representation is now more
> > consistent with how we model other templates.
>
> This did turn out to make a functional change, breaking building the dev
> branch of Qt. A halfway reduced example below:
>

Thanks for reporting this! Reduced a bit more:

template<class _Tp, class _Arg>
inline constexpr bool is_nothrow_assignable_v = true;

template<class T> class QCache {
    void replace() noexcept(is_nothrow_assignable_v<T>);
};

We used to allow this and now reject. This code is ill-formed (no
diagnostic required) by [temp.res]/8, because it has no valid
instantiations, because the second template argument of
is_nothrow_assignable_v is missing.

So, assuming the case from which this was reduced was similarly ill-formed
(which it looks like it is:
https://github.com/qt/qtbase/blob/48c8322a613f58d19ad9e0262bbac437ce2598f8/src/corelib/tools/qcache.h#L114),
I think that's a (minor) quality of implementation improvement -- we now
diagnose a bug that we used to miss. ICC also rejects this, although GCC
does not, and all three compilers reject the corresponding case using a
class template instead of a variable template.


> template <class _Tp, _Tp __v>
> struct integral_constant
> {
>    static constexpr const _Tp value = __v;
>    typedef _Tp value_type;
>    typedef integral_constant type;
>    __attribute__ ((__exclude_from_explicit_instantiation__))
>    constexpr operator value_type() const noexcept {return value;}
>
>    __attribute__ ((__exclude_from_explicit_instantiation__))
>    constexpr value_type operator ()() const noexcept {return value;}
> };
>
>
> template <class _Tp, class _Arg>
> struct is_nothrow_assignable
>      : public integral_constant<bool, __is_nothrow_assignable(_Tp, _Arg)>
> {};
> template <class _Tp, class _Arg>
> inline constexpr bool is_nothrow_assignable_v
>      = is_nothrow_assignable<_Tp, _Arg>::value;
>
>
> template <class T>
> class QCache
> {
>      struct Value {
>          T *t = nullptr;
>      };
>
>      struct Node {
>          Value value;
>
>          void replace(const Value &t) noexcept(is_nothrow_assignable_v<T>)
> {
>              value = t;
>          }
>      };
>
> };
>
>
>
> // Martin
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200811/e13fd748/attachment.html>


More information about the cfe-commits mailing list