forked from OSchip/llvm-project
Instantiation of local class members.
If a function containing a local class is instantiated, instantiate all of local class member, including default arguments and exception specifications. This change fixes PR21332 and thus implements DR1484. Differential Revision: http://reviews.llvm.org/D9990 llvm-svn: 240974
This commit is contained in:
parent
ae51f5bab1
commit
3739f5e7c9
|
@ -3317,13 +3317,16 @@ Parser::tryParseExceptionSpecification(bool Delayed,
|
|||
T.consumeOpen();
|
||||
NoexceptType = EST_ComputedNoexcept;
|
||||
NoexceptExpr = ParseConstantExpression();
|
||||
T.consumeClose();
|
||||
// The argument must be contextually convertible to bool. We use
|
||||
// ActOnBooleanCondition for this purpose.
|
||||
if (!NoexceptExpr.isInvalid())
|
||||
if (!NoexceptExpr.isInvalid()) {
|
||||
NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc,
|
||||
NoexceptExpr.get());
|
||||
T.consumeClose();
|
||||
NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
|
||||
NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
|
||||
} else {
|
||||
NoexceptType = EST_None;
|
||||
}
|
||||
} else {
|
||||
// There is no argument.
|
||||
NoexceptType = EST_BasicNoexcept;
|
||||
|
|
|
@ -1680,11 +1680,24 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
|
|||
} else if (OldParm->hasUnparsedDefaultArg()) {
|
||||
NewParm->setUnparsedDefaultArg();
|
||||
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
|
||||
} else if (Expr *Arg = OldParm->getDefaultArg())
|
||||
// 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);
|
||||
} else if (Expr *Arg = OldParm->getDefaultArg()) {
|
||||
FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
|
||||
CXXRecordDecl *ClassD = dyn_cast<CXXRecordDecl>(OwningFunc->getDeclContext());
|
||||
if (ClassD && ClassD->isLocalClass() && !ClassD->isLambda()) {
|
||||
// If this is a method of a local class, as per DR1484 its default
|
||||
// arguments must be instantiated.
|
||||
Sema::ContextRAII SavedContext(*this, ClassD);
|
||||
LocalInstantiationScope Local(*this);
|
||||
ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
|
||||
if (NewArg.isUsable())
|
||||
NewParm->setDefaultArg(NewArg.get());
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
|
||||
|
||||
|
|
|
@ -3246,10 +3246,18 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
|
|||
|
||||
// DR1330: In C++11, defer instantiation of a non-trivial
|
||||
// exception specification.
|
||||
// DR1484: Local classes and their members are instantiated along with the
|
||||
// containing function.
|
||||
bool RequireInstantiation = false;
|
||||
if (CXXRecordDecl *Cls = dyn_cast<CXXRecordDecl>(Tmpl->getDeclContext())) {
|
||||
if (Cls->isLocalClass())
|
||||
RequireInstantiation = true;
|
||||
}
|
||||
if (SemaRef.getLangOpts().CPlusPlus11 &&
|
||||
EPI.ExceptionSpec.Type != EST_None &&
|
||||
EPI.ExceptionSpec.Type != EST_DynamicNone &&
|
||||
EPI.ExceptionSpec.Type != EST_BasicNoexcept) {
|
||||
EPI.ExceptionSpec.Type != EST_BasicNoexcept &&
|
||||
!RequireInstantiation) {
|
||||
FunctionDecl *ExceptionSpecTemplate = Tmpl;
|
||||
if (EPI.ExceptionSpec.Type == EST_Uninstantiated)
|
||||
ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate;
|
||||
|
|
|
@ -394,3 +394,57 @@ void f() {
|
|||
|
||||
void g() { f<void>(); }
|
||||
}
|
||||
|
||||
|
||||
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}}
|
||||
};
|
||||
}
|
||||
template void f1<int>(); // expected-note{{in instantiation of function template specialization 'PR21332::f1<int>' requested here}}
|
||||
|
||||
template<typename T> void f2() {
|
||||
struct S { // expected-note{{in instantiation of member class 'S' requested here}}
|
||||
void g2() noexcept(T::error); // expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
|
||||
};
|
||||
}
|
||||
template void f2<int>(); // expected-note{{in instantiation of function template specialization 'PR21332::f2<int>' requested here}}
|
||||
|
||||
template<typename T> void f3() {
|
||||
enum S {
|
||||
val = T::error; // expected-error{{expected '}' or ','}} expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
|
||||
};
|
||||
}
|
||||
template void f3<int>(); //expected-note{{in instantiation of function template specialization 'PR21332::f3<int>' requested here}}
|
||||
|
||||
template<typename T> void f4() {
|
||||
enum class S {
|
||||
val = T::error; // expected-error{{expected '}' or ','}} expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
|
||||
};
|
||||
}
|
||||
template void f4<int>(); // expected-note{{in instantiation of function template specialization 'PR21332::f4<int>' requested here}}
|
||||
|
||||
template<typename T> void f5() {
|
||||
class S { // expected-note {{in instantiation of default member initializer 'PR21332::f5()::S::val' requested here}}
|
||||
int val = T::error; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
|
||||
};
|
||||
}
|
||||
template void f5<int>(); // expected-note {{in instantiation of function template specialization 'PR21332::f5<int>' requested here}}
|
||||
|
||||
template<typename T> void f6() {
|
||||
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}}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
template void f6<int>(); // expected-note{{in instantiation of function template specialization 'PR21332::f6<int>' requested here}}
|
||||
|
||||
template<typename T> void f7() {
|
||||
struct S { void g() noexcept(undefined_val); }; // expected-error{{use of undeclared identifier 'undefined_val'}}
|
||||
}
|
||||
template void f7<int>();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue