Index: include/clang/AST/DeclBase.h =================================================================== --- include/clang/AST/DeclBase.h +++ include/clang/AST/DeclBase.h @@ -728,6 +728,15 @@ return getParentFunctionOrMethod() == nullptr; } + /// \brief Returns true if this declaration lexically is inside a function. + /// It recognizes non-defining declarations as well as members of local + /// classes: + /// \code + /// void foo() { void bar(); } + /// void foo2() { class ABC { void bar(); }; } + /// \endcode + bool isLexicallyWithinFunctionOrMethod() const; + /// \brief If this decl is defined inside a function/method/block it returns /// the corresponding DeclContext, otherwise it returns null. const DeclContext *getParentFunctionOrMethod() const; Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ lib/AST/DeclBase.cpp @@ -266,6 +266,15 @@ } } +bool Decl::isLexicallyWithinFunctionOrMethod() const { + const DeclContext *LDC = getLexicalDeclContext(); + if (LDC->isFunctionOrMethod()) + return true; + if (const CXXRecordDecl *ClassD = dyn_cast(LDC)) + return ClassD->isLocalClass() && !ClassD->isLambda();; + return false; +} + bool Decl::isInAnonymousNamespace() const { const DeclContext *DC = getDeclContext(); do { Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -1682,11 +1682,10 @@ UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm); } 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); + if (OwningFunc->isLexicallyWithinFunctionOrMethod()) { + // Instantiate default arguments for methods of local classes (DR1484) + // and non-defining declarations. + Sema::ContextRAII SavedContext(*this, OwningFunc); LocalInstantiationScope Local(*this); ExprResult NewArg = SubstExpr(Arg, TemplateArgs); if (NewArg.isUsable()) Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3246,16 +3246,11 @@ // 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 && - !RequireInstantiation) { + !Tmpl->isLexicallyWithinFunctionOrMethod()) { FunctionDecl *ExceptionSpecTemplate = Tmpl; if (EPI.ExceptionSpec.Type == EST_Uninstantiated) ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate; Index: test/SemaTemplate/default-arguments.cpp =================================================================== --- test/SemaTemplate/default-arguments.cpp +++ test/SemaTemplate/default-arguments.cpp @@ -159,3 +159,10 @@ int g() { X::f(0); } // expected-note {{in instantiation of template class 'DR1635::X' requested here}} } + +namespace NondefDecls { + template void f1() { + int g1(int defarg = 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 'NondefDecls::f1' requested here}} +} Index: test/SemaTemplate/instantiate-exception-spec-cxx11.cpp =================================================================== --- test/SemaTemplate/instantiate-exception-spec-cxx11.cpp +++ test/SemaTemplate/instantiate-exception-spec-cxx11.cpp @@ -178,3 +178,11 @@ } } + +namespace NondefDecls { + template void f1() { + int g1(int) noexcept(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 'NondefDecls::f1' requested here}} +} +