Index: cfe/trunk/lib/Parse/ParseDeclCXX.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp @@ -3317,13 +3317,16 @@ 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; Index: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp @@ -1680,11 +1680,24 @@ } 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(OldParm->getDeclContext()); + CXXRecordDecl *ClassD = dyn_cast(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()); Index: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3246,10 +3246,18 @@ // 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(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; Index: cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp =================================================================== --- cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp +++ cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp @@ -394,3 +394,57 @@ void g() { f(); } } + + +namespace PR21332 { + template 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(); // expected-note{{in instantiation of function template specialization 'PR21332::f1' requested here}} + + template 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(); // expected-note{{in instantiation of function template specialization 'PR21332::f2' requested here}} + + template 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(); //expected-note{{in instantiation of function template specialization 'PR21332::f3' requested here}} + + template 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(); // expected-note{{in instantiation of function template specialization 'PR21332::f4' requested here}} + + template 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(); // expected-note {{in instantiation of function template specialization 'PR21332::f5' requested here}} + + template 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(); // expected-note{{in instantiation of function template specialization 'PR21332::f6' requested here}} + + template void f7() { + struct S { void g() noexcept(undefined_val); }; // expected-error{{use of undeclared identifier 'undefined_val'}} + } + template void f7(); +}