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.
http://reviews.llvm.org/D9990
Files:
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-local-class.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1819,8 +1819,27 @@
Method->setLexicalDeclContext(D->getLexicalDeclContext());
// Attach the parameters
- for (unsigned P = 0; P < Params.size(); ++P)
+ for (unsigned P = 0; P < Params.size(); ++P) {
Params[P]->setOwningFunction(Method);
+
+ // If this is a method of a local class, as per DR1484 its default arguments
+ // must be instantiated now.
+ CXXRecordDecl *ClassD = cast<CXXRecordDecl>(D->getDeclContext());
+ if (ClassD->isLocalClass() && !ClassD->isLambda()) {
+ ParmVarDecl *OldParm = D->getParamDecl(P);
+ if (Expr *OldDefArg = OldParm->getDefaultArg()) {
+ ExprResult NewDefArg;
+ {
+ Sema::ContextRAII SavedContext(SemaRef, ClassD);
+ LocalInstantiationScope Local(SemaRef);
+ NewDefArg = SemaRef.SubstExpr(OldDefArg, TemplateArgs);
+ }
+ if (NewDefArg.isInvalid())
+ D->setInvalidDecl();
+ Params[P]->setDefaultArg(NewDefArg.get());
+ }
+ }
+ }
Method->setParams(Params);
if (InitMethodInstantiation(Method, D))
@@ -3246,10 +3265,17 @@
// 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 InLocalClass = false;
+ if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Tmpl->getDeclContext()))
+ if (Class->isLocalClass())
+ InLocalClass = 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 &&
+ !InLocalClass) {
FunctionDecl *ExceptionSpecTemplate = Tmpl;
if (EPI.ExceptionSpec.Type == EST_Uninstantiated)
ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate;
Index: test/SemaTemplate/instantiate-local-class.cpp
===================================================================
--- test/SemaTemplate/instantiate-local-class.cpp
+++ test/SemaTemplate/instantiate-local-class.cpp
@@ -394,3 +394,52 @@
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}}
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits