forked from OSchip/llvm-project
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. llvm-svn: 295016
This commit is contained in:
parent
b2bca7e309
commit
c27b3d7623
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -136,4 +136,17 @@ namespace look_into_current_instantiation {
|
|||
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};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue