#include "TreeTransform.h"
#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprConcepts.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/Support/TimeProfiler.h"
using namespace clang;
using namespace sema;
MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
const NamedDecl *D, const TemplateArgumentList *Innermost,
bool RelativeToPrimary, const FunctionDecl *Pattern) {
MultiLevelTemplateArgumentList Result;
if (Innermost)
Result.addOuterTemplateArguments(Innermost);
const auto *Ctx = dyn_cast<DeclContext>(D);
if (!Ctx) {
Ctx = D->getDeclContext();
const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(D);
if (Spec && !Spec->isClassScopeExplicitSpecialization()) {
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
!isa<VarTemplatePartialSpecializationDecl>(Spec))
return Result;
Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
assert(Spec->getSpecializedTemplate() && "No variable template?");
llvm::PointerUnion<VarTemplateDecl*,
VarTemplatePartialSpecializationDecl*> Specialized
= Spec->getSpecializedTemplateOrPartial();
if (VarTemplatePartialSpecializationDecl *Partial =
Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
if (Partial->isMemberSpecialization())
return Result;
} else {
VarTemplateDecl *Tmpl = Specialized.get<VarTemplateDecl *>();
if (Tmpl->isMemberSpecialization())
return Result;
}
}
if (Ctx->isTranslationUnit()) {
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
Result.addOuterTemplateArguments(None);
return Result;
}
}
}
while (!Ctx->isFileContext()) {
const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
if (Spec && !Spec->isClassScopeExplicitSpecialization()) {
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
!isa<ClassTemplatePartialSpecializationDecl>(Spec))
break;
Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
assert(Spec->getSpecializedTemplate() && "No class template?");
if (Spec->getSpecializedTemplate()->isMemberSpecialization())
break;
}
else if (const auto *Function = dyn_cast<FunctionDecl>(Ctx)) {
if (!RelativeToPrimary &&
Function->getTemplateSpecializationKindForInstantiation() ==
TSK_ExplicitSpecialization)
break;
if (!RelativeToPrimary && Function->getTemplateSpecializationKind() ==
TSK_ExplicitSpecialization) {
} else if (const TemplateArgumentList *TemplateArgs
= Function->getTemplateSpecializationArgs()) {
Result.addOuterTemplateArguments(TemplateArgs);
assert(Function->getPrimaryTemplate() && "No function template?");
if (Function->getPrimaryTemplate()->isMemberSpecialization())
break;
if (isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function))
break;
} else if (Function->getDescribedFunctionTemplate()) {
assert(Result.getNumSubstitutedLevels() == 0 &&
"Outer template not instantiated?");
}
if (Function->getFriendObjectKind() &&
Function->getDeclContext()->isFileContext() &&
(!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) {
Ctx = Function->getLexicalDeclContext();
RelativeToPrimary = false;
continue;
}
} else if (const auto *Rec = dyn_cast<CXXRecordDecl>(Ctx)) {
if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
assert(Result.getNumSubstitutedLevels() == 0 &&
"Outer template not instantiated?");
if (ClassTemplate->isMemberSpecialization())
break;
}
}
Ctx = Ctx->getParent();
RelativeToPrimary = false;
}
return Result;
}
bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
switch (Kind) {
case TemplateInstantiation:
case ExceptionSpecInstantiation:
case DefaultTemplateArgumentInstantiation:
case DefaultFunctionArgumentInstantiation:
case ExplicitTemplateArgumentSubstitution:
case DeducedTemplateArgumentSubstitution:
case PriorTemplateArgumentSubstitution:
case ConstraintsCheck:
case NestedRequirementConstraintsCheck:
return true;
case RequirementInstantiation:
case DefaultTemplateArgumentChecking:
case DeclaringSpecialMember:
case DeclaringImplicitEqualityComparison:
case DefiningSynthesizedFunction:
case ExceptionSpecEvaluation:
case ConstraintSubstitution:
case ParameterMappingSubstitution:
case ConstraintNormalization:
case RewritingOperatorAsSpaceship:
case InitializingStructuredBinding:
case MarkingClassDllexported:
case BuildingBuiltinDumpStructCall:
return false;
case Memoization:
break;
}
llvm_unreachable("Invalid SynthesisKind!");
}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
Decl *Entity, NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo *DeductionInfo)
: SemaRef(SemaRef) {
if (SemaRef.Diags.hasFatalErrorOccurred() &&
SemaRef.hasUncompilableErrorOccurred()) {
Invalid = true;
return;
}
Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
if (!Invalid) {
CodeSynthesisContext Inst;
Inst.Kind = Kind;
Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Entity = Entity;
Inst.Template = Template;
Inst.TemplateArgs = TemplateArgs.data();
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.DeductionInfo = DeductionInfo;
Inst.InstantiationRange = InstantiationRange;
SemaRef.pushCodeSynthesisContext(Inst);
AlreadyInstantiating = !Inst.Entity ? false :
!SemaRef.InstantiatingSpecializations
.insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
.second;
atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
}
}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation, Decl *Entity,
SourceRange InstantiationRange)
: InstantiatingTemplate(SemaRef,
CodeSynthesisContext::TemplateInstantiation,
PointOfInstantiation, InstantiationRange, Entity) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionDecl *Entity,
ExceptionSpecification, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ExceptionSpecInstantiation,
PointOfInstantiation, InstantiationRange, Entity) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateParameter Param,
TemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef,
CodeSynthesisContext::DefaultTemplateArgumentInstantiation,
PointOfInstantiation, InstantiationRange, getAsNamedDecl(Param),
Template, TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
FunctionTemplateDecl *FunctionTemplate,
ArrayRef<TemplateArgument> TemplateArgs,
CodeSynthesisContext::SynthesisKind Kind,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
: InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation,
InstantiationRange, FunctionTemplate, nullptr,
TemplateArgs, &DeductionInfo) {
assert(
Kind == CodeSynthesisContext::ExplicitTemplateArgumentSubstitution ||
Kind == CodeSynthesisContext::DeducedTemplateArgumentSubstitution);
}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
TemplateDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef,
CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
PointOfInstantiation, InstantiationRange, Template, nullptr,
TemplateArgs, &DeductionInfo) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
ClassTemplatePartialSpecializationDecl *PartialSpec,
ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef,
CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
TemplateArgs, &DeductionInfo) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
VarTemplatePartialSpecializationDecl *PartialSpec,
ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef,
CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
TemplateArgs, &DeductionInfo) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation, ParmVarDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef,
CodeSynthesisContext::DefaultFunctionArgumentInstantiation,
PointOfInstantiation, InstantiationRange, Param, nullptr,
TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template,
NonTypeTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef,
CodeSynthesisContext::PriorTemplateArgumentSubstitution,
PointOfInstantiation, InstantiationRange, Param, Template,
TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template,
TemplateTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef,
CodeSynthesisContext::PriorTemplateArgumentSubstitution,
PointOfInstantiation, InstantiationRange, Param, Template,
TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template,
NamedDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::DefaultTemplateArgumentChecking,
PointOfInstantiation, InstantiationRange, Param, Template,
TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
concepts::Requirement *Req, sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::RequirementInstantiation,
PointOfInstantiation, InstantiationRange, nullptr,
nullptr, None, &DeductionInfo) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
concepts::NestedRequirement *Req, ConstraintsCheck,
SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::NestedRequirementConstraintsCheck,
PointOfInstantiation, InstantiationRange, nullptr,
nullptr, None) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
ConstraintsCheck, NamedDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ConstraintsCheck,
PointOfInstantiation, InstantiationRange, Template, nullptr,
TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
ConstraintSubstitution, NamedDecl *Template,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ConstraintSubstitution,
PointOfInstantiation, InstantiationRange, Template, nullptr,
{}, &DeductionInfo) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
ConstraintNormalization, NamedDecl *Template,
SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ConstraintNormalization,
PointOfInstantiation, InstantiationRange, Template) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
ParameterMappingSubstitution, NamedDecl *Template,
SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ParameterMappingSubstitution,
PointOfInstantiation, InstantiationRange, Template) {}
void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
InNonInstantiationSFINAEContext = false;
CodeSynthesisContexts.push_back(Ctx);
if (!Ctx.isInstantiationRecord())
++NonInstantiationEntries;
if (isStackNearlyExhausted())
warnStackExhausted(Ctx.PointOfInstantiation);
}
void Sema::popCodeSynthesisContext() {
auto &Active = CodeSynthesisContexts.back();
if (!Active.isInstantiationRecord()) {
assert(NonInstantiationEntries > 0);
--NonInstantiationEntries;
}
InNonInstantiationSFINAEContext = Active.SavedInNonInstantiationSFINAEContext;
assert(CodeSynthesisContexts.size() >=
CodeSynthesisContextLookupModules.size() &&
"forgot to remove a lookup module for a template instantiation");
if (CodeSynthesisContexts.size() ==
CodeSynthesisContextLookupModules.size()) {
if (Module *M = CodeSynthesisContextLookupModules.back())
LookupModulesCache.erase(M);
CodeSynthesisContextLookupModules.pop_back();
}
if (CodeSynthesisContexts.size() ==
LastEmittedCodeSynthesisContextDepth)
LastEmittedCodeSynthesisContextDepth = 0;
CodeSynthesisContexts.pop_back();
}
void Sema::InstantiatingTemplate::Clear() {
if (!Invalid) {
if (!AlreadyInstantiating) {
auto &Active = SemaRef.CodeSynthesisContexts.back();
if (Active.Entity)
SemaRef.InstantiatingSpecializations.erase(
{Active.Entity->getCanonicalDecl(), Active.Kind});
}
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
SemaRef.CodeSynthesisContexts.back());
SemaRef.popCodeSynthesisContext();
Invalid = true;
}
}
static std::string convertCallArgsToString(Sema &S,
llvm::ArrayRef<const Expr *> Args) {
std::string Result;
llvm::raw_string_ostream OS(Result);
llvm::ListSeparator Comma;
for (const Expr *Arg : Args) {
OS << Comma;
Arg->IgnoreParens()->printPretty(OS, nullptr,
S.Context.getPrintingPolicy());
}
return Result;
}
bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
SourceLocation PointOfInstantiation,
SourceRange InstantiationRange) {
assert(SemaRef.NonInstantiationEntries <=
SemaRef.CodeSynthesisContexts.size());
if ((SemaRef.CodeSynthesisContexts.size() -
SemaRef.NonInstantiationEntries)
<= SemaRef.getLangOpts().InstantiationDepth)
return false;
SemaRef.Diag(PointOfInstantiation,
diag::err_template_recursion_depth_exceeded)
<< SemaRef.getLangOpts().InstantiationDepth
<< InstantiationRange;
SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
<< SemaRef.getLangOpts().InstantiationDepth;
return true;
}
void Sema::PrintInstantiationStack() {
unsigned SkipStart = CodeSynthesisContexts.size(), SkipEnd = SkipStart;
unsigned Limit = Diags.getTemplateBacktraceLimit();
if (Limit && Limit < CodeSynthesisContexts.size()) {
SkipStart = Limit / 2 + Limit % 2;
SkipEnd = CodeSynthesisContexts.size() - Limit / 2;
}
unsigned InstantiationIdx = 0;
for (SmallVectorImpl<CodeSynthesisContext>::reverse_iterator
Active = CodeSynthesisContexts.rbegin(),
ActiveEnd = CodeSynthesisContexts.rend();
Active != ActiveEnd;
++Active, ++InstantiationIdx) {
if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) {
if (InstantiationIdx == SkipStart) {
Diags.Report(Active->PointOfInstantiation,
diag::note_instantiation_contexts_suppressed)
<< unsigned(CodeSynthesisContexts.size() - Limit);
}
continue;
}
switch (Active->Kind) {
case CodeSynthesisContext::TemplateInstantiation: {
Decl *D = Active->Entity;
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
unsigned DiagID = diag::note_template_member_class_here;
if (isa<ClassTemplateSpecializationDecl>(Record))
DiagID = diag::note_template_class_instantiation_here;
Diags.Report(Active->PointOfInstantiation, DiagID)
<< Record << Active->InstantiationRange;
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
unsigned DiagID;
if (Function->getPrimaryTemplate())
DiagID = diag::note_function_template_spec_here;
else
DiagID = diag::note_template_member_function_here;
Diags.Report(Active->PointOfInstantiation, DiagID)
<< Function
<< Active->InstantiationRange;
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
Diags.Report(Active->PointOfInstantiation,
VD->isStaticDataMember()?
diag::note_template_static_data_member_def_here
: diag::note_template_variable_def_here)
<< VD
<< Active->InstantiationRange;
} else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
Diags.Report(Active->PointOfInstantiation,
diag::note_template_enum_def_here)
<< ED
<< Active->InstantiationRange;
} else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
Diags.Report(Active->PointOfInstantiation,
diag::note_template_nsdmi_here)
<< FD << Active->InstantiationRange;
} else {
Diags.Report(Active->PointOfInstantiation,
diag::note_template_type_alias_instantiation_here)
<< cast<TypeAliasTemplateDecl>(D)
<< Active->InstantiationRange;
}
break;
}
case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: {
TemplateDecl *Template = cast<TemplateDecl>(Active->Template);
SmallString<128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
Template->printName(OS);
printTemplateArgumentList(OS, Active->template_arguments(),
getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation,
diag::note_default_arg_instantiation_here)
<< OS.str()
<< Active->InstantiationRange;
break;
}
case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution: {
FunctionTemplateDecl *FnTmpl = cast<FunctionTemplateDecl>(Active->Entity);
Diags.Report(Active->PointOfInstantiation,
diag::note_explicit_template_arg_substitution_here)
<< FnTmpl
<< getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
break;
}
case CodeSynthesisContext::DeducedTemplateArgumentSubstitution: {
if (FunctionTemplateDecl *FnTmpl =
dyn_cast<FunctionTemplateDecl>(Active->Entity)) {
Diags.Report(Active->PointOfInstantiation,
diag::note_function_template_deduction_instantiation_here)
<< FnTmpl
<< getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
} else {
bool IsVar = isa<VarTemplateDecl>(Active->Entity) ||
isa<VarTemplateSpecializationDecl>(Active->Entity);
bool IsTemplate = false;
TemplateParameterList *Params;
if (auto *D = dyn_cast<TemplateDecl>(Active->Entity)) {
IsTemplate = true;
Params = D->getTemplateParameters();
} else if (auto *D = dyn_cast<ClassTemplatePartialSpecializationDecl>(
Active->Entity)) {
Params = D->getTemplateParameters();
} else if (auto *D = dyn_cast<VarTemplatePartialSpecializationDecl>(
Active->Entity)) {
Params = D->getTemplateParameters();
} else {
llvm_unreachable("unexpected template kind");
}
Diags.Report(Active->PointOfInstantiation,
diag::note_deduced_template_arg_substitution_here)
<< IsVar << IsTemplate << cast<NamedDecl>(Active->Entity)
<< getTemplateArgumentBindingsText(Params, Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
}
break;
}
case CodeSynthesisContext::DefaultFunctionArgumentInstantiation: {
ParmVarDecl *Param = cast<ParmVarDecl>(Active->Entity);
FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
SmallString<128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
FD->printName(OS);
printTemplateArgumentList(OS, Active->template_arguments(),
getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation,
diag::note_default_function_arg_instantiation_here)
<< OS.str()
<< Active->InstantiationRange;
break;
}
case CodeSynthesisContext::PriorTemplateArgumentSubstitution: {
NamedDecl *Parm = cast<NamedDecl>(Active->Entity);
std::string Name;
if (!Parm->getName().empty())
Name = std::string(" '") + Parm->getName().str() + "'";
TemplateParameterList *TemplateParams = nullptr;
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
TemplateParams = Template->getTemplateParameters();
else
TemplateParams =
cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
->getTemplateParameters();
Diags.Report(Active->PointOfInstantiation,
diag::note_prior_template_arg_substitution)
<< isa<TemplateTemplateParmDecl>(Parm)
<< Name
<< getTemplateArgumentBindingsText(TemplateParams,
Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
break;
}
case CodeSynthesisContext::DefaultTemplateArgumentChecking: {
TemplateParameterList *TemplateParams = nullptr;
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
TemplateParams = Template->getTemplateParameters();
else
TemplateParams =
cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
->getTemplateParameters();
Diags.Report(Active->PointOfInstantiation,
diag::note_template_default_arg_checking)
<< getTemplateArgumentBindingsText(TemplateParams,
Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
break;
}
case CodeSynthesisContext::ExceptionSpecEvaluation:
Diags.Report(Active->PointOfInstantiation,
diag::note_evaluating_exception_spec_here)
<< cast<FunctionDecl>(Active->Entity);
break;
case CodeSynthesisContext::ExceptionSpecInstantiation:
Diags.Report(Active->PointOfInstantiation,
diag::note_template_exception_spec_instantiation_here)
<< cast<FunctionDecl>(Active->Entity)
<< Active->InstantiationRange;
break;
case CodeSynthesisContext::RequirementInstantiation:
Diags.Report(Active->PointOfInstantiation,
diag::note_template_requirement_instantiation_here)
<< Active->InstantiationRange;
break;
case CodeSynthesisContext::NestedRequirementConstraintsCheck:
Diags.Report(Active->PointOfInstantiation,
diag::note_nested_requirement_here)
<< Active->InstantiationRange;
break;
case CodeSynthesisContext::DeclaringSpecialMember:
Diags.Report(Active->PointOfInstantiation,
diag::note_in_declaration_of_implicit_special_member)
<< cast<CXXRecordDecl>(Active->Entity) << Active->SpecialMember;
break;
case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
Diags.Report(Active->Entity->getLocation(),
diag::note_in_declaration_of_implicit_equality_comparison);
break;
case CodeSynthesisContext::DefiningSynthesizedFunction: {
auto *FD = dyn_cast<FunctionDecl>(Active->Entity);
DefaultedFunctionKind DFK =
FD ? getDefaultedFunctionKind(FD) : DefaultedFunctionKind();
if (DFK.isSpecialMember()) {
auto *MD = cast<CXXMethodDecl>(FD);
Diags.Report(Active->PointOfInstantiation,
diag::note_member_synthesized_at)
<< MD->isExplicitlyDefaulted() << DFK.asSpecialMember()
<< Context.getTagDeclType(MD->getParent());
} else if (DFK.isComparison()) {
Diags.Report(Active->PointOfInstantiation,
diag::note_comparison_synthesized_at)
<< (int)DFK.asComparison()
<< Context.getTagDeclType(
cast<CXXRecordDecl>(FD->getLexicalDeclContext()));
}
break;
}
case CodeSynthesisContext::RewritingOperatorAsSpaceship:
Diags.Report(Active->Entity->getLocation(),
diag::note_rewriting_operator_as_spaceship);
break;
case CodeSynthesisContext::InitializingStructuredBinding:
Diags.Report(Active->PointOfInstantiation,
diag::note_in_binding_decl_init)
<< cast<BindingDecl>(Active->Entity);
break;
case CodeSynthesisContext::MarkingClassDllexported:
Diags.Report(Active->PointOfInstantiation,
diag::note_due_to_dllexported_class)
<< cast<CXXRecordDecl>(Active->Entity) << !getLangOpts().CPlusPlus11;
break;
case CodeSynthesisContext::BuildingBuiltinDumpStructCall:
Diags.Report(Active->PointOfInstantiation,
diag::note_building_builtin_dump_struct_call)
<< convertCallArgsToString(
*this,
llvm::makeArrayRef(Active->CallArgs, Active->NumCallArgs));
break;
case CodeSynthesisContext::Memoization:
break;
case CodeSynthesisContext::ConstraintsCheck: {
unsigned DiagID = 0;
if (!Active->Entity) {
Diags.Report(Active->PointOfInstantiation,
diag::note_nested_requirement_here)
<< Active->InstantiationRange;
break;
}
if (isa<ConceptDecl>(Active->Entity))
DiagID = diag::note_concept_specialization_here;
else if (isa<TemplateDecl>(Active->Entity))
DiagID = diag::note_checking_constraints_for_template_id_here;
else if (isa<VarTemplatePartialSpecializationDecl>(Active->Entity))
DiagID = diag::note_checking_constraints_for_var_spec_id_here;
else if (isa<ClassTemplatePartialSpecializationDecl>(Active->Entity))
DiagID = diag::note_checking_constraints_for_class_spec_id_here;
else {
assert(isa<FunctionDecl>(Active->Entity));
DiagID = diag::note_checking_constraints_for_function_here;
}
SmallString<128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
cast<NamedDecl>(Active->Entity)->printName(OS);
if (!isa<FunctionDecl>(Active->Entity)) {
printTemplateArgumentList(OS, Active->template_arguments(),
getPrintingPolicy());
}
Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str()
<< Active->InstantiationRange;
break;
}
case CodeSynthesisContext::ConstraintSubstitution:
Diags.Report(Active->PointOfInstantiation,
diag::note_constraint_substitution_here)
<< Active->InstantiationRange;
break;
case CodeSynthesisContext::ConstraintNormalization:
Diags.Report(Active->PointOfInstantiation,
diag::note_constraint_normalization_here)
<< cast<NamedDecl>(Active->Entity)->getName()
<< Active->InstantiationRange;
break;
case CodeSynthesisContext::ParameterMappingSubstitution:
Diags.Report(Active->PointOfInstantiation,
diag::note_parameter_mapping_substitution_here)
<< Active->InstantiationRange;
break;
}
}
}
Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
if (InNonInstantiationSFINAEContext)
return Optional<TemplateDeductionInfo *>(nullptr);
for (SmallVectorImpl<CodeSynthesisContext>::const_reverse_iterator
Active = CodeSynthesisContexts.rbegin(),
ActiveEnd = CodeSynthesisContexts.rend();
Active != ActiveEnd;
++Active)
{
switch (Active->Kind) {
case CodeSynthesisContext::TemplateInstantiation:
if (isa<TypeAliasTemplateDecl>(Active->Entity))
break;
LLVM_FALLTHROUGH;
case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
case CodeSynthesisContext::ExceptionSpecInstantiation:
case CodeSynthesisContext::ConstraintsCheck:
case CodeSynthesisContext::ParameterMappingSubstitution:
case CodeSynthesisContext::ConstraintNormalization:
case CodeSynthesisContext::NestedRequirementConstraintsCheck:
return None;
case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
case CodeSynthesisContext::DefaultTemplateArgumentChecking:
case CodeSynthesisContext::RewritingOperatorAsSpaceship:
break;
case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
case CodeSynthesisContext::ConstraintSubstitution:
case CodeSynthesisContext::RequirementInstantiation:
assert(Active->DeductionInfo && "Missing deduction info pointer");
return Active->DeductionInfo;
case CodeSynthesisContext::DeclaringSpecialMember:
case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
case CodeSynthesisContext::DefiningSynthesizedFunction:
case CodeSynthesisContext::InitializingStructuredBinding:
case CodeSynthesisContext::MarkingClassDllexported:
case CodeSynthesisContext::BuildingBuiltinDumpStructCall:
return None;
case CodeSynthesisContext::ExceptionSpecEvaluation:
break;
case CodeSynthesisContext::Memoization:
break;
}
if (Active->SavedInNonInstantiationSFINAEContext)
return Optional<TemplateDeductionInfo *>(nullptr);
}
return None;
}
namespace {
class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
const MultiLevelTemplateArgumentList &TemplateArgs;
SourceLocation Loc;
DeclarationName Entity;
public:
typedef TreeTransform<TemplateInstantiator> inherited;
TemplateInstantiator(Sema &SemaRef,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc,
DeclarationName Entity)
: inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
Entity(Entity) { }
bool AlreadyTransformed(QualType T);
SourceLocation getBaseLocation() { return Loc; }
DeclarationName getBaseEntity() { return Entity; }
void setBase(SourceLocation Loc, DeclarationName Entity) {
this->Loc = Loc;
this->Entity = Entity;
}
unsigned TransformTemplateDepth(unsigned Depth) {
return TemplateArgs.getNewDepth(Depth);
}
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded,
bool &ShouldExpand, bool &RetainExpansion,
Optional<unsigned> &NumExpansions) {
return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
PatternRange, Unexpanded,
TemplateArgs,
ShouldExpand,
RetainExpansion,
NumExpansions);
}
void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
}
TemplateArgument ForgetPartiallySubstitutedPack() {
TemplateArgument Result;
if (NamedDecl *PartialPack
= SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
MultiLevelTemplateArgumentList &TemplateArgs
= const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
Result = TemplateArgs(Depth, Index);
TemplateArgs.setArgument(Depth, Index, TemplateArgument());
}
}
return Result;
}
void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
if (Arg.isNull())
return;
if (NamedDecl *PartialPack
= SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
MultiLevelTemplateArgumentList &TemplateArgs
= const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
TemplateArgs.setArgument(Depth, Index, Arg);
}
}
Decl *TransformDecl(SourceLocation Loc, Decl *D);
void transformAttrs(Decl *Old, Decl *New) {
SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
}
void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
if (Old->isParameterPack()) {
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
for (auto *New : NewDecls)
SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
Old, cast<VarDecl>(New));
return;
}
assert(NewDecls.size() == 1 &&
"should only have multiple expansions for a pack");
Decl *New = NewDecls.front();
auto *NewMD = dyn_cast<CXXMethodDecl>(New);
if (NewMD && isLambdaCallOperator(NewMD)) {
auto *OldMD = dyn_cast<CXXMethodDecl>(Old);
if (auto *NewTD = NewMD->getDescribedFunctionTemplate())
NewTD->setInstantiatedFromMemberTemplate(
OldMD->getDescribedFunctionTemplate());
else
NewMD->setInstantiationOfMemberFunction(OldMD,
TSK_ImplicitInstantiation);
}
SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
if (auto *DC = dyn_cast<DeclContext>(Old))
SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
}
Decl *TransformDefinition(SourceLocation Loc, Decl *D);
NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *Declarator,
SourceLocation StartLoc,
SourceLocation NameLoc,
IdentifierInfo *Name);
VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TSInfo, QualType T);
QualType RebuildElaboratedType(SourceLocation KeywordLoc,
ElaboratedTypeKeyword Keyword,
NestedNameSpecifierLoc QualifierLoc,
QualType T);
TemplateName
TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = nullptr,
bool AllowInjectedClassName = false);
const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
ExprResult TransformPredefinedExpr(PredefinedExpr *E);
ExprResult TransformDeclRefExpr(DeclRefExpr *E);
ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *D);
ExprResult TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E);
ExprResult TransformSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E);
ExprResult RebuildVarDeclRefExpr(VarDecl *PD, SourceLocation Loc);
ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, VarDecl *PD);
ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL) {
return inherited::TransformFunctionProtoType(TLB, TL);
}
template<typename Fn>
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
Qualifiers ThisTypeQuals,
Fn TransformExceptionSpec);
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
Optional<unsigned> NumExpansions,
bool ExpectParameterPack);
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
TemplateTypeParmTypeLoc TL);
QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
SubstTemplateTypeParmPackTypeLoc TL);
ExprResult TransformLambdaExpr(LambdaExpr *E) {
LocalInstantiationScope Scope(SemaRef, true);
return inherited::TransformLambdaExpr(E);
}
ExprResult TransformRequiresExpr(RequiresExpr *E) {
LocalInstantiationScope Scope(SemaRef, true);
return inherited::TransformRequiresExpr(E);
}
bool TransformRequiresExprRequirements(
ArrayRef<concepts::Requirement *> Reqs,
SmallVectorImpl<concepts::Requirement *> &Transformed) {
bool SatisfactionDetermined = false;
for (concepts::Requirement *Req : Reqs) {
concepts::Requirement *TransReq = nullptr;
if (!SatisfactionDetermined) {
if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req))
TransReq = TransformTypeRequirement(TypeReq);
else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req))
TransReq = TransformExprRequirement(ExprReq);
else
TransReq = TransformNestedRequirement(
cast<concepts::NestedRequirement>(Req));
if (!TransReq)
return true;
if (!TransReq->isDependent() && !TransReq->isSatisfied())
SatisfactionDetermined = true;
} else
TransReq = Req;
Transformed.push_back(TransReq);
}
return false;
}
TemplateParameterList *TransformTemplateParameterList(
TemplateParameterList *OrigTPL) {
if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
TemplateDeclInstantiator DeclInstantiator(getSema(),
Owner, TemplateArgs);
return DeclInstantiator.SubstTemplateParams(OrigTPL);
}
concepts::TypeRequirement *
TransformTypeRequirement(concepts::TypeRequirement *Req);
concepts::ExprRequirement *
TransformExprRequirement(concepts::ExprRequirement *Req);
concepts::NestedRequirement *
TransformNestedRequirement(concepts::NestedRequirement *Req);
private:
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
SourceLocation loc,
TemplateArgument arg);
};
}
bool TemplateInstantiator::AlreadyTransformed(QualType T) {
if (T.isNull())
return true;
if (T->isInstantiationDependentType() || T->isVariablyModifiedType())
return false;
getSema().MarkDeclarationsReferencedInType(Loc, T);
return true;
}
static TemplateArgument
getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
assert(S.ArgumentPackSubstitutionIndex >= 0);
assert(S.ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
Arg = Arg.pack_begin()[S.ArgumentPackSubstitutionIndex];
if (Arg.isPackExpansion())
Arg = Arg.getPackExpansionPattern();
return Arg;
}
Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
if (!D)
return nullptr;
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
TTP->getPosition()))
return D;
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
"Wrong kind of template template argument");
return Template.getAsTemplateDecl();
}
}
return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
}
Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
if (!Inst)
return nullptr;
getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst);
return Inst;
}
NamedDecl *
TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
SourceLocation Loc) {
if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) {
const TemplateTypeParmType *TTP
= cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getIndex());
if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1)
return nullptr;
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
QualType T = Arg.getAsType();
if (T.isNull())
return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
if (const TagType *Tag = T->getAs<TagType>())
return Tag->getDecl();
getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
return nullptr;
}
}
return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
}
VarDecl *
TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *Declarator,
SourceLocation StartLoc,
SourceLocation NameLoc,
IdentifierInfo *Name) {
VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, Declarator,
StartLoc, NameLoc, Name);
if (Var)
getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
return Var;
}
VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TSInfo,
QualType T) {
VarDecl *Var = inherited::RebuildObjCExceptionDecl(ExceptionDecl, TSInfo, T);
if (Var)
getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
return Var;
}
QualType
TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
ElaboratedTypeKeyword Keyword,
NestedNameSpecifierLoc QualifierLoc,
QualType T) {
if (const TagType *TT = T->getAs<TagType>()) {
TagDecl* TD = TT->getDecl();
SourceLocation TagLocation = KeywordLoc;
IdentifierInfo *Id = TD->getIdentifier();
if (Id && Keyword != ETK_None && Keyword != ETK_Typename) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, false,
TagLocation, Id)) {
SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)
<< Id
<< FixItHint::CreateReplacement(SourceRange(TagLocation),
TD->getKindName());
SemaRef.Diag(TD->getLocation(), diag::note_previous_use);
}
}
}
return inherited::RebuildElaboratedType(KeywordLoc, Keyword, QualifierLoc, T);
}
TemplateName TemplateInstantiator::TransformTemplateName(
CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc,
QualType ObjectType, NamedDecl *FirstQualifierInScope,
bool AllowInjectedClassName) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
TTP->getPosition()))
return Name;
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
if (TemplateArgs.isRewrite()) {
if (Arg.getKind() == TemplateArgument::Pack) {
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
"unexpected pack arguments in template rewrite");
Arg = Arg.pack_begin()->getPackExpansionPattern();
}
assert(Arg.getKind() == TemplateArgument::Template &&
"unexpected nontype template argument kind in template rewrite");
return Arg.getAsTemplate();
}
if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1) {
return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg);
}
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
assert(!Template.isNull() && "Null template template argument");
assert(!Template.getAsQualifiedTemplateName() &&
"template decl to substitute is qualified?");
Template = getSema().Context.getSubstTemplateTemplateParm(TTP, Template);
return Template;
}
}
if (SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack()) {
if (getSema().ArgumentPackSubstitutionIndex == -1)
return Name;
TemplateArgument Arg = SubstPack->getArgumentPack();
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
return Arg.getAsTemplate().getNameToSubstitute();
}
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
FirstQualifierInScope,
AllowInjectedClassName);
}
ExprResult
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return E;
return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind());
}
ExprResult
TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *NTTP) {
if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
NTTP->getPosition()))
return E;
TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
if (TemplateArgs.isRewrite()) {
if (Arg.getKind() == TemplateArgument::Pack) {
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
"unexpected pack arguments in template rewrite");
Arg = Arg.pack_begin()->getPackExpansionPattern();
}
assert(Arg.getKind() == TemplateArgument::Expression &&
"unexpected nontype template argument kind in template rewrite");
return Arg.getAsExpr();
}
if (NTTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1) {
QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
E->getLocation(),
NTTP->getDeclName());
if (TargetType.isNull())
return ExprError();
QualType ExprType = TargetType.getNonLValueExprType(SemaRef.Context);
if (TargetType->isRecordType())
ExprType.addConst();
return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
NTTP, E->getLocation(), Arg);
}
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg);
}
const LoopHintAttr *
TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) {
Expr *TransformedExpr = getDerived().TransformExpr(LH->getValue()).get();
if (TransformedExpr == LH->getValue())
return LH;
if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation()))
return LH;
return LoopHintAttr::CreateImplicit(getSema().Context, LH->getOption(),
LH->getState(), TransformedExpr, *LH);
}
ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
NonTypeTemplateParmDecl *parm,
SourceLocation loc,
TemplateArgument arg) {
ExprResult result;
auto SubstParamType = [&] {
QualType T;
if (parm->isExpandedParameterPack())
T = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex);
else
T = parm->getType();
if (parm->isParameterPack() && isa<PackExpansionType>(T))
T = cast<PackExpansionType>(T)->getPattern();
return SemaRef.SubstType(T, TemplateArgs, loc, parm->getDeclName());
};
bool refParam = false;
if (arg.getKind() == TemplateArgument::Expression) {
Expr *argExpr = arg.getAsExpr();
result = argExpr;
if (argExpr->isLValue()) {
if (argExpr->getType()->isRecordType()) {
QualType paramType = SubstParamType();
if (paramType.isNull())
return ExprError();
refParam = paramType->isReferenceType();
} else {
refParam = true;
}
}
} else if (arg.getKind() == TemplateArgument::Declaration ||
arg.getKind() == TemplateArgument::NullPtr) {
ValueDecl *VD;
if (arg.getKind() == TemplateArgument::Declaration) {
VD = arg.getAsDecl();
VD = cast_or_null<ValueDecl>(
getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
if (!VD)
return ExprError();
} else {
VD = nullptr;
}
QualType paramType = VD ? arg.getParamTypeForDecl() : arg.getNullPtrType();
assert(!paramType.isNull() && "type substitution failed for param type");
assert(!paramType->isDependentType() && "param type still dependent");
result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc);
refParam = paramType->isReferenceType();
} else {
result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc);
assert(result.isInvalid() ||
SemaRef.Context.hasSameType(result.get()->getType(),
arg.getIntegralType()));
}
if (result.isInvalid())
return ExprError();
Expr *resultExpr = result.get();
return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
resultExpr->getType(), resultExpr->getValueKind(), loc, parm, refParam,
resultExpr);
}
ExprResult
TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) {
if (getSema().ArgumentPackSubstitutionIndex == -1) {
return E;
}
TemplateArgument Arg = E->getArgumentPack();
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
return transformNonTypeTemplateParmRef(E->getParameterPack(),
E->getParameterPackLocation(),
Arg);
}
ExprResult
TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) {
ExprResult SubstReplacement = E->getReplacement();
if (!isa<ConstantExpr>(SubstReplacement.get()))
SubstReplacement = TransformExpr(E->getReplacement());
if (SubstReplacement.isInvalid())
return true;
QualType SubstType = TransformType(E->getParameterType(getSema().Context));
if (SubstType.isNull())
return true;
TemplateArgument Converted;
if (SemaRef.CheckTemplateArgument(E->getParameter(), SubstType,
SubstReplacement.get(),
Converted).isInvalid())
return true;
return transformNonTypeTemplateParmRef(E->getParameter(),
E->getExprLoc(), Converted);
}
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD,
SourceLocation Loc) {
DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
return getSema().BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, PD);
}
ExprResult
TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
if (getSema().ArgumentPackSubstitutionIndex != -1) {
VarDecl *D = E->getExpansion(getSema().ArgumentPackSubstitutionIndex);
VarDecl *VD = cast_or_null<VarDecl>(TransformDecl(E->getExprLoc(), D));
if (!VD)
return ExprError();
return RebuildVarDeclRefExpr(VD, E->getExprLoc());
}
QualType T = TransformType(E->getType());
if (T.isNull())
return ExprError();
SmallVector<VarDecl *, 8> Vars;
Vars.reserve(E->getNumExpansions());
for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
I != End; ++I) {
VarDecl *D = cast_or_null<VarDecl>(TransformDecl(E->getExprLoc(), *I));
if (!D)
return ExprError();
Vars.push_back(D);
}
auto *PackExpr =
FunctionParmPackExpr::Create(getSema().Context, T, E->getParameterPack(),
E->getParameterPackLocation(), Vars);
getSema().MarkFunctionParmPackReferenced(PackExpr);
return PackExpr;
}
ExprResult
TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
VarDecl *PD) {
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
= getSema().CurrentInstantiationScope->findInstantiationOf(PD);
assert(Found && "no instantiation for parameter pack");
Decl *TransformedDecl;
if (DeclArgumentPack *Pack = Found->dyn_cast<DeclArgumentPack *>()) {
if (getSema().ArgumentPackSubstitutionIndex == -1) {
QualType T = TransformType(E->getType());
if (T.isNull())
return ExprError();
auto *PackExpr = FunctionParmPackExpr::Create(getSema().Context, T, PD,
E->getExprLoc(), *Pack);
getSema().MarkFunctionParmPackReferenced(PackExpr);
return PackExpr;
}
TransformedDecl = (*Pack)[getSema().ArgumentPackSubstitutionIndex];
} else {
TransformedDecl = Found->get<Decl*>();
}
return RebuildVarDeclRefExpr(cast<VarDecl>(TransformedDecl), E->getExprLoc());
}
ExprResult
TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
NamedDecl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
if (NTTP->getDepth() < TemplateArgs.getNumLevels())
return TransformTemplateParmRefExpr(E, NTTP);
}
if (VarDecl *PD = dyn_cast<VarDecl>(D))
if (PD->isParameterPack())
return TransformFunctionParmPackRefExpr(E, PD);
return inherited::TransformDeclRefExpr(E);
}
ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
CXXDefaultArgExpr *E) {
assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
getDescribedFunctionTemplate() &&
"Default arg expressions are never formed in dependent cases.");
return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(),
cast<FunctionDecl>(E->getParam()->getDeclContext()),
E->getParam());
}
template<typename Fn>
QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
Qualifiers ThisTypeQuals,
Fn TransformExceptionSpec) {
LocalInstantiationScope Scope(SemaRef, true);
return inherited::TransformFunctionProtoType(
TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);
}
ParmVarDecl *
TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
auto NewParm =
SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
NumExpansions, ExpectParameterPack);
if (NewParm && SemaRef.getLangOpts().OpenCL)
SemaRef.deduceOpenCLAddressSpace(NewParm);
return NewParm;
}
QualType
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
TemplateTypeParmTypeLoc TL) {
const TemplateTypeParmType *T = TL.getTypePtr();
if (T->getDepth() < TemplateArgs.getNumLevels()) {
if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) {
TemplateTypeParmTypeLoc NewTL
= TLB.push<TemplateTypeParmTypeLoc>(TL.getType());
NewTL.setNameLoc(TL.getNameLoc());
return TL.getType();
}
TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
if (TemplateArgs.isRewrite()) {
if (Arg.getKind() == TemplateArgument::Pack) {
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
"unexpected pack arguments in template rewrite");
Arg = Arg.pack_begin()->getPackExpansionPattern();
}
assert(Arg.getKind() == TemplateArgument::Type &&
"unexpected nontype template argument kind in template rewrite");
QualType NewT = Arg.getAsType();
assert(isa<TemplateTypeParmType>(NewT) &&
"type parm not rewritten to type parm");
auto NewTL = TLB.push<TemplateTypeParmTypeLoc>(NewT);
NewTL.setNameLoc(TL.getNameLoc());
return NewT;
}
if (T->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1) {
QualType Result
= getSema().Context.getSubstTemplateTypeParmPackType(T, Arg);
SubstTemplateTypeParmPackTypeLoc NewTL
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
}
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
assert(Arg.getKind() == TemplateArgument::Type &&
"Template argument kind mismatch");
QualType Replacement = Arg.getAsType();
QualType Result
= getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
SubstTemplateTypeParmTypeLoc NewTL
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
}
TemplateTypeParmDecl *NewTTPDecl = nullptr;
if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
TransformDecl(TL.getNameLoc(), OldTTPDecl));
QualType Result = getSema().Context.getTemplateTypeParmType(
T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(),
T->isParameterPack(), NewTTPDecl);
TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
}
QualType
TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
TypeLocBuilder &TLB,
SubstTemplateTypeParmPackTypeLoc TL) {
if (getSema().ArgumentPackSubstitutionIndex == -1) {
SubstTemplateTypeParmPackTypeLoc NewTL
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(TL.getType());
NewTL.setNameLoc(TL.getNameLoc());
return TL.getType();
}
TemplateArgument Arg = TL.getTypePtr()->getArgumentPack();
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
QualType Result = Arg.getAsType();
Result = getSema().Context.getSubstTemplateTypeParmType(
TL.getTypePtr()->getReplacedParameter(),
Result);
SubstTemplateTypeParmTypeLoc NewTL
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
}
template<typename EntityPrinter>
static concepts::Requirement::SubstitutionDiagnostic *
createSubstDiag(Sema &S, TemplateDeductionInfo &Info, EntityPrinter Printer) {
SmallString<128> Message;
SourceLocation ErrorLoc;
if (Info.hasSFINAEDiagnostic()) {
PartialDiagnosticAt PDA(SourceLocation(),
PartialDiagnostic::NullDiagnostic{});
Info.takeSFINAEDiagnostic(PDA);
PDA.second.EmitToString(S.getDiagnostics(), Message);
ErrorLoc = PDA.first;
} else {
ErrorLoc = Info.getLocation();
}
char *MessageBuf = new (S.Context) char[Message.size()];
std::copy(Message.begin(), Message.end(), MessageBuf);
SmallString<128> Entity;
llvm::raw_svector_ostream OS(Entity);
Printer(OS);
char *EntityBuf = new (S.Context) char[Entity.size()];
std::copy(Entity.begin(), Entity.end(), EntityBuf);
return new (S.Context) concepts::Requirement::SubstitutionDiagnostic{
StringRef(EntityBuf, Entity.size()), ErrorLoc,
StringRef(MessageBuf, Message.size())};
}
concepts::TypeRequirement *
TemplateInstantiator::TransformTypeRequirement(concepts::TypeRequirement *Req) {
if (!Req->isDependent() && !AlwaysRebuild())
return Req;
if (Req->isSubstitutionFailure()) {
if (AlwaysRebuild())
return RebuildTypeRequirement(
Req->getSubstitutionDiagnostic());
return Req;
}
Sema::SFINAETrap Trap(SemaRef);
TemplateDeductionInfo Info(Req->getType()->getTypeLoc().getBeginLoc());
Sema::InstantiatingTemplate TypeInst(SemaRef,
Req->getType()->getTypeLoc().getBeginLoc(), Req, Info,
Req->getType()->getTypeLoc().getSourceRange());
if (TypeInst.isInvalid())
return nullptr;
TypeSourceInfo *TransType = TransformType(Req->getType());
if (!TransType || Trap.hasErrorOccurred())
return RebuildTypeRequirement(createSubstDiag(SemaRef, Info,
[&] (llvm::raw_ostream& OS) {
Req->getType()->getType().print(OS, SemaRef.getPrintingPolicy());
}));
return RebuildTypeRequirement(TransType);
}
concepts::ExprRequirement *
TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) {
if (!Req->isDependent() && !AlwaysRebuild())
return Req;
Sema::SFINAETrap Trap(SemaRef);
llvm::PointerUnion<Expr *, concepts::Requirement::SubstitutionDiagnostic *>
TransExpr;
if (Req->isExprSubstitutionFailure())
TransExpr = Req->getExprSubstitutionDiagnostic();
else {
Expr *E = Req->getExpr();
TemplateDeductionInfo Info(E->getBeginLoc());
Sema::InstantiatingTemplate ExprInst(SemaRef, E->getBeginLoc(), Req, Info,
E->getSourceRange());
if (ExprInst.isInvalid())
return nullptr;
ExprResult TransExprRes = TransformExpr(E);
if (!TransExprRes.isInvalid() && !Trap.hasErrorOccurred() &&
TransExprRes.get()->hasPlaceholderType())
TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
if (TransExprRes.isInvalid() || Trap.hasErrorOccurred())
TransExpr = createSubstDiag(SemaRef, Info, [&](llvm::raw_ostream &OS) {
E->printPretty(OS, nullptr, SemaRef.getPrintingPolicy());
});
else
TransExpr = TransExprRes.get();
}
llvm::Optional<concepts::ExprRequirement::ReturnTypeRequirement> TransRetReq;
const auto &RetReq = Req->getReturnTypeRequirement();
if (RetReq.isEmpty())
TransRetReq.emplace();
else if (RetReq.isSubstitutionFailure())
TransRetReq.emplace(RetReq.getSubstitutionDiagnostic());
else if (RetReq.isTypeConstraint()) {
TemplateParameterList *OrigTPL =
RetReq.getTypeConstraintTemplateParameterList();
TemplateDeductionInfo Info(OrigTPL->getTemplateLoc());
Sema::InstantiatingTemplate TPLInst(SemaRef, OrigTPL->getTemplateLoc(),
Req, Info, OrigTPL->getSourceRange());
if (TPLInst.isInvalid())
return nullptr;
TemplateParameterList *TPL =
TransformTemplateParameterList(OrigTPL);
if (!TPL)
TransRetReq.emplace(createSubstDiag(SemaRef, Info,
[&] (llvm::raw_ostream& OS) {
RetReq.getTypeConstraint()->getImmediatelyDeclaredConstraint()
->printPretty(OS, nullptr, SemaRef.getPrintingPolicy());
}));
else {
TPLInst.Clear();
TransRetReq.emplace(TPL);
}
}
assert(TransRetReq && "All code paths leading here must set TransRetReq");
if (Expr *E = TransExpr.dyn_cast<Expr *>())
return RebuildExprRequirement(E, Req->isSimple(), Req->getNoexceptLoc(),
std::move(*TransRetReq));
return RebuildExprRequirement(
TransExpr.get<concepts::Requirement::SubstitutionDiagnostic *>(),
Req->isSimple(), Req->getNoexceptLoc(), std::move(*TransRetReq));
}
concepts::NestedRequirement *
TemplateInstantiator::TransformNestedRequirement(
concepts::NestedRequirement *Req) {
if (!Req->isDependent() && !AlwaysRebuild())
return Req;
if (Req->isSubstitutionFailure()) {
if (AlwaysRebuild())
return RebuildNestedRequirement(
Req->getSubstitutionDiagnostic());
return Req;
}
Sema::InstantiatingTemplate ReqInst(SemaRef,
Req->getConstraintExpr()->getBeginLoc(), Req,
Sema::InstantiatingTemplate::ConstraintsCheck{},
Req->getConstraintExpr()->getSourceRange());
ExprResult TransConstraint;
ConstraintSatisfaction Satisfaction;
TemplateDeductionInfo Info(Req->getConstraintExpr()->getBeginLoc());
{
EnterExpressionEvaluationContext ContextRAII(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
Sema::SFINAETrap Trap(SemaRef);
Sema::InstantiatingTemplate ConstrInst(SemaRef,
Req->getConstraintExpr()->getBeginLoc(), Req, Info,
Req->getConstraintExpr()->getSourceRange());
if (ConstrInst.isInvalid())
return nullptr;
TransConstraint = TransformExpr(Req->getConstraintExpr());
if (!TransConstraint.isInvalid()) {
bool CheckSucceeded =
SemaRef.CheckConstraintExpression(TransConstraint.get());
(void)CheckSucceeded;
assert((CheckSucceeded || Trap.hasErrorOccurred()) &&
"CheckConstraintExpression failed, but "
"did not produce a SFINAE error");
}
if (!TransConstraint.isInvalid() &&
!TransConstraint.get()->isInstantiationDependent() &&
!Trap.hasErrorOccurred()) {
bool CheckFailed = SemaRef.CheckConstraintSatisfaction(
TransConstraint.get(), Satisfaction);
(void)CheckFailed;
assert((!CheckFailed || Trap.hasErrorOccurred()) &&
"CheckConstraintSatisfaction failed, "
"but did not produce a SFINAE error");
}
if (TransConstraint.isInvalid() || Trap.hasErrorOccurred())
return RebuildNestedRequirement(createSubstDiag(SemaRef, Info,
[&] (llvm::raw_ostream& OS) {
Req->getConstraintExpr()->printPretty(OS, nullptr,
SemaRef.getPrintingPolicy());
}));
}
if (TransConstraint.get()->isInstantiationDependent())
return new (SemaRef.Context)
concepts::NestedRequirement(TransConstraint.get());
return new (SemaRef.Context) concepts::NestedRequirement(
SemaRef.Context, TransConstraint.get(), Satisfaction);
}
TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &Args,
SourceLocation Loc,
DeclarationName Entity,
bool AllowDeducedTST) {
assert(!CodeSynthesisContexts.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
if (!T->getType()->isInstantiationDependentType() &&
!T->getType()->isVariablyModifiedType())
return T;
TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
return AllowDeducedTST ? Instantiator.TransformTypeWithDeducedTST(T)
: Instantiator.TransformType(T);
}
TypeSourceInfo *Sema::SubstType(TypeLoc TL,
const MultiLevelTemplateArgumentList &Args,
SourceLocation Loc,
DeclarationName Entity) {
assert(!CodeSynthesisContexts.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
if (TL.getType().isNull())
return nullptr;
if (!TL.getType()->isInstantiationDependentType() &&
!TL.getType()->isVariablyModifiedType()) {
TypeLocBuilder TLB;
TLB.pushFullCopy(TL);
return TLB.getTypeSourceInfo(Context, TL.getType());
}
TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
TypeLocBuilder TLB;
TLB.reserve(TL.getFullDataSize());
QualType Result = Instantiator.TransformType(TLB, TL);
if (Result.isNull())
return nullptr;
return TLB.getTypeSourceInfo(Context, Result);
}
QualType Sema::SubstType(QualType T,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc, DeclarationName Entity) {
assert(!CodeSynthesisContexts.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
if (!T->isInstantiationDependentType() && !T->isVariablyModifiedType())
return T;
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
return Instantiator.TransformType(T);
}
static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
if (T->getType()->isInstantiationDependentType() ||
T->getType()->isVariablyModifiedType())
return true;
TypeLoc TL = T->getTypeLoc().IgnoreParens();
if (!TL.getAs<FunctionProtoTypeLoc>())
return false;
FunctionProtoTypeLoc FP = TL.castAs<FunctionProtoTypeLoc>();
for (ParmVarDecl *P : FP.getParams()) {
if (!P) continue;
return true;
}
return false;
}
TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &Args,
SourceLocation Loc,
DeclarationName Entity,
CXXRecordDecl *ThisContext,
Qualifiers ThisTypeQuals) {
assert(!CodeSynthesisContexts.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
if (!NeedsInstantiationAsFunctionType(T))
return T;
TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
TypeLocBuilder TLB;
TypeLoc TL = T->getTypeLoc();
TLB.reserve(TL.getFullDataSize());
QualType Result;
if (FunctionProtoTypeLoc Proto =
TL.IgnoreParens().getAs<FunctionProtoTypeLoc>()) {
Result = Instantiator.TransformFunctionProtoType(
TLB, Proto, ThisContext, ThisTypeQuals,
[](FunctionProtoType::ExceptionSpecInfo &ESI,
bool &Changed) { return false; });
} else {
Result = Instantiator.TransformType(TLB, TL);
}
if (Result.isNull())
return nullptr;
return TLB.getTypeSourceInfo(Context, Result);
}
bool Sema::SubstExceptionSpec(SourceLocation Loc,
FunctionProtoType::ExceptionSpecInfo &ESI,
SmallVectorImpl<QualType> &ExceptionStorage,
const MultiLevelTemplateArgumentList &Args) {
assert(ESI.Type != EST_Uninstantiated);
bool Changed = false;
TemplateInstantiator Instantiator(*this, Args, Loc, DeclarationName());
return Instantiator.TransformExceptionSpec(Loc, ESI, ExceptionStorage,
Changed);
}
void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
const MultiLevelTemplateArgumentList &Args) {
FunctionProtoType::ExceptionSpecInfo ESI =
Proto->getExtProtoInfo().ExceptionSpec;
SmallVector<QualType, 4> ExceptionStorage;
if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getEndLoc(),
ESI, ExceptionStorage, Args))
ESI.Type = EST_None;
UpdateExceptionSpec(New, ESI);
}
namespace {
struct GetContainedInventedTypeParmVisitor :
public TypeVisitor<GetContainedInventedTypeParmVisitor,
TemplateTypeParmDecl *> {
using TypeVisitor<GetContainedInventedTypeParmVisitor,
TemplateTypeParmDecl *>::Visit;
TemplateTypeParmDecl *Visit(QualType T) {
if (T.isNull())
return nullptr;
return Visit(T.getTypePtr());
}
TemplateTypeParmDecl *VisitTemplateTypeParmType(
const TemplateTypeParmType *T) {
if (!T->getDecl() || !T->getDecl()->isImplicit())
return nullptr;
return T->getDecl();
}
TemplateTypeParmDecl *VisitElaboratedType(const ElaboratedType *T) {
return Visit(T->getNamedType());
}
TemplateTypeParmDecl *VisitPointerType(const PointerType *T) {
return Visit(T->getPointeeType());
}
TemplateTypeParmDecl *VisitBlockPointerType(const BlockPointerType *T) {
return Visit(T->getPointeeType());
}
TemplateTypeParmDecl *VisitReferenceType(const ReferenceType *T) {
return Visit(T->getPointeeTypeAsWritten());
}
TemplateTypeParmDecl *VisitMemberPointerType(const MemberPointerType *T) {
return Visit(T->getPointeeType());
}
TemplateTypeParmDecl *VisitArrayType(const ArrayType *T) {
return Visit(T->getElementType());
}
TemplateTypeParmDecl *VisitDependentSizedExtVectorType(
const DependentSizedExtVectorType *T) {
return Visit(T->getElementType());
}
TemplateTypeParmDecl *VisitVectorType(const VectorType *T) {
return Visit(T->getElementType());
}
TemplateTypeParmDecl *VisitFunctionProtoType(const FunctionProtoType *T) {
return VisitFunctionType(T);
}
TemplateTypeParmDecl *VisitFunctionType(const FunctionType *T) {
return Visit(T->getReturnType());
}
TemplateTypeParmDecl *VisitParenType(const ParenType *T) {
return Visit(T->getInnerType());
}
TemplateTypeParmDecl *VisitAttributedType(const AttributedType *T) {
return Visit(T->getModifiedType());
}
TemplateTypeParmDecl *VisitMacroQualifiedType(const MacroQualifiedType *T) {
return Visit(T->getUnderlyingType());
}
TemplateTypeParmDecl *VisitAdjustedType(const AdjustedType *T) {
return Visit(T->getOriginalType());
}
TemplateTypeParmDecl *VisitPackExpansionType(const PackExpansionType *T) {
return Visit(T->getPattern());
}
};
}
bool Sema::SubstTypeConstraint(
TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
const MultiLevelTemplateArgumentList &TemplateArgs) {
const ASTTemplateArgumentListInfo *TemplArgInfo =
TC->getTemplateArgsAsWritten();
TemplateArgumentListInfo InstArgs;
if (TemplArgInfo) {
InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc);
InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc);
if (SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs,
InstArgs))
return true;
}
return AttachTypeConstraint(
TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
TC->getNamedConcept(), &InstArgs, Inst,
Inst->isParameterPack()
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
->getEllipsisLoc()
: SourceLocation());
}
ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
const MultiLevelTemplateArgumentList &TemplateArgs,
int indexAdjustment,
Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
TypeSourceInfo *NewDI = nullptr;
TypeLoc OldTL = OldDI->getTypeLoc();
if (PackExpansionTypeLoc ExpansionTL = OldTL.getAs<PackExpansionTypeLoc>()) {
NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs,
OldParm->getLocation(), OldParm->getDeclName());
if (!NewDI)
return nullptr;
if (NewDI->getType()->containsUnexpandedParameterPack()) {
NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(),
NumExpansions);
} else if (ExpectParameterPack) {
Diag(OldParm->getLocation(),
diag::err_function_parameter_pack_without_parameter_packs)
<< NewDI->getType();
return nullptr;
}
} else {
NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
OldParm->getDeclName());
}
if (!NewDI)
return nullptr;
if (NewDI->getType()->isVoidType()) {
Diag(OldParm->getLocation(), diag::err_param_with_void_type);
return nullptr;
}
if (TemplateTypeParmDecl *TTP =
GetContainedInventedTypeParmVisitor().Visit(OldDI->getType())) {
if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
auto *Inst = cast_or_null<TemplateTypeParmDecl>(
FindInstantiatedDecl(TTP->getLocation(), TTP, TemplateArgs));
if (Inst && !Inst->getTypeConstraint()) {
if (SubstTypeConstraint(Inst, TC, TemplateArgs))
return nullptr;
}
}
}
ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(),
OldParm->getInnerLocStart(),
OldParm->getLocation(),
OldParm->getIdentifier(),
NewDI->getType(), NewDI,
OldParm->getStorageClass());
if (!NewParm)
return nullptr;
if (OldParm->hasUninstantiatedDefaultArg()) {
Expr *Arg = OldParm->getUninstantiatedDefaultArg();
NewParm->setUninstantiatedDefaultArg(Arg);
} else if (OldParm->hasUnparsedDefaultArg()) {
NewParm->setUnparsedDefaultArg();
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
} else if (Expr *Arg = OldParm->getDefaultArg()) {
FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
if (OwningFunc->isInLocalScopeForInstantiation()) {
Sema::ContextRAII SavedContext(*this, OwningFunc);
LocalInstantiationScope Local(*this, true);
ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
if (NewArg.isUsable()) {
SourceLocation EqualLoc = NewArg.get()->getBeginLoc();
ExprResult Result =
ConvertParamDefaultArgument(NewParm, NewArg.get(), EqualLoc);
if (Result.isInvalid())
return nullptr;
SetParamDefaultArgument(NewParm, Result.getAs<Expr>(), EqualLoc);
}
} else {
NewParm->setUninstantiatedDefaultArg(Arg);
}
}
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
if (OldParm->isParameterPack() && !NewParm->isParameterPack()) {
CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm);
} else {
CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm);
}
NewParm->setDeclContext(CurContext);
NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
OldParm->getFunctionScopeIndex() + indexAdjustment);
InstantiateAttrs(TemplateArgs, OldParm, NewParm);
return NewParm;
}
bool Sema::SubstParmTypes(
SourceLocation Loc, ArrayRef<ParmVarDecl *> Params,
const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
const MultiLevelTemplateArgumentList &TemplateArgs,
SmallVectorImpl<QualType> &ParamTypes,
SmallVectorImpl<ParmVarDecl *> *OutParams,
ExtParameterInfoBuilder &ParamInfos) {
assert(!CodeSynthesisContexts.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
DeclarationName());
return Instantiator.TransformFunctionTypeParams(
Loc, Params, nullptr, ExtParamInfos, ParamTypes, OutParams, ParamInfos);
}
bool
Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
CXXRecordDecl *Pattern,
const MultiLevelTemplateArgumentList &TemplateArgs) {
bool Invalid = false;
SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
for (const auto &Base : Pattern->bases()) {
if (!Base.getType()->isDependentType()) {
if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) {
if (RD->isInvalidDecl())
Instantiation->setInvalidDecl();
}
InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(Base));
continue;
}
SourceLocation EllipsisLoc;
TypeSourceInfo *BaseTypeLoc;
if (Base.isPackExpansion()) {
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
collectUnexpandedParameterPacks(Base.getTypeSourceInfo()->getTypeLoc(),
Unexpanded);
bool ShouldExpand = false;
bool RetainExpansion = false;
Optional<unsigned> NumExpansions;
if (CheckParameterPacksForExpansion(Base.getEllipsisLoc(),
Base.getSourceRange(),
Unexpanded,
TemplateArgs, ShouldExpand,
RetainExpansion,
NumExpansions)) {
Invalid = true;
continue;
}
if (ShouldExpand) {
for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
TypeSourceInfo *BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
Base.getSourceRange().getBegin(),
DeclarationName());
if (!BaseTypeLoc) {
Invalid = true;
continue;
}
if (CXXBaseSpecifier *InstantiatedBase
= CheckBaseSpecifier(Instantiation,
Base.getSourceRange(),
Base.isVirtual(),
Base.getAccessSpecifierAsWritten(),
BaseTypeLoc,
SourceLocation()))
InstantiatedBases.push_back(InstantiatedBase);
else
Invalid = true;
}
continue;
}
EllipsisLoc = Base.getEllipsisLoc();
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
Base.getSourceRange().getBegin(),
DeclarationName());
} else {
BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
TemplateArgs,
Base.getSourceRange().getBegin(),
DeclarationName());
}
if (!BaseTypeLoc) {
Invalid = true;
continue;
}
if (CXXBaseSpecifier *InstantiatedBase
= CheckBaseSpecifier(Instantiation,
Base.getSourceRange(),
Base.isVirtual(),
Base.getAccessSpecifierAsWritten(),
BaseTypeLoc,
EllipsisLoc))
InstantiatedBases.push_back(InstantiatedBase);
else
Invalid = true;
}
if (!Invalid && AttachBaseSpecifiers(Instantiation, InstantiatedBases))
Invalid = true;
return Invalid;
}
namespace clang {
namespace sema {
Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S,
const MultiLevelTemplateArgumentList &TemplateArgs);
Attr *instantiateTemplateAttributeForDecl(
const Attr *At, ASTContext &C, Sema &S,
const MultiLevelTemplateArgumentList &TemplateArgs);
}
}
bool
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateSpecializationKind TSK,
bool Complain) {
CXXRecordDecl *PatternDef
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
Instantiation->getInstantiatedFromMemberClass(),
Pattern, PatternDef, TSK, Complain))
return true;
llvm::TimeTraceScope TimeScope("InstantiateClass", [&]() {
std::string Name;
llvm::raw_string_ostream OS(Name);
Instantiation->getNameForDiagnostic(OS, getPrintingPolicy(),
true);
return Name;
});
Pattern = PatternDef;
if (MemberSpecializationInfo *MSInfo
= Instantiation->getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
} else if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
Spec->setTemplateSpecializationKind(TSK);
Spec->setPointOfInstantiation(PointOfInstantiation);
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller");
PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating class definition");
ContextRAII SavedContext(*this, Instantiation);
EnterExpressionEvaluationContext EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
LocalInstantiationScope Scope(*this, MergeWithParentScope);
SavePendingParsedClassStateRAII SavedPendingParsedClassState(*this);
InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
Instantiation->startDefinition();
Instantiation->setVisibleDespiteOwningModule();
Instantiation->setTagKind(Pattern->getTagKind());
if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
Instantiation->setInvalidDecl();
TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
SmallVector<Decl*, 4> Fields;
LateInstantiatedAttrVec LateAttrs;
Instantiator.enableLateAttributeInstantiation(&LateAttrs);
bool MightHaveConstexprVirtualFunctions = false;
for (auto *Member : Pattern->decls()) {
if (Member->getDeclContext() != Pattern)
continue;
if (isa<BlockDecl>(Member) ||
(isa<CXXRecordDecl>(Member) && cast<CXXRecordDecl>(Member)->isLambda()))
continue;
if (Member->isInvalidDecl()) {
Instantiation->setInvalidDecl();
continue;
}
Decl *NewMember = Instantiator.Visit(Member);
if (NewMember) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
Fields.push_back(Field);
} else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) {
if (TSK == TSK_ImplicitInstantiation && !Enum->isScoped() &&
Enum->isCompleteDefinition()) {
MemberSpecializationInfo *MSInfo =Enum->getMemberSpecializationInfo();
assert(MSInfo && "no spec info for member enum specialization");
MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
}
} else if (StaticAssertDecl *SA = dyn_cast<StaticAssertDecl>(NewMember)) {
if (SA->isFailed()) {
Instantiation->setInvalidDecl();
break;
}
} else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewMember)) {
if (MD->isConstexpr() && !MD->getFriendObjectKind() &&
(MD->isVirtualAsWritten() || Instantiation->getNumBases()))
MightHaveConstexprVirtualFunctions = true;
}
if (NewMember->isInvalidDecl())
Instantiation->setInvalidDecl();
} else {
}
}
ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields,
SourceLocation(), SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(nullptr, Instantiation);
if (ParsingClassDepth == 0)
ActOnFinishCXXNonNestedClass();
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
E = LateAttrs.end(); I != E; ++I) {
assert(CurrentInstantiationScope == Instantiator.getStartingScope());
CurrentInstantiationScope = I->Scope;
auto *ND = cast<NamedDecl>(I->NewDecl);
auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
ND->isCXXInstanceMember());
Attr *NewAttr =
instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
if (NewAttr)
I->NewDecl->addAttr(NewAttr);
LocalInstantiationScope::deleteScopes(I->Scope,
Instantiator.getStartingScope());
}
Instantiator.disableLateAttributeInstantiation();
LateAttrs.clear();
ActOnFinishDelayedMemberInitializers(Instantiation);
if (TSK == TSK_ImplicitInstantiation) {
Instantiation->setLocation(Pattern->getLocation());
Instantiation->setLocStart(Pattern->getInnerLocStart());
Instantiation->setBraceRange(Pattern->getBraceRange());
}
if (!Instantiation->isInvalidDecl()) {
if (Pattern->isDependentContext())
PerformDependentDiagnostics(Pattern, TemplateArgs);
for (TemplateDeclInstantiator::delayed_partial_spec_iterator
P = Instantiator.delayed_partial_spec_begin(),
PEnd = Instantiator.delayed_partial_spec_end();
P != PEnd; ++P) {
if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
P->first, P->second)) {
Instantiation->setInvalidDecl();
break;
}
}
for (TemplateDeclInstantiator::delayed_var_partial_spec_iterator
P = Instantiator.delayed_var_partial_spec_begin(),
PEnd = Instantiator.delayed_var_partial_spec_end();
P != PEnd; ++P) {
if (!Instantiator.InstantiateVarTemplatePartialSpecialization(
P->first, P->second)) {
Instantiation->setInvalidDecl();
break;
}
}
}
SavedContext.pop();
if (!Instantiation->isInvalidDecl()) {
if (TSK == TSK_ExplicitInstantiationDefinition)
MarkVTableUsed(PointOfInstantiation, Instantiation, true);
else if (MightHaveConstexprVirtualFunctions)
MarkVirtualMembersReferenced(PointOfInstantiation, Instantiation,
true);
}
Consumer.HandleTagDeclDefinition(Instantiation);
return Instantiation->isInvalidDecl();
}
bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
EnumDecl *Instantiation, EnumDecl *Pattern,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateSpecializationKind TSK) {
EnumDecl *PatternDef = Pattern->getDefinition();
if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
Instantiation->getInstantiatedFromMemberEnum(),
Pattern, PatternDef, TSK,true))
return true;
Pattern = PatternDef;
if (MemberSpecializationInfo *MSInfo
= Instantiation->getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
if (Inst.isAlreadyInstantiating())
return false;
PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating enum definition");
Instantiation->setVisibleDespiteOwningModule();
ContextRAII SavedContext(*this, Instantiation);
EnterExpressionEvaluationContext EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
LocalInstantiationScope Scope(*this, true);
InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
Instantiator.InstantiateEnumDefinition(Instantiation, Pattern);
SavedContext.pop();
return Instantiation->isInvalidDecl();
}
bool Sema::InstantiateInClassInitializer(
SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!Pattern->hasInClassInitializer())
return false;
assert(Instantiation->getInClassInitStyle() ==
Pattern->getInClassInitStyle() &&
"pattern and instantiation disagree about init style");
Expr *OldInit = Pattern->getInClassInitializer();
if (!OldInit) {
RecordDecl *PatternRD = Pattern->getParent();
RecordDecl *OutermostClass = PatternRD->getOuterLexicalRecordContext();
Diag(PointOfInstantiation,
diag::err_default_member_initializer_not_yet_parsed)
<< OutermostClass << Pattern;
Diag(Pattern->getEndLoc(),
diag::note_default_member_initializer_not_yet_parsed);
Instantiation->setInvalidDecl();
return true;
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
if (Inst.isAlreadyInstantiating()) {
Diag(PointOfInstantiation, diag::err_default_member_initializer_cycle)
<< Instantiation;
return true;
}
PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
"instantiating default member init");
ContextRAII SavedContext(*this, Instantiation->getParent());
EnterExpressionEvaluationContext EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
LocalInstantiationScope Scope(*this, true);
ActOnStartCXXInClassMemberInitializer();
CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), Qualifiers());
ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
false);
Expr *Init = NewInit.get();
assert((!Init || !isa<ParenListExpr>(Init)) && "call-style init in class");
ActOnFinishCXXInClassMemberInitializer(
Instantiation, Init ? Init->getBeginLoc() : SourceLocation(), Init);
if (auto *L = getASTMutationListener())
L->DefaultMemberInitializerInstantiated(Instantiation);
return !Instantiation->getInClassInitializer();
}
namespace {
struct PartialSpecMatchResult {
ClassTemplatePartialSpecializationDecl *Partial;
TemplateArgumentList *Args;
};
}
bool Sema::usesPartialOrExplicitSpecialization(
SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec) {
if (ClassTemplateSpec->getTemplateSpecializationKind() ==
TSK_ExplicitSpecialization)
return true;
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
ClassTemplateSpec->getSpecializedTemplate()
->getPartialSpecializations(PartialSpecs);
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
TemplateDeductionInfo Info(Loc);
if (!DeduceTemplateArguments(PartialSpecs[I],
ClassTemplateSpec->getTemplateArgs(), Info))
return true;
}
return false;
}
static ActionResult<CXXRecordDecl *>
getPatternForClassTemplateSpecialization(
Sema &S, SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK) {
Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
if (Inst.isInvalid())
return {true};
if (Inst.isAlreadyInstantiating())
return {false};
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
if (!Specialized.is<ClassTemplatePartialSpecializationDecl *>()) {
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
typedef PartialSpecMatchResult MatchResult;
SmallVector<MatchResult, 4> Matched;
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
Template->getPartialSpecializations(PartialSpecs);
TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(
Partial, ClassTemplateSpec->getTemplateArgs(), Info)) {
FailedCandidates.addCandidate().set(
DeclAccessPair::make(Template, AS_public), Partial,
MakeDeductionFailureInfo(S.Context, Result, Info));
(void)Result;
} else {
Matched.push_back(PartialSpecMatchResult());
Matched.back().Partial = Partial;
Matched.back().Args = Info.take();
}
}
if (Matched.size() >= 1) {
SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
if (Matched.size() == 1) {
} else {
for (SmallVectorImpl<MatchResult>::iterator P = Best + 1,
PEnd = Matched.end();
P != PEnd; ++P) {
if (S.getMoreSpecializedPartialSpecialization(
P->Partial, Best->Partial, PointOfInstantiation) ==
P->Partial)
Best = P;
}
bool Ambiguous = false;
for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
PEnd = Matched.end();
P != PEnd; ++P) {
if (P != Best && S.getMoreSpecializedPartialSpecialization(
P->Partial, Best->Partial,
PointOfInstantiation) != Best->Partial) {
Ambiguous = true;
break;
}
}
if (Ambiguous) {
Inst.Clear();
ClassTemplateSpec->setInvalidDecl();
S.Diag(PointOfInstantiation,
diag::err_partial_spec_ordering_ambiguous)
<< ClassTemplateSpec;
for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
PEnd = Matched.end();
P != PEnd; ++P)
S.Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
<< S.getTemplateArgumentBindingsText(
P->Partial->getTemplateParameters(), *P->Args);
return {true};
}
}
ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
} else {
}
}
CXXRecordDecl *Pattern = nullptr;
Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
if (auto *PartialSpec =
Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
while (PartialSpec->getInstantiatedFromMember()) {
if (PartialSpec->isMemberSpecialization())
break;
PartialSpec = PartialSpec->getInstantiatedFromMember();
}
Pattern = PartialSpec;
} else {
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
while (Template->getInstantiatedFromMemberTemplate()) {
if (Template->isMemberSpecialization())
break;
Template = Template->getInstantiatedFromMemberTemplate();
}
Pattern = Template->getTemplatedDecl();
}
return Pattern;
}
bool Sema::InstantiateClassTemplateSpecialization(
SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK, bool Complain) {
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
ClassTemplateSpec->getCanonicalDecl());
if (ClassTemplateSpec->isInvalidDecl())
return true;
ActionResult<CXXRecordDecl *> Pattern =
getPatternForClassTemplateSpecialization(*this, PointOfInstantiation,
ClassTemplateSpec, TSK);
if (!Pattern.isUsable())
return Pattern.isInvalid();
return InstantiateClass(
PointOfInstantiation, ClassTemplateSpec, Pattern.get(),
getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain);
}
void
Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateSpecializationKind TSK) {
assert(
(TSK == TSK_ExplicitInstantiationDefinition ||
TSK == TSK_ExplicitInstantiationDeclaration ||
(TSK == TSK_ImplicitInstantiation && Instantiation->isLocalClass())) &&
"Unexpected template specialization kind!");
for (auto *D : Instantiation->decls()) {
bool SuppressNew = false;
if (auto *Function = dyn_cast<FunctionDecl>(D)) {
if (FunctionDecl *Pattern =
Function->getInstantiatedFromMemberFunction()) {
if (Function->isIneligibleOrNotSelected())
continue;
if (Function->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (CheckFunctionConstraints(Function, Satisfaction) ||
!Satisfaction.IsSatisfied) {
continue;
}
}
if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
MemberSpecializationInfo *MSInfo =
Function->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
if (MSInfo->getTemplateSpecializationKind()
== TSK_ExplicitSpecialization)
continue;
if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
Function,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
SuppressNew) ||
SuppressNew)
continue;
if (TSK == TSK_ExplicitInstantiationDefinition && !Pattern->isDefined())
continue;
Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
if (Function->isDefined()) {
Consumer.HandleTopLevelDecl(DeclGroupRef(Function));
} else if (TSK == TSK_ExplicitInstantiationDefinition) {
InstantiateFunctionDefinition(PointOfInstantiation, Function);
} else if (TSK == TSK_ImplicitInstantiation) {
PendingLocalImplicitInstantiations.push_back(
std::make_pair(Function, PointOfInstantiation));
}
}
} else if (auto *Var = dyn_cast<VarDecl>(D)) {
if (isa<VarTemplateSpecializationDecl>(Var))
continue;
if (Var->isStaticDataMember()) {
if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
if (MSInfo->getTemplateSpecializationKind()
== TSK_ExplicitSpecialization)
continue;
if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
Var,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
SuppressNew) ||
SuppressNew)
continue;
if (TSK == TSK_ExplicitInstantiationDefinition) {
if (!Var->getInstantiatedFromStaticDataMember()->getDefinition())
continue;
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
InstantiateVariableDefinition(PointOfInstantiation, Var);
} else {
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
}
} else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
if (Record->isInjectedClassName() || Record->getPreviousDecl() ||
Record->isLambda())
continue;
MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
if (MSInfo->getTemplateSpecializationKind()
== TSK_ExplicitSpecialization)
continue;
if (Context.getTargetInfo().getTriple().isOSWindows() &&
TSK == TSK_ExplicitInstantiationDeclaration) {
continue;
}
if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
Record,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
SuppressNew) ||
SuppressNew)
continue;
CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
assert(Pattern && "Missing instantiated-from-template information");
if (!Record->getDefinition()) {
if (!Pattern->getDefinition()) {
if (TSK == TSK_ExplicitInstantiationDeclaration) {
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
}
continue;
}
InstantiateClass(PointOfInstantiation, Record, Pattern,
TemplateArgs,
TSK);
} else {
if (TSK == TSK_ExplicitInstantiationDefinition &&
Record->getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDeclaration) {
Record->setTemplateSpecializationKind(TSK);
MarkVTableUsed(PointOfInstantiation, Record, true);
}
}
Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition());
if (Pattern)
InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
TSK);
} else if (auto *Enum = dyn_cast<EnumDecl>(D)) {
MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
if (MSInfo->getTemplateSpecializationKind()
== TSK_ExplicitSpecialization)
continue;
if (CheckSpecializationInstantiationRedecl(
PointOfInstantiation, TSK, Enum,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(), SuppressNew) ||
SuppressNew)
continue;
if (Enum->getDefinition())
continue;
EnumDecl *Pattern = Enum->getTemplateInstantiationPattern();
assert(Pattern && "Missing instantiated-from-template information");
if (TSK == TSK_ExplicitInstantiationDefinition) {
if (!Pattern->getDefinition())
continue;
InstantiateEnum(PointOfInstantiation, Enum, Pattern, TemplateArgs, TSK);
} else {
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
}
} else if (auto *Field = dyn_cast<FieldDecl>(D)) {
if (Field->hasInClassInitializer() && TSK == TSK_ImplicitInstantiation) {
CXXRecordDecl *ClassPattern =
Instantiation->getTemplateInstantiationPattern();
DeclContext::lookup_result Lookup =
ClassPattern->lookup(Field->getDeclName());
FieldDecl *Pattern = Lookup.find_first<FieldDecl>();
assert(Pattern);
InstantiateInClassInitializer(PointOfInstantiation, Field, Pattern,
TemplateArgs);
}
}
}
}
void
Sema::InstantiateClassTemplateSpecializationMembers(
SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK) {
InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
getTemplateInstantiationArgs(ClassTemplateSpec),
TSK);
}
StmtResult
Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!S)
return S;
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
DeclarationName());
return Instantiator.TransformStmt(S);
}
bool Sema::SubstTemplateArguments(
ArrayRef<TemplateArgumentLoc> Args,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateArgumentListInfo &Out) {
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
DeclarationName());
return Instantiator.TransformTemplateArguments(Args.begin(), Args.end(),
Out);
}
ExprResult
Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!E)
return E;
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
DeclarationName());
return Instantiator.TransformExpr(E);
}
ExprResult Sema::SubstInitializer(Expr *Init,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool CXXDirectInit) {
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
DeclarationName());
return Instantiator.TransformInitializer(Init, CXXDirectInit);
}
bool Sema::SubstExprs(ArrayRef<Expr *> Exprs, bool IsCall,
const MultiLevelTemplateArgumentList &TemplateArgs,
SmallVectorImpl<Expr *> &Outputs) {
if (Exprs.empty())
return false;
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
DeclarationName());
return Instantiator.TransformExprs(Exprs.data(), Exprs.size(),
IsCall, Outputs);
}
NestedNameSpecifierLoc
Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!NNS)
return NestedNameSpecifierLoc();
TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(),
DeclarationName());
return Instantiator.TransformNestedNameSpecifierLoc(NNS);
}
DeclarationNameInfo
Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, NameInfo.getLoc(),
NameInfo.getName());
return Instantiator.TransformDeclarationNameInfo(NameInfo);
}
TemplateName
Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc,
TemplateName Name, SourceLocation Loc,
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
DeclarationName());
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
return Instantiator.TransformTemplateName(SS, Name, Loc);
}
static const Decl *getCanonicalParmVarDecl(const Decl *D) {
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(D)) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
unsigned i = PV->getFunctionScopeIndex();
if (i < FD->getNumParams() && FD->getParamDecl(i) == PV)
return FD->getCanonicalDecl()->getParamDecl(i);
}
}
return D;
}
llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
LocalInstantiationScope::findInstantiationOf(const Decl *D) {
D = getCanonicalParmVarDecl(D);
for (LocalInstantiationScope *Current = this; Current;
Current = Current->Outer) {
const Decl *CheckD = D;
do {
LocalDeclsMap::iterator Found = Current->LocalDecls.find(CheckD);
if (Found != Current->LocalDecls.end())
return &Found->second;
if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
CheckD = Tag->getPreviousDecl();
else
CheckD = nullptr;
} while (CheckD);
if (!Current->CombineWithOuterScope)
break;
}
if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
isa<TemplateTemplateParmDecl>(D))
return nullptr;
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
if (RD->isLocalClass())
return nullptr;
if (isa<EnumDecl>(D))
return nullptr;
if (isa<TypedefNameDecl>(D) &&
isa<CXXDeductionGuideDecl>(D->getDeclContext()))
return nullptr;
assert(isa<LabelDecl>(D) && "declaration not instantiated in this scope");
return nullptr;
}
void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
D = getCanonicalParmVarDecl(D);
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
if (Stored.isNull()) {
#ifndef NDEBUG
LocalInstantiationScope *Current = this;
while (Current->CombineWithOuterScope && Current->Outer) {
Current = Current->Outer;
assert(Current->LocalDecls.find(D) == Current->LocalDecls.end() &&
"Instantiated local in inner and outer scopes");
}
#endif
Stored = Inst;
} else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>()) {
Pack->push_back(cast<VarDecl>(Inst));
} else {
assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
}
}
void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
VarDecl *Inst) {
D = getCanonicalParmVarDecl(D);
DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>();
Pack->push_back(Inst);
}
void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) {
#ifndef NDEBUG
for (LocalInstantiationScope *Current = this;
Current && Current->CombineWithOuterScope; Current = Current->Outer)
assert(Current->LocalDecls.find(D) == Current->LocalDecls.end() &&
"Creating local pack after instantiation of local");
#endif
D = getCanonicalParmVarDecl(D);
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
DeclArgumentPack *Pack = new DeclArgumentPack;
Stored = Pack;
ArgumentPacks.push_back(Pack);
}
bool LocalInstantiationScope::isLocalPackExpansion(const Decl *D) {
for (DeclArgumentPack *Pack : ArgumentPacks)
if (llvm::is_contained(*Pack, D))
return true;
return false;
}
void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack,
const TemplateArgument *ExplicitArgs,
unsigned NumExplicitArgs) {
assert((!PartiallySubstitutedPack || PartiallySubstitutedPack == Pack) &&
"Already have a partially-substituted pack");
assert((!PartiallySubstitutedPack
|| NumArgsInPartiallySubstitutedPack == NumExplicitArgs) &&
"Wrong number of arguments in partially-substituted pack");
PartiallySubstitutedPack = Pack;
ArgsInPartiallySubstitutedPack = ExplicitArgs;
NumArgsInPartiallySubstitutedPack = NumExplicitArgs;
}
NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
const TemplateArgument **ExplicitArgs,
unsigned *NumExplicitArgs) const {
if (ExplicitArgs)
*ExplicitArgs = nullptr;
if (NumExplicitArgs)
*NumExplicitArgs = 0;
for (const LocalInstantiationScope *Current = this; Current;
Current = Current->Outer) {
if (Current->PartiallySubstitutedPack) {
if (ExplicitArgs)
*ExplicitArgs = Current->ArgsInPartiallySubstitutedPack;
if (NumExplicitArgs)
*NumExplicitArgs = Current->NumArgsInPartiallySubstitutedPack;
return Current->PartiallySubstitutedPack;
}
if (!Current->CombineWithOuterScope)
break;
}
return nullptr;
}