Skip to content

Commit

Permalink
[clang] NFCI: use TemplateArgumentLoc for NTTP DefaultArgument (#92852)
Browse files Browse the repository at this point in the history
This is an enabler for #92855

This allows an NTTP default argument to be set as an arbitrary
TemplateArgument, not just an expression.
This allows template parameter packs to have default arguments in the
AST, even though the language proper doesn't support the syntax for it.

This allows NTTP default arguments to be other kinds of arguments, like
packs, integral constants, and such.
  • Loading branch information
mizvekov authored May 22, 2024
1 parent 30d484f commit 2bde13c
Show file tree
Hide file tree
Showing 25 changed files with 99 additions and 74 deletions.
3 changes: 2 additions & 1 deletion clang-tools-extra/clangd/Hover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ fetchTemplateParameters(const TemplateParameterList *Params,
if (NTTP->hasDefaultArgument()) {
P.Default.emplace();
llvm::raw_string_ostream Out(*P.Default);
NTTP->getDefaultArgument()->printPretty(Out, nullptr, PP);
NTTP->getDefaultArgument().getArgument().print(PP, Out,
/*IncludeType=*/false);
}
} else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
P.Type = printType(TTPD, PP);
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/AST/ASTNodeTraverser.h
Original file line number Diff line number Diff line change
Expand Up @@ -704,9 +704,9 @@ class ASTNodeTraverser
if (const auto *E = D->getPlaceholderTypeConstraint())
Visit(E);
if (D->hasDefaultArgument())
Visit(D->getDefaultArgument(), SourceRange(),
D->getDefaultArgStorage().getInheritedFrom(),
D->defaultArgumentWasInherited() ? "inherited from" : "previous");
dumpTemplateArgumentLoc(
D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(),
D->defaultArgumentWasInherited() ? "inherited from" : "previous");
}

void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) {
Expand Down
11 changes: 8 additions & 3 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -1360,7 +1360,8 @@ class NonTypeTemplateParmDecl final

/// The default template argument, if any, and whether or not
/// it was inherited.
using DefArgStorage = DefaultArgStorage<NonTypeTemplateParmDecl, Expr *>;
using DefArgStorage =
DefaultArgStorage<NonTypeTemplateParmDecl, TemplateArgumentLoc *>;
DefArgStorage DefaultArgument;

// FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
Expand Down Expand Up @@ -1430,7 +1431,10 @@ class NonTypeTemplateParmDecl final
bool hasDefaultArgument() const { return DefaultArgument.isSet(); }

/// Retrieve the default argument, if any.
Expr *getDefaultArgument() const { return DefaultArgument.get(); }
const TemplateArgumentLoc &getDefaultArgument() const {
static const TemplateArgumentLoc NoneLoc;
return DefaultArgument.isSet() ? *DefaultArgument.get() : NoneLoc;
}

/// Retrieve the location of the default argument, if any.
SourceLocation getDefaultArgumentLoc() const;
Expand All @@ -1444,7 +1448,8 @@ class NonTypeTemplateParmDecl final
/// Set the default argument for this template parameter, and
/// whether that default argument was inherited from another
/// declaration.
void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); }
void setDefaultArgument(const ASTContext &C,
const TemplateArgumentLoc &DefArg);
void setInheritedDefaultArgument(const ASTContext &C,
NonTypeTemplateParmDecl *Parm) {
DefaultArgument.setInherited(C, Parm);
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2320,7 +2320,7 @@ DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
// A non-type template parameter, e.g. "S" in template<int S> class Foo ...
TRY_TO(TraverseDeclaratorHelper(D));
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
TRY_TO(TraverseStmt(D->getDefaultArgument()));
TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
})

DEF_TRAVERSE_DECL(ParmVarDecl, {
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6503,8 +6503,10 @@ bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X,
if (!NTTPX->hasDefaultArgument() || !NTTPY->hasDefaultArgument())
return false;

Expr *DefaultArgumentX = NTTPX->getDefaultArgument()->IgnoreImpCasts();
Expr *DefaultArgumentY = NTTPY->getDefaultArgument()->IgnoreImpCasts();
Expr *DefaultArgumentX =
NTTPX->getDefaultArgument().getArgument().getAsExpr()->IgnoreImpCasts();
Expr *DefaultArgumentY =
NTTPY->getDefaultArgument().getArgument().getAsExpr()->IgnoreImpCasts();
llvm::FoldingSetNodeID XID, YID;
DefaultArgumentX->Profile(XID, *this, /*Canonical=*/true);
DefaultArgumentY->Profile(YID, *this, /*Canonical=*/true);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ASTDiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1238,7 +1238,7 @@ class TemplateDiff {
E = Iter->getAsExpr();
}
} else if (!Default->isParameterPack()) {
E = Default->getDefaultArgument();
E = Default->getDefaultArgument().getArgument().getAsExpr();
}

if (!Iter.hasDesugaredTA()) return;
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5949,10 +5949,11 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
return ToD;

if (D->hasDefaultArgument()) {
ExpectedExpr ToDefaultArgOrErr = import(D->getDefaultArgument());
Expected<TemplateArgumentLoc> ToDefaultArgOrErr =
import(D->getDefaultArgument());
if (!ToDefaultArgOrErr)
return ToDefaultArgOrErr.takeError();
ToD->setDefaultArgument(*ToDefaultArgOrErr);
ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr);
}

return ToD;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/DeclPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1898,7 +1898,7 @@ void DeclPrinter::VisitNonTypeTemplateParmDecl(

if (NTTP->hasDefaultArgument()) {
Out << " = ";
NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation,
"\n", &Context);
NTTP->getDefaultArgument().getArgument().print(Policy, Out,
/*IncludeType=*/false);
}
}
15 changes: 11 additions & 4 deletions clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -795,14 +795,21 @@ NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
if (hasDefaultArgument() && !defaultArgumentWasInherited())
return SourceRange(getOuterLocStart(),
getDefaultArgument()->getSourceRange().getEnd());
getDefaultArgument().getSourceRange().getEnd());
return DeclaratorDecl::getSourceRange();
}

SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
return hasDefaultArgument()
? getDefaultArgument()->getSourceRange().getBegin()
: SourceLocation();
return hasDefaultArgument() ? getDefaultArgument().getSourceRange().getBegin()
: SourceLocation();
}

void NonTypeTemplateParmDecl::setDefaultArgument(
const ASTContext &C, const TemplateArgumentLoc &DefArg) {
if (DefArg.getArgument().isNull())
DefaultArgument.set(nullptr);
else
DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
}

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/JSONNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ void JSONNodeDumper::VisitNonTypeTemplateParmDecl(

if (D->hasDefaultArgument())
JOS.attributeObject("defaultArg", [=] {
Visit(D->getDefaultArgument(), SourceRange(),
Visit(D->getDefaultArgument().getArgument(), SourceRange(),
D->getDefaultArgStorage().getInheritedFrom(),
D->defaultArgumentWasInherited() ? "inherited from" : "previous");
});
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/AST/ODRDiagsEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1523,8 +1523,11 @@ bool ODRDiagsEmitter::diagnoseMismatch(
}

if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument();
Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument();
TemplateArgument FirstDefaultArgument =
FirstNTTPD->getDefaultArgument().getArgument();
TemplateArgument SecondDefaultArgument =
SecondNTTPD->getDefaultArgument().getArgument();

if (computeODRHash(FirstDefaultArgument) !=
computeODRHash(SecondDefaultArgument)) {
DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ODRHash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> {
D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
Hash.AddBoolean(hasDefaultArgument);
if (hasDefaultArgument) {
AddStmt(D->getDefaultArgument());
AddTemplateArgument(D->getDefaultArgument().getArgument());
}
Hash.AddBoolean(D->isParameterPack());

Expand Down
5 changes: 3 additions & 2 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2281,8 +2281,9 @@ bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
Ctx, Arg, TTPD->getDefaultArgument().getArgument(), Args, Depth);
} else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
return NTTPD->hasDefaultArgument() &&
isSubstitutedTemplateArgument(Ctx, Arg, NTTPD->getDefaultArgument(),
Args, Depth);
isSubstitutedTemplateArgument(
Ctx, Arg, NTTPD->getDefaultArgument().getArgument(), Args,
Depth);
}
return false;
}
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/ExtractAPI/DeclarationFragments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,8 +1023,9 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
if (NTP->hasDefaultArgument()) {
SmallString<8> ExprStr;
raw_svector_ostream Output(ExprStr);
NTP->getDefaultArgument()->printPretty(
Output, nullptr, NTP->getASTContext().getPrintingPolicy());
NTP->getDefaultArgument().getArgument().print(
NTP->getASTContext().getPrintingPolicy(), Output,
/*IncludeType=*/false);
Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
.append(ExprStr, DeclarationFragments::FragmentKind::Text);
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Index/IndexDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,8 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
IndexCtx.indexTypeSourceInfo(NTTP->getTypeSourceInfo(), Parent);
if (NTTP->hasDefaultArgument())
IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
handleTemplateArgumentLoc(NTTP->getDefaultArgument(), Parent,
TP->getLexicalDeclContext());
} else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
if (TTPD->hasDefaultArgument())
handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,12 @@ void HLSLExternalSemaSource::defineHLSLVectorAlias() {
AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1,
&AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy,
false, AST.getTrivialTypeSourceInfo(AST.IntTy));
Expr *LiteralExpr =
IntegerLiteral::Create(AST, llvm::APInt(AST.getIntWidth(AST.IntTy), 4),
AST.IntTy, SourceLocation());
SizeParam->setDefaultArgument(LiteralExpr);
llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4);
TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy,
/*IsDefaulted=*/true);
SizeParam->setDefaultArgument(
AST, SemaPtr->getTrivialTemplateArgumentLoc(Default, AST.IntTy,
SourceLocation(), SizeParam));
TemplateParams.emplace_back(SizeParam);

