Index: lib/Parse/ParseDeclCXX.cpp =================================================================== --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -3318,13 +3318,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: 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(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(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,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(); +}