Changeset View
Standalone View
clang/lib/Sema/SemaTemplateInstantiate.cpp
Show First 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
/// template specializations. | /// template specializations. | ||||
/// | /// | ||||
/// \param Pattern If non-NULL, indicates the pattern from which we will be | /// \param Pattern If non-NULL, indicates the pattern from which we will be | ||||
/// instantiating the definition of the given declaration, \p D. This is | /// instantiating the definition of the given declaration, \p D. This is | ||||
/// used to determine the proper set of template instantiation arguments for | /// used to determine the proper set of template instantiation arguments for | ||||
/// friend function template specializations. | /// friend function template specializations. | ||||
MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( | MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( | ||||
const NamedDecl *D, const TemplateArgumentList *Innermost, | const NamedDecl *D, const TemplateArgumentList *Innermost, | ||||
bool RelativeToPrimary, const FunctionDecl *Pattern) { | bool RelativeToPrimary, const FunctionDecl *Pattern, | ||||
Lint: Pre-merge checks: clang-format: please reformat the code
```
- bool RelativeToPrimary, const FunctionDecl… | |||||
bool LookBeyondLambda, bool IncludeContainingStructArgs) { | |||||
// Accumulate the set of template argument lists in this structure. | // Accumulate the set of template argument lists in this structure. | ||||
Would you elaborate more for LookBeyondLambda and IncludeContainingStructArgs? It confuses me since I couldn't find Lambda or Struct from the context of use point. ChuanqiXu: Would you elaborate more for `LookBeyondLambda` and `IncludeContainingStructArgs`? It confuses… | |||||
Sure! So this function is typically used for 'getting the template instantiation args' of the current Declaration (D) for a variety of reasons. In all of those cases previously, it would 'stop' looking when it hit a lambda generic call operator (see line 157). This would block our ability to get the full instantiation tree. Similarly, it would stop at a containing class-template (as most instantiations are done against the parent class template). Unfortunately this is sufficient, so the IncludeContainingStructArgs (see line 185) ALSO includes those arguments, as they are necessary (since they haven't been instantiated in the constraint yet). erichkeane: Sure!
So this function is typically used for 'getting the template instantiation args' of… | |||||
I got it. It might be necessary to edit the comment too. ChuanqiXu: I got it. It might be necessary to edit the comment too. | |||||
MultiLevelTemplateArgumentList Result; | MultiLevelTemplateArgumentList Result; | ||||
if (Innermost) | if (Innermost) | ||||
Result.addOuterTemplateArguments(Innermost); | Result.addOuterTemplateArguments(Innermost); | ||||
const auto *Ctx = dyn_cast<DeclContext>(D); | const auto *Ctx = dyn_cast<DeclContext>(D); | ||||
if (!Ctx) { | if (!Ctx) { | ||||
Ctx = D->getDeclContext(); | Ctx = D->getDeclContext(); | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | else if (const auto *Function = dyn_cast<FunctionDecl>(Ctx)) { | ||||
// If this function was instantiated from a specialized member that is | // If this function was instantiated from a specialized member that is | ||||
// a function template, we're done. | // a function template, we're done. | ||||
assert(Function->getPrimaryTemplate() && "No function template?"); | assert(Function->getPrimaryTemplate() && "No function template?"); | ||||
if (Function->getPrimaryTemplate()->isMemberSpecialization()) | if (Function->getPrimaryTemplate()->isMemberSpecialization()) | ||||
break; | break; | ||||
// If this function is a generic lambda specialization, we are done. | // If this function is a generic lambda specialization, we are done. | ||||
if (isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) | if (!LookBeyondLambda && | ||||
isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) | |||||
break; | break; | ||||
} else if (Function->getDescribedFunctionTemplate()) { | } else if (Function->getDescribedFunctionTemplate()) { | ||||
assert(Result.getNumSubstitutedLevels() == 0 && | assert((IncludeContainingStructArgs || | ||||
Result.getNumSubstitutedLevels() == 0) && | |||||
"Outer template not instantiated?"); | "Outer template not instantiated?"); | ||||
} | } | ||||
// If this is a friend declaration and it declares an entity at | // If this is a friend declaration and it declares an entity at | ||||
// namespace scope, take arguments from its lexical parent | // namespace scope, take arguments from its lexical parent | ||||
// instead of its semantic parent, unless of course the pattern we're | // instead of its semantic parent, unless of course the pattern we're | ||||
// instantiating actually comes from the file's context! | // instantiating actually comes from the file's context! | ||||
if (Function->getFriendObjectKind() && | if (Function->getFriendObjectKind() && | ||||
Function->getDeclContext()->isFileContext() && | Function->getDeclContext()->isFileContext() && | ||||
(!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) { | (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) { | ||||
Ctx = Function->getLexicalDeclContext(); | Ctx = Function->getLexicalDeclContext(); | ||||
RelativeToPrimary = false; | RelativeToPrimary = false; | ||||
continue; | continue; | ||||
} | } | ||||
} else if (const auto *Rec = dyn_cast<CXXRecordDecl>(Ctx)) { | } else if (const auto *Rec = dyn_cast<CXXRecordDecl>(Ctx)) { | ||||
if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { | if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { | ||||
assert(Result.getNumSubstitutedLevels() == 0 && | assert((IncludeContainingStructArgs || | ||||
Result.getNumSubstitutedLevels() == 0) && | |||||
"Outer template not instantiated?"); | "Outer template not instantiated?"); | ||||
if (ClassTemplate->isMemberSpecialization()) | if (ClassTemplate->isMemberSpecialization()) | ||||
break; | break; | ||||
if (IncludeContainingStructArgs) { | |||||
QualType RecordType = Context.getTypeDeclType(Rec); | |||||
QualType Injected = cast<InjectedClassNameType>(RecordType) | |||||
->getInjectedSpecializationType(); | |||||
const auto *InjectedType = cast<TemplateSpecializationType>(Injected); | |||||
Result.addOuterTemplateArguments(InjectedType->template_arguments()); | |||||
} | |||||
} | } | ||||
} | } | ||||
Ctx = Ctx->getParent(); | Ctx = Ctx->getParent(); | ||||
RelativeToPrimary = false; | RelativeToPrimary = false; | ||||
} | } | ||||
return Result; | return Result; | ||||
▲ Show 20 Lines • Show All 2,110 Lines • ▼ Show 20 Lines | |||||
} // namespace | } // namespace | ||||
bool Sema::SubstTypeConstraint( | bool Sema::SubstTypeConstraint( | ||||
TemplateTypeParmDecl *Inst, const TypeConstraint *TC, | TemplateTypeParmDecl *Inst, const TypeConstraint *TC, | ||||
const MultiLevelTemplateArgumentList &TemplateArgs) { | const MultiLevelTemplateArgumentList &TemplateArgs) { | ||||
const ASTTemplateArgumentListInfo *TemplArgInfo = | const ASTTemplateArgumentListInfo *TemplArgInfo = | ||||
TC->getTemplateArgsAsWritten(); | TC->getTemplateArgsAsWritten(); | ||||
// If we're not checking a constraint, we shouldn't be instantiating the type | |||||
// constraint, so we should just create a copy of the previous one. | |||||
if (!IsEvaluatingAConstraint()) { | |||||
I'm still not sure if anything should be rebuilt here, I suspect the answer is MAYBE on the named-concept, but it isn't clear to me. erichkeane: I'm still not sure if anything should be rebuilt here, I suspect the answer is MAYBE on the… | |||||
Inst->setTypeConstraint(TC->getNestedNameSpecifierLoc(), | |||||
TC->getConceptNameInfo(), TC->getNamedConcept(), | |||||
TC->getNamedConcept(), TemplArgInfo, | |||||
TC->getImmediatelyDeclaredConstraint()); | |||||
return false; | |||||
} | |||||
TemplateArgumentListInfo InstArgs; | TemplateArgumentListInfo InstArgs; | ||||
if (TemplArgInfo) { | if (TemplArgInfo) { | ||||
InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); | InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); | ||||
InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); | InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); | ||||
if (SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs, | if (SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs, | ||||
InstArgs)) | InstArgs)) | ||||
return true; | return true; | ||||
▲ Show 20 Lines • Show All 1,168 Lines • ▼ Show 20 Lines | if (!E) | ||||
return E; | return E; | ||||
TemplateInstantiator Instantiator(*this, TemplateArgs, | TemplateInstantiator Instantiator(*this, TemplateArgs, | ||||
SourceLocation(), | SourceLocation(), | ||||
DeclarationName()); | DeclarationName()); | ||||
return Instantiator.TransformExpr(E); | return Instantiator.TransformExpr(E); | ||||
} | } | ||||
ExprResult | |||||
Sema::SubstConstraintExpr(Expr *E, | |||||
const MultiLevelTemplateArgumentList &TemplateArgs) { | |||||
ConstraintEvalRAII EvalRAII(*this); | |||||
return SubstExpr(E, TemplateArgs); | |||||
} | |||||
ExprResult Sema::SubstInitializer(Expr *Init, | ExprResult Sema::SubstInitializer(Expr *Init, | ||||
const MultiLevelTemplateArgumentList &TemplateArgs, | const MultiLevelTemplateArgumentList &TemplateArgs, | ||||
bool CXXDirectInit) { | bool CXXDirectInit) { | ||||
TemplateInstantiator Instantiator(*this, TemplateArgs, | TemplateInstantiator Instantiator(*this, TemplateArgs, | ||||
SourceLocation(), | SourceLocation(), | ||||
DeclarationName()); | DeclarationName()); | ||||
return Instantiator.TransformInitializer(Init, CXXDirectInit); | return Instantiator.TransformInitializer(Init, CXXDirectInit); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 207 Lines • Show Last 20 Lines |
clang-format: please reformat the code