r295016 - Canonicalize implicit deduction guide parameter types when forming a deduction
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 13 20:42:43 PST 2017
Hi Richard,
The following test triggers an assertion, even after this patch:
#include <memory>
#include <string>
template <class T>
struct TestAlloc : std::allocator<T> {};
template <class Char, class Traits = std::char_traits<Char>,
class Allocator = std::allocator<Char>>
struct String {
using size_type = typename Allocator::size_type;
String() = default;
String(const String&, size_type, size_type, const Allocator& =
Allocator()) {}
String(String const&, size_type, const Allocator& = Allocator()) {}
};
int main() {
using BStr = String<char>;
BStr bs;
String s(bs, 1ul, 1ul, std::allocator<char>{});
static_assert(std::is_same_v<decltype(s), BStr>);
}
On Mon, Feb 13, 2017 at 6:50 PM, Richard Smith via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: rsmith
> Date: Mon Feb 13 19:49:59 2017
> New Revision: 295016
>
> URL: http://llvm.org/viewvc/llvm-project?rev=295016&view=rev
> Log:
> Canonicalize implicit deduction guide parameter types when forming a
> deduction
> guide from a constructor.
>
> The purpose of this change is to avoid triggering instantiation of the
> class
> when substituting back into the deduction guide if it uses a typedef
> member.
> We will still instantiate the class if the constructor (explicitly or
> implicitly, directly or indirectly) uses the current instantiation in a way
> that we can't canonicalize out, but that seems unavoidable.
>
> Modified:
> cfe/trunk/lib/Sema/SemaTemplate.cpp
> cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaTemplate.cpp?rev=295016&r1=295015&r2=295016&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Feb 13 19:49:59 2017
> @@ -1585,12 +1585,7 @@ private:
>
> // -- The types of the function parameters are those of the
> constructor.
> for (auto *OldParam : TL.getParams()) {
> - // If we're transforming a non-template constructor, just reuse its
> - // parameters as the parameters of the deduction guide. Otherwise,
> we
> - // need to transform their references to constructor template
> parameters.
> - ParmVarDecl *NewParam = Args.getNumLevels()
> - ? transformFunctionTypeParam(OldParam,
> Args)
> - : OldParam;
> + ParmVarDecl *NewParam = transformFunctionTypeParam(OldParam, Args);
> if (!NewParam)
> return QualType();
> ParamTypes.push_back(NewParam->getType());
> @@ -1636,16 +1631,31 @@ private:
> transformFunctionTypeParam(ParmVarDecl *OldParam,
> MultiLevelTemplateArgumentList &Args) {
> TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo();
> - TypeSourceInfo *NewDI = SemaRef.SubstType(
> - OldDI, Args, OldParam->getLocation(), OldParam->getDeclName());
> + TypeSourceInfo *NewDI =
> + Args.getNumLevels()
> + ? SemaRef.SubstType(OldDI, Args, OldParam->getLocation(),
> + OldParam->getDeclName())
> + : OldDI;
> if (!NewDI)
> return nullptr;
>
> + // Canonicalize the type. This (for instance) replaces references to
> + // typedef members of the current instantiations with the definitions
> of
> + // those typedefs, avoiding triggering instantiation of the deduced
> type
> + // during deduction.
> + // FIXME: It would be preferable to retain type sugar and source
> + // information here (and handle this in substitution instead).
> + NewDI = SemaRef.Context.getTrivialTypeSourceInfo(
> + SemaRef.Context.getCanonicalType(NewDI->getType()),
> + OldParam->getLocation());
> +
> // Resolving a wording defect, we also inherit default arguments from
> the
> // constructor.
> ExprResult NewDefArg;
> if (OldParam->hasDefaultArg()) {
> - NewDefArg = SemaRef.SubstExpr(OldParam->getDefaultArg(), Args);
> + NewDefArg = Args.getNumLevels()
> + ? SemaRef.SubstExpr(OldParam->getDefaultArg(),
> Args)
> + : OldParam->getDefaultArg();
> if (NewDefArg.isInvalid())
> return nullptr;
> }
>
> Modified: cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-
> deduction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaCXX/cxx1z-class-template-argument-deduction.cpp?rev=
> 295016&r1=295015&r2=295016&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
> (original)
> +++ cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
> Mon Feb 13 19:49:59 2017
> @@ -136,4 +136,17 @@ namespace look_into_current_instantiatio
> B(typename X::type); // expected-note {{couldn't infer template
> argument 'T'}}
> };
> B b = 0; // expected-error {{no viable}}
> +
> + // We should have a substitution failure in the immediate context of
> + // deduction when using the C(T, U) constructor (probably; core wording
> + // unclear).
> + template<typename T> struct C {
> + using U = typename T::type;
> + C(T, U);
> + };
> +
> + struct R { R(int); typedef R type; };
> + C(...) -> C<R>;
> +
> + C c = {1, 2};
> }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170213/54ca2dd6/attachment.html>
More information about the cfe-commits
mailing list