@@ -1344,15 +1344,21 @@ namespace {
13441344 DeclarationName Entity;
13451345 // Whether to evaluate the C++20 constraints or simply substitute into them.
13461346 bool EvaluateConstraints = true ;
1347+ // Whether Substitution was Incomplete, that is, we tried to substitute in
1348+ // any user provided template arguments which were null.
1349+ bool IsIncomplete = false ;
1350+ // Whether an incomplete substituion should be treated as an error.
1351+ bool BailOutOnIncomplete;
13471352
13481353 public:
13491354 typedef TreeTransform<TemplateInstantiator> inherited;
13501355
13511356 TemplateInstantiator (Sema &SemaRef,
13521357 const MultiLevelTemplateArgumentList &TemplateArgs,
1353- SourceLocation Loc, DeclarationName Entity)
1358+ SourceLocation Loc, DeclarationName Entity,
1359+ bool BailOutOnIncomplete = false )
13541360 : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
1355- Entity (Entity) {}
1361+ Entity (Entity), BailOutOnIncomplete(BailOutOnIncomplete) {}
13561362
13571363 void setEvaluateConstraints (bool B) {
13581364 EvaluateConstraints = B;
@@ -1374,6 +1380,9 @@ namespace {
13741380 // / Returns the name of the entity being instantiated, if any.
13751381 DeclarationName getBaseEntity () { return Entity; }
13761382
1383+ // / Returns whether any substitution so far was incomplete.
1384+ bool getIsIncomplete () const { return IsIncomplete; }
1385+
13771386 // / Sets the "base" location and entity when that
13781387 // / information is known based on another transformation.
13791388 void setBase (SourceLocation Loc, DeclarationName Entity) {
@@ -1420,6 +1429,10 @@ namespace {
14201429 if (TemplateArgs.hasTemplateArgument (Depth, Index)) {
14211430 Result = TemplateArgs (Depth, Index);
14221431 TemplateArgs.setArgument (Depth, Index, TemplateArgument ());
1432+ } else {
1433+ IsIncomplete = true ;
1434+ if (BailOutOnIncomplete)
1435+ return TemplateArgument ();
14231436 }
14241437 }
14251438
@@ -1820,8 +1833,10 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
18201833 // template arguments in a function template, but there were some
18211834 // arguments left unspecified.
18221835 if (!TemplateArgs.hasTemplateArgument (TTP->getDepth (),
1823- TTP->getPosition ()))
1824- return D;
1836+ TTP->getPosition ())) {
1837+ IsIncomplete = true ;
1838+ return BailOutOnIncomplete ? nullptr : D;
1839+ }
18251840
18261841 TemplateArgument Arg = TemplateArgs (TTP->getDepth (), TTP->getPosition ());
18271842
@@ -1967,8 +1982,10 @@ TemplateName TemplateInstantiator::TransformTemplateName(
19671982 // template arguments in a function template, but there were some
19681983 // arguments left unspecified.
19691984 if (!TemplateArgs.hasTemplateArgument (TTP->getDepth (),
1970- TTP->getPosition ()))
1971- return Name;
1985+ TTP->getPosition ())) {
1986+ IsIncomplete = true ;
1987+ return BailOutOnIncomplete ? TemplateName () : Name;
1988+ }
19721989
19731990 TemplateArgument Arg = TemplateArgs (TTP->getDepth (), TTP->getPosition ());
19741991
@@ -2050,8 +2067,10 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
20502067 // template arguments in a function template, but there were some
20512068 // arguments left unspecified.
20522069 if (!TemplateArgs.hasTemplateArgument (NTTP->getDepth (),
2053- NTTP->getPosition ()))
2054- return E;
2070+ NTTP->getPosition ())) {
2071+ IsIncomplete = true ;
2072+ return BailOutOnIncomplete ? ExprError () : E;
2073+ }
20552074
20562075 TemplateArgument Arg = TemplateArgs (NTTP->getDepth (), NTTP->getPosition ());
20572076
@@ -2470,6 +2489,10 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
24702489 // template arguments in a function template class, but there were some
24712490 // arguments left unspecified.
24722491 if (!TemplateArgs.hasTemplateArgument (T->getDepth (), T->getIndex ())) {
2492+ IsIncomplete = true ;
2493+ if (BailOutOnIncomplete)
2494+ return QualType ();
2495+
24732496 TemplateTypeParmTypeLoc NewTL
24742497 = TLB.push <TemplateTypeParmTypeLoc>(TL.getType ());
24752498 NewTL.setNameLoc (TL.getNameLoc ());
@@ -2841,7 +2864,8 @@ TypeSourceInfo *Sema::SubstType(TypeLoc TL,
28412864// / Deprecated form of the above.
28422865QualType Sema::SubstType (QualType T,
28432866 const MultiLevelTemplateArgumentList &TemplateArgs,
2844- SourceLocation Loc, DeclarationName Entity) {
2867+ SourceLocation Loc, DeclarationName Entity,
2868+ bool *IsIncompleteSubstitution) {
28452869 assert (!CodeSynthesisContexts.empty () &&
28462870 " Cannot perform an instantiation without some context on the "
28472871 " instantiation stack" );
@@ -2851,8 +2875,13 @@ QualType Sema::SubstType(QualType T,
28512875 if (!T->isInstantiationDependentType () && !T->isVariablyModifiedType ())
28522876 return T;
28532877
2854- TemplateInstantiator Instantiator (*this , TemplateArgs, Loc, Entity);
2855- return Instantiator.TransformType (T);
2878+ TemplateInstantiator Instantiator (
2879+ *this , TemplateArgs, Loc, Entity,
2880+ /* BailOutOnIncomplete=*/ IsIncompleteSubstitution != nullptr );
2881+ QualType QT = Instantiator.TransformType (T);
2882+ if (IsIncompleteSubstitution && Instantiator.getIsIncomplete ())
2883+ *IsIncompleteSubstitution = true ;
2884+ return QT;
28562885}
28572886
28582887static bool NeedsInstantiationAsFunctionType (TypeSourceInfo *T) {
0 commit comments