Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang] Implement CWG2398 provisional TTP matching to class templates #92855

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
51 changes: 26 additions & 25 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 @@ -1805,6 +1807,8 @@ static void SetNestedNameSpecifier(Sema &S, TagDecl *T,
// Returns the template parameter list with all default template argument
// information.
static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) {
if (TD->isImplicit())
return TD->getTemplateParameters();
// Make sure we get the template parameter list from the most
// recent declaration, since that is the only one that is guaranteed to
// have all the default template argument information.
Expand All @@ -1825,7 +1829,8 @@ static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) {
// template <class = void> friend struct C;
// };
// template struct S<int>;
while (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None &&
while ((D->isImplicit() ||
D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) &&
D->getPreviousDecl())
D = D->getPreviousDecl();
return cast<TemplateDecl>(D)->getTemplateParameters();
Expand Down Expand Up @@ -3630,9 +3635,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 +6112,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 +6133,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 +6226,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 +6808,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 +9524,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
Loading
Loading