auto *ParamList =
Expand Down
46 changes: 22 additions & 24 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1599,7 +1599,9 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
return Param;

Param->setDefaultArgument(Default);
Param->setDefaultArgument(
Context, getTrivialTemplateArgumentLoc(TemplateArgument(Default),
QualType(), SourceLocation()));
}

return Param;
Expand Down Expand Up @@ -3630,9 +3632,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,

// Check the presence of a default argument here.
if (NewNonTypeParm->hasDefaultArgument() &&
DiagnoseDefaultTemplateArgument(*this, TPC,
NewNonTypeParm->getLocation(),
NewNonTypeParm->getDefaultArgument()->getSourceRange())) {
DiagnoseDefaultTemplateArgument(
*this, TPC, NewNonTypeParm->getLocation(),
NewNonTypeParm->getDefaultArgument().getSourceRange())) {
NewNonTypeParm->removeDefaultArgument();
}

Expand Down Expand Up @@ -6107,16 +6109,17 @@ static bool SubstDefaultTemplateArgument(
/// parameters that precede \p Param in the template parameter list.
///
/// \returns the substituted template argument, or NULL if an error occurred.
static ExprResult SubstDefaultTemplateArgument(
static bool SubstDefaultTemplateArgument(
Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc,
SourceLocation RAngleLoc, NonTypeTemplateParmDecl *Param,
ArrayRef<TemplateArgument> SugaredConverted,
ArrayRef<TemplateArgument> CanonicalConverted) {
ArrayRef<TemplateArgument> CanonicalConverted,
TemplateArgumentLoc &Output) {
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template,
SugaredConverted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return ExprError();
return true;

// Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted,
Expand All @@ -6127,7 +6130,8 @@ static ExprResult SubstDefaultTemplateArgument(
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
EnterExpressionEvaluationContext ConstantEvaluated(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists);
return SemaRef.SubstTemplateArgument(Param->getDefaultArgument(),
TemplateArgLists, Output);
}

/// Substitute template arguments into the default template argument for
Expand Down Expand Up @@ -6219,14 +6223,12 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable(
return TemplateArgumentLoc();

HasDefaultArg = true;
ExprResult Arg = SubstDefaultTemplateArgument(
*this, Template, TemplateLoc, RAngleLoc, NonTypeParm, SugaredConverted,
CanonicalConverted);
if (Arg.isInvalid())
TemplateArgumentLoc Output;
if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc,
NonTypeParm, SugaredConverted,
CanonicalConverted, Output))
return TemplateArgumentLoc();

Expr *ArgE = Arg.getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE);
return Output;
}

TemplateTemplateParmDecl *TempTempParm
Expand Down Expand Up @@ -6803,14 +6805,10 @@ bool Sema::CheckTemplateArgumentList(
return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP,
NewArgs);

ExprResult E = SubstDefaultTemplateArgument(
*this, Template, TemplateLoc, RAngleLoc, NTTP, SugaredConverted,
CanonicalConverted);
if (E.isInvalid())
if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc,
NTTP, SugaredConverted,
CanonicalConverted, Arg))
return true;

Expr *Ex = E.getAs<Expr>();
Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
} else {
TemplateTemplateParmDecl *TempParm
= cast<TemplateTemplateParmDecl>(*Param);
Expand Down Expand Up @@ -9523,10 +9521,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
}
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
if (Expr *DefArg = NTTP->getDefaultArgument()) {
if (NTTP->hasDefaultArgument()) {
Diag(NTTP->getDefaultArgumentLoc(),
diag::err_default_arg_in_partial_spec)
<< DefArg->getSourceRange();
<< NTTP->getDefaultArgument().getSourceRange();
NTTP->removeDefaultArgument();
}
} else {
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,14 +536,14 @@ static NamedDecl *getTemplateParameterWithDefault(Sema &S, NamedDecl *A,
}
case Decl::NonTypeTemplateParm: {
auto *T = cast<NonTypeTemplateParmDecl>(A);
// FIXME: Ditto, as above for TemplateTypeParm case.
if (T->isParameterPack())
return A;
auto *R = NonTypeTemplateParmDecl::Create(
S.Context, A->getDeclContext(), SourceLocation(), SourceLocation(),
T->getDepth(), T->getIndex(), T->getIdentifier(), T->getType(),
/*ParameterPack=*/false, T->getTypeSourceInfo());
R->setDefaultArgument(Default.getAsExpr());
T->isParameterPack(), T->getTypeSourceInfo());
R->setDefaultArgument(S.Context,
S.getTrivialTemplateArgumentLoc(
Default, Default.getNonTypeTemplateArgumentType(),
SourceLocation()));
if (auto *PTC = T->getPlaceholderTypeConstraint())
R->setPlaceholderTypeConstraint(PTC);
return R;
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3123,9 +3123,10 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
EnterExpressionEvaluationContext ConstantEvaluated(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs);
if (!Value.isInvalid())
Param->setDefaultArgument(Value.get());
TemplateArgumentLoc Result;
if (!SemaRef.SubstTemplateArgument(D->getDefaultArgument(), TemplateArgs,
Result))
Param->setDefaultArgument(SemaRef.Context, Result);
}

// Introduce this template parameter's instantiation into the instantiation
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2717,7 +2717,8 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
// Rest of NonTypeTemplateParmDecl.
D->ParameterPack = Record.readInt();
if (Record.readInt())
D->setDefaultArgument(Record.readExpr());
D->setDefaultArgument(Reader.getContext(),
Record.readTemplateArgumentLoc());
}
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTWriterDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1941,7 +1941,7 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
!D->defaultArgumentWasInherited();
Record.push_back(OwnsDefaultArg);
if (OwnsDefaultArg)
Record.AddStmt(D->getDefaultArgument());
Record.AddTemplateArgumentLoc(D->getDefaultArgument());
Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
}
}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/AST/ast-dump-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ namespace testClassTemplateDecl {

// CHECK: ClassTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-148]]:3, col:31> col:31 TestTemplateDefaultNonType{{$}}
// CHECK-NEXT: |-NonTypeTemplateParmDecl 0x{{.+}} <col:12, col:20> col:16 'int' depth 0 index 0 I{{$}}
// CHECK-NEXT: | `-TemplateArgument expr{{$}}
// CHECK-NEXT: | `-TemplateArgument <col:20> expr{{$}}
// CHECK-NEXT: | `-IntegerLiteral 0x{{.+}} <col:20> 'int' 42{{$}}
// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} <col:24, col:31> col:31 struct TestTemplateDefaultNonType{{$}}

Expand Down Expand Up @@ -671,7 +671,7 @@ namespace TestNonTypeTemplateParmDecl {
// CHECK: NamespaceDecl{{.*}} TestNonTypeTemplateParmDecl
// CHECK-NEXT: FunctionTemplateDecl
// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I
// CHECK-NEXT: TemplateArgument expr
// CHECK-NEXT: TemplateArgument {{.*}} expr
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J

Expand Down
Loading

0 comments on commit 2bde13c

Please sign in to comment.