mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
Lambda closure types are always considered to be like "local" classes,
even if they are not within a function scope. Teach template instantiation to treat them as such, and make sure that we have a local instantiation scope when instantiating default arguments and static data members. llvm-svn: 150725
This commit is contained in:
@@ -3128,6 +3128,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
|
||||
// the semantic constraints are checked, at the point where the
|
||||
// default argument expression appears.
|
||||
ContextRAII SavedContext(*this, FD);
|
||||
LocalInstantiationScope Local(*this);
|
||||
Result = SubstExpr(UninstExpr, ArgList);
|
||||
}
|
||||
if (Result.isInvalid())
|
||||
|
||||
@@ -2629,7 +2629,8 @@ void Sema::InstantiateStaticDataMemberDefinition(
|
||||
// Enter the scope of this instantiation. We don't use
|
||||
// PushDeclContext because we don't have a scope.
|
||||
ContextRAII previousContext(*this, Var->getDeclContext());
|
||||
|
||||
LocalInstantiationScope Local(*this);
|
||||
|
||||
VarDecl *OldVar = Var;
|
||||
Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
|
||||
getTemplateInstantiationArgs(Var)));
|
||||
@@ -2644,7 +2645,8 @@ void Sema::InstantiateStaticDataMemberDefinition(
|
||||
DeclGroupRef DG(Var);
|
||||
Consumer.HandleTopLevelDecl(DG);
|
||||
}
|
||||
|
||||
Local.Exit();
|
||||
|
||||
if (Recursive) {
|
||||
// Define any newly required vtables.
|
||||
DefineUsedVTables();
|
||||
@@ -3096,7 +3098,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
|
||||
DeclContext *ParentDC = D->getDeclContext();
|
||||
if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
|
||||
isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
|
||||
(ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext())) {
|
||||
(ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) ||
|
||||
(isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {
|
||||
// D is a local of some kind. Look into the map of local
|
||||
// declarations to their instantiations.
|
||||
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
|
||||
|
||||
@@ -114,3 +114,36 @@ namespace p5 {
|
||||
|
||||
template void double_capture(NonConstCopy&);
|
||||
}
|
||||
|
||||
namespace NonLocalLambdaInstantation {
|
||||
template<typename T>
|
||||
struct X {
|
||||
static int value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
int X<T>::value = []{ return T(); }(); // expected-error{{cannot initialize a variable of type 'int' with an rvalue of type 'int *'}}
|
||||
|
||||
template int X<int>::value;
|
||||
template int X<float>::value;
|
||||
template int X<int*>::value; // expected-note{{in instantiation of static data member }}
|
||||
|
||||
template<typename T>
|
||||
void defaults(int x = []{ return T(); }()) { }; // expected-error{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}} \
|
||||
// expected-note{{passing argument to parameter 'x' here}}
|
||||
|
||||
void call_defaults() {
|
||||
defaults<int>();
|
||||
defaults<float>();
|
||||
defaults<int*>(); // expected-note{{in instantiation of default function argument expression for 'defaults<int *>' required here}}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct X2 {
|
||||
int x = []{ return T(); }(); // expected-error{{cannot initialize a member subobject of type 'int' with an rvalue of type 'int *'}}
|
||||
};
|
||||
|
||||
X2<int> x2i;
|
||||
X2<float> x2f;
|
||||
X2<int*> x2ip; // expected-note{{in instantiation of template class 'NonLocalLambdaInstantation::X2<int *>' requested here}}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user