SmallVectorImpl<QualType> &ParamTypes,
SmallVectorImpl<ParmVarDecl *> *OutParams,
ExtParameterInfoBuilder &ParamInfos);
+ bool SubstDefaultArgument(SourceLocation Loc, ParmVarDecl *Param,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool ForCallExpr = false);
ExprResult SubstExpr(Expr *E,
const MultiLevelTemplateArgumentList &TemplateArgs);
bool Decl::isTemplated() const {
// A declaration is templated if it is a template or a template pattern, or
- // is within (lexcially for a friend, semantically otherwise) a dependent
- // context.
- // FIXME: Should local extern declarations be treated like friends?
+ // is within (lexcially for a friend or local function declaration,
+ // semantically otherwise) a dependent context.
if (auto *AsDC = dyn_cast<DeclContext>(this))
return AsDC->isDependentContext();
- auto *DC = getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext();
+ auto *DC = getFriendObjectKind() || isLocalExternDecl()
+ ? getLexicalDeclContext() : getDeclContext();
return DC->isDependentContext() || isTemplateDecl() ||
getDescribedTemplateParams();
}
(ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
"Outer template not instantiated?");
}
- // If this is a friend declaration and it declares an entity at
+ // If this is a friend or local declaration and it declares an entity at
// namespace scope, take arguments from its lexical parent
// instead of its semantic parent, unless of course the pattern we're
// instantiating actually comes from the file's context!
- if (Function->getFriendObjectKind() &&
+ if ((Function->getFriendObjectKind() || Function->isLocalExternDecl()) &&
Function->getNonTransparentDeclContext()->isFileContext() &&
(!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) {
return Response::ChangeDecl(Function->getLexicalDeclContext());
ExprResult TransformLambdaExpr(LambdaExpr *E) {
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this);
- ExprResult Res = inherited::TransformLambdaExpr(E);
- return Res;
+ ExprResult Result = inherited::TransformLambdaExpr(E);
+ if (Result.isInvalid())
+ return Result;
+
+ CXXMethodDecl *MD = Result.getAs<LambdaExpr>()->getCallOperator();
+ for (ParmVarDecl *PVD : MD->parameters()) {
+ if (!PVD->hasDefaultArg())
+ continue;
+ Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
+ // FIXME: Obtain the source location for the '=' token.
+ SourceLocation EqualLoc = UninstExpr->getBeginLoc();
+ if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
+ // If substitution fails, the default argument is set to a
+ // RecoveryExpr that wraps the uninstantiated default argument so
+ // that downstream diagnostics are omitted.
+ ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
+ UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(),
+ { UninstExpr }, UninstExpr->getType());
+ if (ErrorResult.isUsable())
+ PVD->setDefaultArg(ErrorResult.get());
+ }
+ }
+
+ return Result;
}
ExprResult TransformRequiresExpr(RequiresExpr *E) {
NewParm->setUnparsedDefaultArg();
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
} else if (Expr *Arg = OldParm->getDefaultArg()) {
- FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
- if (OwningFunc->isInLocalScopeForInstantiation()) {
- // Instantiate default arguments for methods of local classes (DR1484)
- // and non-defining declarations.
- Sema::ContextRAII SavedContext(*this, OwningFunc);
- LocalInstantiationScope Local(*this, true);
- ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
- if (NewArg.isUsable()) {
- // It would be nice if we still had this.
- SourceLocation EqualLoc = NewArg.get()->getBeginLoc();
- ExprResult Result =
- ConvertParamDefaultArgument(NewParm, NewArg.get(), EqualLoc);
- if (Result.isInvalid())
- return nullptr;
-
- SetParamDefaultArgument(NewParm, Result.getAs<Expr>(), EqualLoc);
- }
- } else {
- // FIXME: if we non-lazily instantiated non-dependent default args for
- // non-dependent parameter types we could remove a bunch of duplicate
- // conversion warnings for such arguments.
- NewParm->setUninstantiatedDefaultArg(Arg);
- }
+ // Default arguments cannot be substituted until the declaration context
+ // for the associated function or lambda capture class is available.
+ // This is necessary for cases like the following where construction of
+ // the lambda capture class for the outer lambda is dependent on the
+ // parameter types but where the default argument is dependent on the
+ // outer lambda's declaration context.
+ // template <typename T>
+ // auto f() {
+ // return [](T = []{ return T{}; }()) { return 0; };
+ // }
+ NewParm->setUninstantiatedDefaultArg(Arg);
}
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
Loc, Params, nullptr, ExtParamInfos, ParamTypes, OutParams, ParamInfos);
}
+/// Substitute the given template arguments into the default argument.
+bool Sema::SubstDefaultArgument(
+ SourceLocation Loc,
+ ParmVarDecl *Param,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool ForCallExpr) {
+ FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
+ Expr *PatternExpr = Param->getUninstantiatedDefaultArg();
+
+ EnterExpressionEvaluationContext EvalContext(
+ *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param);
+
+ InstantiatingTemplate Inst(*this, Loc, Param, TemplateArgs.getInnermost());
+ if (Inst.isInvalid())
+ return true;
+ if (Inst.isAlreadyInstantiating()) {
+ Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
+ Param->setInvalidDecl();
+ return true;
+ }
+
+ ExprResult Result;
+ {
+ // C++ [dcl.fct.default]p5:
+ // The names in the [default argument] expression are bound, and
+ // the semantic constraints are checked, at the point where the
+ // default argument expression appears.
+ ContextRAII SavedContext(*this, FD);
+ std::unique_ptr<LocalInstantiationScope> LIS;
+
+ if (ForCallExpr) {
+ // When instantiating a default argument due to use in a call expression,
+ // an instantiation scope that includes the parameters of the callee is
+ // required to satisfy references from the default argument. For example:
+ // template<typename T> void f(T a, int = decltype(a)());
+ // void g() { f(0); }
+ LIS = std::make_unique<LocalInstantiationScope>(*this);
+ FunctionDecl *PatternFD = FD->getTemplateInstantiationPattern(
+ /*ForDefinition*/ false);
+ if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
+ return true;
+ }
+
+ runWithSufficientStackSpace(Loc, [&] {
+ Result = SubstInitializer(PatternExpr, TemplateArgs,
+ /*DirectInit*/false);
+ });
+ }
+ if (Result.isInvalid())
+ return true;
+
+ if (ForCallExpr) {
+ // Check the expression as an initializer for the parameter.
+ InitializedEntity Entity
+ = InitializedEntity::InitializeParameter(Context, Param);
+ InitializationKind Kind = InitializationKind::CreateCopy(
+ Param->getLocation(),
+ /*FIXME:EqualLoc*/ PatternExpr->getBeginLoc());
+ Expr *ResultE = Result.getAs<Expr>();
+
+ InitializationSequence InitSeq(*this, Entity, Kind, ResultE);
+ Result = InitSeq.Perform(*this, Entity, Kind, ResultE);
+ if (Result.isInvalid())
+ return true;
+
+ Result =
+ ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(),
+ /*DiscardedValue*/ false);
+ } else {
+ // FIXME: Obtain the source location for the '=' token.
+ SourceLocation EqualLoc = PatternExpr->getBeginLoc();
+ Result = ConvertParamDefaultArgument(Param, Result.getAs<Expr>(), EqualLoc);
+ }
+ if (Result.isInvalid())
+ return true;
+
+ // Remember the instantiated default argument.
+ Param->setDefaultArg(Result.getAs<Expr>());
+
+ return false;
+}
+
/// Perform substitution on the base class specifiers of the
/// given class template specialization.
///
/// Normal class members are of more specific types and therefore
/// don't make it here. This function serves three purposes:
/// 1) instantiating function templates
-/// 2) substituting friend declarations
+/// 2) substituting friend and local function declarations
/// 3) substituting deduction guide declarations for nested class templates
Decl *TemplateDeclInstantiator::VisitFunctionDecl(
FunctionDecl *D, TemplateParameterList *TemplateParams,
assert(D->getDeclContext()->isFileContext());
LexicalDC = D->getDeclContext();
}
+ else if (D->isLocalExternDecl()) {
+ LexicalDC = SemaRef.CurContext;
+ }
Function->setLexicalDeclContext(LexicalDC);
QualifierLoc.hasQualifier());
}
+ // Per [temp.inst], default arguments in function declarations at local scope
+ // are instantiated along with the enclosing declaration. For example:
+ //
+ // template<typename T>
+ // void ft() {
+ // void f(int = []{ return T::value; }());
+ // }
+ // template void ft<int>(); // error: type 'int' cannot be used prior
+ // to '::' because it has no members
+ //
+ // The error is issued during instantiation of ft<int>() because substitution
+ // into the default argument fails; the default argument is instantiated even
+ // though it is never used.
+ if (Function->isLocalExternDecl()) {
+ for (ParmVarDecl *PVD : Function->parameters()) {
+ if (!PVD->hasDefaultArg())
+ continue;
+ if (SemaRef.SubstDefaultArgument(D->getInnerLocStart(), PVD, TemplateArgs)) {
+ // If substitution fails, the default argument is set to a
+ // RecoveryExpr that wraps the uninstantiated default argument so
+ // that downstream diagnostics are omitted.
+ Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
+ ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
+ UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(),
+ { UninstExpr }, UninstExpr->getType());
+ if (ErrorResult.isUsable())
+ PVD->setDefaultArg(ErrorResult.get());
+ }
+ }
+ }
+
SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous,
IsExplicitSpecialization,
Function->isThisDeclarationADefinition());
Previous.clear();
}
+ // Per [temp.inst], default arguments in member functions of local classes
+ // are instantiated along with the member function declaration. For example:
+ //
+ // template<typename T>
+ // void ft() {
+ // struct lc {
+ // int operator()(int p = []{ return T::value; }());
+ // };
+ // }
+ // template void ft<int>(); // error: type 'int' cannot be used prior
+ // to '::'because it has no members
+ //
+ // The error is issued during instantiation of ft<int>()::lc::operator()
+ // because substitution into the default argument fails; the default argument
+ // is instantiated even though it is never used.
+ if (D->isInLocalScopeForInstantiation()) {
+ for (unsigned P = 0; P < Params.size(); ++P) {
+ if (!Params[P]->hasDefaultArg())
+ continue;
+ if (SemaRef.SubstDefaultArgument(StartLoc, Params[P], TemplateArgs)) {
+ // If substitution fails, the default argument is set to a
+ // RecoveryExpr that wraps the uninstantiated default argument so
+ // that downstream diagnostics are omitted.
+ Expr *UninstExpr = Params[P]->getUninstantiatedDefaultArg();
+ ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
+ UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(),
+ { UninstExpr }, UninstExpr->getType());
+ if (ErrorResult.isUsable())
+ Params[P]->setDefaultArg(ErrorResult.get());
+ }
+ }
+ }
+
SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous,
IsExplicitSpecialization,
Method->isThisDeclarationADefinition());
bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
ParmVarDecl *Param) {
assert(Param->hasUninstantiatedDefaultArg());
- Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
-
- EnterExpressionEvaluationContext EvalContext(
- *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param);
// Instantiate the expression.
//
MultiLevelTemplateArgumentList TemplateArgs
= getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true);
- InstantiatingTemplate Inst(*this, CallLoc, Param,
- TemplateArgs.getInnermost());
- if (Inst.isInvalid())
- return true;
- if (Inst.isAlreadyInstantiating()) {
- Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
- Param->setInvalidDecl();
- return true;
- }
-
- ExprResult Result;
- {
- // C++ [dcl.fct.default]p5:
- // The names in the [default argument] expression are bound, and
- // the semantic constraints are checked, at the point where the
- // default argument expression appears.
- ContextRAII SavedContext(*this, FD);
- LocalInstantiationScope Local(*this);
-
- FunctionDecl *Pattern = FD->getTemplateInstantiationPattern(
- /*ForDefinition*/ false);
- if (addInstantiatedParametersToScope(FD, Pattern, Local, TemplateArgs))
- return true;
-
- runWithSufficientStackSpace(CallLoc, [&] {
- Result = SubstInitializer(UninstExpr, TemplateArgs,
- /*DirectInit*/false);
- });
- }
- if (Result.isInvalid())
- return true;
-
- // Check the expression as an initializer for the parameter.
- InitializedEntity Entity
- = InitializedEntity::InitializeParameter(Context, Param);
- InitializationKind Kind = InitializationKind::CreateCopy(
- Param->getLocation(),
- /*FIXME:EqualLoc*/ UninstExpr->getBeginLoc());
- Expr *ResultE = Result.getAs<Expr>();
-
- InitializationSequence InitSeq(*this, Entity, Kind, ResultE);
- Result = InitSeq.Perform(*this, Entity, Kind, ResultE);
- if (Result.isInvalid())
- return true;
-
- Result =
- ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(),
- /*DiscardedValue*/ false);
- if (Result.isInvalid())
+ if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true))
return true;
- // Remember the instantiated default argument.
- Param->setDefaultArg(Result.getAs<Expr>());
if (ASTMutationListener *L = getASTMutationListener())
L->DefaultArgumentInstantiated(Param);
template<typename T>
void defargs_in_template_unused(T t) {
- auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}}
+ auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} \
+ // expected-note {{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}}
l1(t);
}
template<typename T>
void defargs_in_template_used() {
auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} \
- // expected-note{{candidate function not viable: requires single argument 'value', but no arguments were provided}}
-#if defined(_WIN32) && !defined(_WIN64)
- // expected-note@46{{conversion candidate of type 'void (*)(const NoDefaultCtor &) __attribute__((thiscall))'}}
-#else
- // expected-note@46{{conversion candidate of type 'void (*)(const NoDefaultCtor &)'}}
-#endif
- l1(); // expected-error{{no matching function for call to object of type '(lambda at }}
+ // expected-note {{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}}
+ l1();
}
template void defargs_in_template_used<NonPOD>();
--- /dev/null
+// RUN: %clang_cc1 -no-opaque-pointers -std=c++14 -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s -w | FileCheck %s
+
+template<typename T = int>
+auto ft1() {
+ return [](int p = [] { return 0; } ()) { return p; };
+}
+void test_ft1() {
+ // CHECK: call noundef i32 @_ZZZ3ft1IiEDavENKUliE_clEiEd_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZZ3ft1IiEDavENKUliE_clEi
+ ft1<>()();
+}
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZ3ft1IiEDavENKUliE_clEi
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZZ3ft1IiEDavENKUliE_clEiEd_NKUlvE_clEv
+
+template <typename T>
+auto ft2() {
+ struct S {
+ T operator()(T p = []{ return 0; }()) const { return p; }
+ };
+ return S{};
+}
+void test_ft2() {
+ // CHECK: call noundef i32 @_ZZZ3ft2IiEDavENK1SclEiEd_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZZ3ft2IiEDavENK1SclEi
+ ft2<int>()();
+}
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZ3ft2IiEDavENK1SclEi
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZZ3ft2IiEDavENK1SclEiEd_NKUlvE_clEv
+
+template <typename>
+auto vt1 = [](int p = [] { return 0; } ()) { return p; };
+void test_vt1() {
+ // CHECK: call noundef i32 @_ZZNK3vt1IiEMUliE_clEiEd_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZNK3vt1IiEMUliE_clEi
+ vt1<int>();
+}
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZNK3vt1IiEMUliE_clEi
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZNK3vt1IiEMUliE_clEiEd_NKUlvE_clEv
--- /dev/null
+// RUN: %clang_cc1 -no-opaque-pointers -std=c++20 -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s -w | FileCheck %s
+
+template <typename T>
+auto ft1() {
+ return []<typename U = T>(T p1 = [] { return T{}; } (),
+ U p2 = [] { return U{}; } ()) { return p1+p2; };
+}
+void test_ft1() {
+ // CHECK: call noundef i32 @_ZZZ3ft1IiEDavENKUlTyiT_E_clIiEEDaiS0_Ed0_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZZZ3ft1IiEDavENKUlTyiT_E_clIiEEDaiS0_Ed_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZZ3ft1IiEDavENKUlTyiT_E_clIiEEDaiS0_
+ ft1<int>()();
+}
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZ3ft1IiEDavENKUlTyiT_E_clIiEEDaiS0_
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZZ3ft1IiEDavENKUlTyiT_E_clIiEEDaiS0_Ed0_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZZ3ft1IiEDavENKUlTyiT_E_clIiEEDaiS0_Ed_NKUlvE_clEv
+
+template <typename T>
+auto vt1 = []<typename U = T>(T p1 = [] { return T{}; } (),
+ U p2 = [] { return U{}; } ()) { return p1+p2; };
+void test_vt1() {
+ // CHECK: call noundef i32 @_ZZNK3vt1IiEMUlTyiT_E_clIiEEDaiS1_Ed0_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZZNK3vt1IiEMUlTyiT_E_clIiEEDaiS1_Ed_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZNK3vt1IiEMUlTyiT_E_clIiEEDaiS1_
+ vt1<int>();
+}
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZNK3vt1IiEMUlTyiT_E_clIiEEDaiS1_
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZNK3vt1IiEMUlTyiT_E_clIiEEDaiS1_Ed0_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZNK3vt1IiEMUlTyiT_E_clIiEEDaiS1_Ed_NKUlvE_clEv
}
int k = testVarargsLambdaNumbering();
+
+template<typename = int>
+void ft1(int = [](int p = [] { return 42; } ()) {
+ return p;
+ } ());
+void test_ft1() {
+ // CHECK: call noundef i32 @"_ZZZ3ft1IiEviENK3$_4clEiEd_NKUlvE_clEv"
+ // CHECK: call noundef i32 @"_ZZ3ft1IiEviENK3$_4clEi"
+ ft1();
+}
+// CHECK-LABEL: define internal noundef i32 @"_ZZ3ft1IiEviENK3$_4clEi"
+// CHECK-LABEL: define internal noundef i32 @"_ZZZ3ft1IiEviENK3$_4clEiEd_NKUlvE_clEv"
+
+struct c1 {
+ template<typename = int>
+ void mft1(int = [](int p = [] { return 42; } ()) {
+ return p;
+ } ());
+};
+void test_c1_mft1() {
+ // CHECK: call noundef i32 @_ZZZN2c14mft1IiEEviEd_NKUliE_clEiEd_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZZN2c14mft1IiEEviEd_NKUliE_clEi
+ c1{}.mft1();
+}
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN2c14mft1IiEEviEd_NKUliE_clEi
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZZN2c14mft1IiEEviEd_NKUliE_clEiEd_NKUlvE_clEv
+
+template<typename = int>
+struct ct1 {
+ void mf1(int = [](int p = [] { return 42; } ()) {
+ return p;
+ } ());
+ friend void ff(ct1, int = [](int p = [] { return 0; }()) { return p; }()) {}
+};
+void test_ct1_mft1() {
+ // CHECK: call noundef i32 @_ZZZN3ct1IiE3mf1EiEd_NKUliE_clEiEd_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZZN3ct1IiE3mf1EiEd_NKUliE_clEi
+ ct1<>{}.mf1();
+ // CHECK: call noundef i32 @_ZZZ2ff3ct1IiEiEd_NKUliE_clEiEd_NKUlvE_clEv
+ // CHECK: call noundef i32 @_ZZ2ff3ct1IiEiEd_NKUliE_clEi
+ ff(ct1<>{});
+}
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN3ct1IiE3mf1EiEd_NKUliE_clEi
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZZN3ct1IiE3mf1EiEd_NKUliE_clEiEd_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZ2ff3ct1IiEiEd_NKUliE_clEi
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZZ2ff3ct1IiEiEd_NKUliE_clEiEd_NKUlvE_clEv
+
+template<typename = int>
+void ft2() {
+ [](int p = [] { return 42; } ()) { return p; } ();
+}
+template void ft2<>();
+// CHECK: call noundef i32 @_ZZZ3ft2IiEvvENKUliE_clEiEd_NKUlvE_clEv
+// CHECK: call noundef i32 @_ZZ3ft2IiEvvENKUliE_clEi
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZ3ft2IiEvvENKUliE_clEi
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZZ3ft2IiEvvENKUliE_clEiEd_NKUlvE_clEv
+
+template<typename>
+void ft3() {
+ void f(int = []{ return 0; }());
+ f();
+}
+template void ft3<int>();
+// CHECK: call noundef i32 @"_ZZ1fiENK3$_5clEv"
+// CHECK-LABEL: define internal noundef i32 @"_ZZ1fiENK3$_5clEv"
+
+template<typename>
+void ft4() {
+ struct lc {
+ void mf(int = []{ return 0; }()) {}
+ };
+ lc().mf();
+}
+template void ft4<int>();
+// CHECK: call noundef i32 @_ZZZ3ft4IiEvvEN2lc2mfEiEd_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZZ3ft4IiEvvEN2lc2mfEiEd_NKUlvE_clEv
+
+
// Check linkage of the various lambdas.
// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZ11inline_funciENKUlvE_clEv
// CHECK: ret i32 1
template<typename T> auto fn1 = [](auto a) { return a + T(1); };
template<typename T> auto v1 = [](int a = T()) { return a; }();
// expected-error@-1{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}}
-// expected-note@-2{{passing argument to parameter 'a' here}}
+// expected-note@-2{{in instantiation of default function argument expression for 'operator()<int *>' required here}}
+// expected-note@-3{{passing argument to parameter 'a' here}}
struct S {
template<class T>
namespace NondefDecls {
template<typename T> void f1() {
- int g1(int defarg = T::error); // expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
+ int g1(int defarg = T::error); // expected-error{{type 'int' cannot be used prior to '::' because it has no members}} \
+ // expected-note {{in instantiation of default function argument expression for 'g1<int>' required here}}
}
template void f1<int>(); // expected-note{{in instantiation of function template specialization 'NondefDecls::f1<int>' requested here}}
}
namespace PR21332 {
template<typename T> void f1() {
struct S { // expected-note{{in instantiation of member class 'S' requested here}}
- void g1(int n = T::error); // expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
+ void g1(int n = T::error); // expected-error{{type 'int' cannot be used prior to '::' because it has no members}} \
+ // expected-note {{in instantiation of default function argument expression for 'g1<int>' required here}}
};
}
template void f1<int>(); // expected-note{{in instantiation of function template specialization 'PR21332::f1<int>' requested here}}
class S { // expected-note {{in instantiation of member function 'PR21332::f6()::S::get' requested here}}
void get() {
class S2 { // expected-note {{in instantiation of member class 'S2' requested here}}
- void g1(int n = T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
+ void g1(int n = T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} \
+ // expected-note {{in instantiation of default function argument expression for 'g1<int>' required here}}
};
}
};
template <typename T> void foo() {
struct Inner { // expected-note {{in instantiation}}
- void operator()(T a = "") {} // expected-error {{conversion function from 'const char[1]' to 'rdar23721638::A' invokes a deleted function}}
- // expected-note@-1 {{passing argument to parameter 'a' here}}
+ void operator()(T a = "") {} // expected-error {{conversion function from 'const char[1]' to 'rdar23721638::A' invokes a deleted function}} \
+ // expected-note {{in instantiation of default function argument expression for 'operator()<rdar23721638::A>' required here}} \
+ // expected-note {{passing argument to parameter 'a' here}}
};
- Inner()(); // expected-error {{type 'Inner' does not provide a call operator}}
+ Inner()();
}
- template void foo<A>(); // expected-note 2 {{in instantiation}}
+ template void foo<A>(); // expected-note {{in instantiation}}
template <typename T> void bar() {
- auto lambda = [](T a = "") {}; // expected-error {{conversion function from 'const char[1]' to 'rdar23721638::A' invokes a deleted function}}
- // expected-note@-1 {{passing argument to parameter 'a' here}}
+ auto lambda = [](T a = "") {}; // expected-error {{conversion function from 'const char[1]' to 'rdar23721638::A' invokes a deleted function}} \
+ // expected-note {{in instantiation of default function argument expression for 'operator()<rdar23721638::A>' required here}} \
+ // expected-note {{passing argument to parameter 'a' here}}
lambda();
}
template void bar<A>(); // expected-note {{in instantiation}}
template <typename T>
void f(int x = [](T x = nullptr) -> int { return x; }());
// expected-error@-1 {{cannot initialize a parameter of type 'int' with an rvalue of type 'std::nullptr_t'}}
- // expected-note@-2 {{passing argument to parameter 'x' here}}
+ // expected-note@-2 {{in instantiation of default function argument expression for 'operator()<int>' required here}}
+ // expected-note@-3 {{passing argument to parameter 'x' here}}
void g() { f<int>(); }
// expected-note@-1 {{in instantiation of default function argument expression for 'f<int>' required here}}