mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
Push parameters into the local instantiation scope before instantiating
a default argument. Default arguments can (after recent language changes) refer to parameters of the same function. Make sure they're added to the local instantiation scope before transforming a default argument so that we can remap such references to them properly.
This commit is contained in:
parent
7462793be7
commit
a5569f0898
@ -2618,7 +2618,13 @@ public:
|
||||
/// Retrieve the function declaration from which this function could
|
||||
/// be instantiated, if it is an instantiation (rather than a non-template
|
||||
/// or a specialization, for example).
|
||||
FunctionDecl *getTemplateInstantiationPattern() const;
|
||||
///
|
||||
/// If \p ForDefinition is \c false, explicit specializations will be treated
|
||||
/// as if they were implicit instantiations. This will then find the pattern
|
||||
/// corresponding to non-definition portions of the declaration, such as
|
||||
/// default arguments and the exception specification.
|
||||
FunctionDecl *
|
||||
getTemplateInstantiationPattern(bool ForDefinition = true) const;
|
||||
|
||||
/// Retrieve the primary template that this function template
|
||||
/// specialization either specializes or was instantiated from.
|
||||
|
@ -3623,7 +3623,8 @@ bool FunctionDecl::isTemplateInstantiation() const {
|
||||
return clang::isTemplateInstantiation(getTemplateSpecializationKind());
|
||||
}
|
||||
|
||||
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
|
||||
FunctionDecl *
|
||||
FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
|
||||
// If this is a generic lambda call operator specialization, its
|
||||
// instantiation pattern is always its primary template's pattern
|
||||
// even if its primary template was instantiated from another
|
||||
@ -3640,18 +3641,20 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
|
||||
}
|
||||
|
||||
if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) {
|
||||
if (!clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
|
||||
if (ForDefinition &&
|
||||
!clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
|
||||
return nullptr;
|
||||
return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom()));
|
||||
}
|
||||
|
||||
if (!clang::isTemplateInstantiation(getTemplateSpecializationKind()))
|
||||
if (ForDefinition &&
|
||||
!clang::isTemplateInstantiation(getTemplateSpecializationKind()))
|
||||
return nullptr;
|
||||
|
||||
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
|
||||
// If we hit a point where the user provided a specialization of this
|
||||
// template, we're done looking.
|
||||
while (!Primary->isMemberSpecialization()) {
|
||||
while (!ForDefinition || !Primary->isMemberSpecialization()) {
|
||||
auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
|
||||
if (!NewPrimary)
|
||||
break;
|
||||
|
@ -4273,6 +4273,13 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
|
||||
// default argument expression appears.
|
||||
ContextRAII SavedContext(*this, FD);
|
||||
LocalInstantiationScope Local(*this);
|
||||
|
||||
FunctionDecl *Pattern = FD->getTemplateInstantiationPattern(
|
||||
/*ForDefinition*/ false);
|
||||
if (addInstantiatedParametersToScope(*this, FD, Pattern, Local,
|
||||
TemplateArgs))
|
||||
return true;
|
||||
|
||||
runWithSufficientStackSpace(CallLoc, [&] {
|
||||
Result = SubstInitializer(UninstExpr, TemplateArgs,
|
||||
/*DirectInit*/false);
|
||||
@ -4338,6 +4345,10 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
|
||||
MultiLevelTemplateArgumentList TemplateArgs =
|
||||
getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
|
||||
|
||||
// FIXME: We can't use getTemplateInstantiationPattern(false) in general
|
||||
// here, because for a non-defining friend declaration in a class template,
|
||||
// we don't store enough information to map back to the friend declaration in
|
||||
// the template.
|
||||
FunctionDecl *Template = Proto->getExceptionSpecTemplate();
|
||||
if (addInstantiatedParametersToScope(*this, Decl, Template, Scope,
|
||||
TemplateArgs)) {
|
||||
|
@ -116,6 +116,11 @@ namespace rdar34167492 {
|
||||
};
|
||||
}
|
||||
|
||||
namespace use_of_earlier_param {
|
||||
template<typename T> void f(T a, int = decltype(a)());
|
||||
void g() { f(0); }
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
namespace lambda {
|
||||
// Verify that a default argument in a lambda can refer to the type of a
|
||||
|
Loading…
Reference in New Issue
Block a user