Author: sepavloff Date: Sun Aug 23 05:22:28 2015 New Revision: 245810 URL: http://llvm.org/viewvc/llvm-project?rev=245810&view=rev Log: Instantiate function declarations in instantiated functions.
If a function declaration is found inside a template function as in: template<class T> void f() { void g(int x = T::v) except(T::w); } it must be instantiated along with the enclosing template function, including default arguments and exception specification. Together with the patch committed in r240974 this implements DR1484. Differential Revision: http://reviews.llvm.org/D11194 Modified: cfe/trunk/include/clang/AST/DeclBase.h cfe/trunk/lib/AST/DeclBase.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp cfe/trunk/test/SemaTemplate/default-arguments.cpp cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp Modified: cfe/trunk/include/clang/AST/DeclBase.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=245810&r1=245809&r2=245810&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclBase.h (original) +++ cfe/trunk/include/clang/AST/DeclBase.h Sun Aug 23 05:22:28 2015 @@ -728,6 +728,15 @@ public: 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; Modified: cfe/trunk/lib/AST/DeclBase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=245810&r1=245809&r2=245810&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclBase.cpp (original) +++ cfe/trunk/lib/AST/DeclBase.cpp Sun Aug 23 05:22:28 2015 @@ -266,6 +266,18 @@ void Decl::setDeclContextsImpl(DeclConte } } +bool Decl::isLexicallyWithinFunctionOrMethod() const { + const DeclContext *LDC = getLexicalDeclContext(); + do { + if (LDC->isFunctionOrMethod()) + return true; + if (!isa<TagDecl>(LDC)) + return false; + LDC = LDC->getParent(); + } while (LDC); + return false; +} + bool Decl::isInAnonymousNamespace() const { const DeclContext *DC = getDeclContext(); do { Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=245810&r1=245809&r2=245810&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Sun Aug 23 05:22:28 2015 @@ -1682,11 +1682,10 @@ ParmVarDecl *Sema::SubstParmVarDecl(Parm UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm); } 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); + 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()) Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=245810&r1=245809&r2=245810&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Aug 23 05:22:28 2015 @@ -3247,16 +3247,11 @@ TemplateDeclInstantiator::InitFunctionIn // 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 && - !RequireInstantiation) { + !Tmpl->isLexicallyWithinFunctionOrMethod()) { FunctionDecl *ExceptionSpecTemplate = Tmpl; if (EPI.ExceptionSpec.Type == EST_Uninstantiated) ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate; Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp?rev=245810&r1=245809&r2=245810&view=diff ============================================================================== --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp Sun Aug 23 05:22:28 2015 @@ -26,23 +26,26 @@ struct NonPOD { }; struct NoDefaultCtor { - NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}} + NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}} \ + // expected-note{{candidate constructor not viable: requires 1 argument, but 0 were provided}} ~NoDefaultCtor(); }; template<typename T> void defargs_in_template_unused(T t) { - auto l1 = [](const T& value = T()) { }; + auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} l1(t); } template void defargs_in_template_unused(NonPOD); -template void defargs_in_template_unused(NoDefaultCtor); +template void defargs_in_template_unused(NoDefaultCtor); // expected-note{{in instantiation of function template specialization 'defargs_in_template_unused<NoDefaultCtor>' requested here}} template<typename T> void defargs_in_template_used() { - auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} - l1(); // expected-note{{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}} + auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} \ + // expected-note{{candidate function not viable: requires single argument 'value', but no arguments were provided}} \ + // expected-note{{conversion candidate of type 'void (*)(const NoDefaultCtor &)'}} + l1(); // expected-error{{no matching function for call to object of type '(lambda at }} } template void defargs_in_template_used<NonPOD>(); Modified: cfe/trunk/test/SemaTemplate/default-arguments.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/default-arguments.cpp?rev=245810&r1=245809&r2=245810&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/default-arguments.cpp (original) +++ cfe/trunk/test/SemaTemplate/default-arguments.cpp Sun Aug 23 05:22:28 2015 @@ -159,3 +159,10 @@ namespace DR1635 { int g() { X<int>::f(0); } // expected-note {{in instantiation of template class 'DR1635::X<int>' requested here}} } + +namespace NondefDecls { + template<typename T> 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<int>(); // expected-note{{in instantiation of function template specialization 'NondefDecls::f1<int>' requested here}} +} Modified: cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp?rev=245810&r1=245809&r2=245810&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp (original) +++ cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp Sun Aug 23 05:22:28 2015 @@ -178,3 +178,11 @@ namespace Variadic { } } + +namespace NondefDecls { + template<typename T> 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<int>(); // expected-note{{in instantiation of function template specialization 'NondefDecls::f1<int>' requested here}} +} + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits