Author: faisalv Date: Tue Jun 25 21:34:24 2013 New Revision: 184903 URL: http://llvm.org/viewvc/llvm-project?rev=184903&view=rev Log: Fix PCH bug with member templates of local classes in nontemplate functions.
As noted by Richard in the post: http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130624/082605.html, the following code should not add an entry into PendingLocalImplicitInstantiations, since local instantiations should only occur within the context of other instantiations: int foo(double y) { struct Lambda { template<class T> T operator()(T t) const { return t; }; } lambda; return lambda(y); } Hence the attached code does the following: 1) In MarkFunctionReferenced, check if ActiveInstantiations.size() is non-zero before adding to PendingLocalImplicitInstantiations. 2) In InstantiateFunctionDefinition, we swap out/in PendingLocalImplicitInstantiations so that only those pending local instantiations that are added during the instantiation of the current function are instantiated recursively. Added: cfe/trunk/test/PCH/cxx-local-templates.cpp cfe/trunk/test/PCH/cxx1y-local-templates.cpp Modified: cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=184903&r1=184902&r2=184903&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 25 21:34:24 2013 @@ -10893,7 +10893,8 @@ void Sema::MarkFunctionReferenced(Source if (!AlreadyInstantiated || Func->isConstexpr()) { if (isa<CXXRecordDecl>(Func->getDeclContext()) && - cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass()) + cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() && + ActiveTemplateInstantiations.size()) PendingLocalImplicitInstantiations.push_back( std::make_pair(Func, PointOfInstantiation)); else if (Func->isConstexpr()) Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=184903&r1=184902&r2=184903&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Jun 25 21:34:24 2013 @@ -2918,6 +2918,10 @@ void Sema::InstantiateFunctionDefinition // while we're still within our own instantiation context. SmallVector<VTableUse, 16> SavedVTableUses; std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; + std::deque<PendingImplicitInstantiation> + SavedPendingLocalImplicitInstantiations; + SavedPendingLocalImplicitInstantiations.swap( + PendingLocalImplicitInstantiations); if (Recursive) { VTableUses.swap(SavedVTableUses); PendingInstantiations.swap(SavedPendingInstantiations); @@ -2998,6 +3002,8 @@ void Sema::InstantiateFunctionDefinition "PendingInstantiations should be empty before it is discarded."); PendingInstantiations.swap(SavedPendingInstantiations); } + SavedPendingLocalImplicitInstantiations.swap( + PendingLocalImplicitInstantiations); } /// \brief Instantiate the definition of the given variable from its Added: cfe/trunk/test/PCH/cxx-local-templates.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-local-templates.cpp?rev=184903&view=auto ============================================================================== --- cfe/trunk/test/PCH/cxx-local-templates.cpp (added) +++ cfe/trunk/test/PCH/cxx-local-templates.cpp Tue Jun 25 21:34:24 2013 @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t-cxx11 +// RUN: %clang_cc1 -ast-print -pedantic-errors -std=c++11 -include-pch %t-cxx11 %s | FileCheck -check-prefix=CHECK-PRINT %s + +#ifndef HEADER_INCLUDED + +#define HEADER_INCLUDED + +int nontemplate_test(double d) { + struct Local { + template<class T> T foo(T t) { + return t; + } + }; + return Local{}.foo(d); +} + +template<class U> +U template_test(U d) { + struct Local { + template<class T> T foo(T t) { + return t; + } + }; + return Local{}.foo(d); +} + +int nested_local() { + struct Inner1 { + int inner1_foo(char c) { + struct Inner2 { + template<class T> T inner2_foo(T t) { + return t; + } + }; + return Inner2{}.inner2_foo(3.14); + } + }; + return Inner1{}.inner1_foo('a'); +} + +#else + +// CHECK-PRINT: U template_test + +// CHECK-PRINT: int nontemplate_test(double) + +int nontemplate_test(double); + +template double template_test(double); +int test2(int y) { + return nontemplate_test(y) + template_test(y); +} + + +#endif Added: cfe/trunk/test/PCH/cxx1y-local-templates.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx1y-local-templates.cpp?rev=184903&view=auto ============================================================================== --- cfe/trunk/test/PCH/cxx1y-local-templates.cpp (added) +++ cfe/trunk/test/PCH/cxx1y-local-templates.cpp Tue Jun 25 21:34:24 2013 @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -pedantic-errors -std=c++1y -emit-pch %s -o %t-cxx1y +// RUN: %clang_cc1 -ast-print -pedantic-errors -std=c++1y -include-pch %t-cxx1y %s | FileCheck -check-prefix=CHECK-PRINT %s + +#ifndef HEADER_INCLUDED + +#define HEADER_INCLUDED + +auto nested_local_call_all() { + struct Inner1 { + auto inner1_foo(char c) { + struct Inner2 { + template<class T> T inner2_foo(T t) { + return t; + } + }; + return Inner2{}; + } + }; + return Inner1{}.inner1_foo('a').inner2_foo(4); +} + + +auto nested_local() { + struct Inner1 { + auto inner1_foo(char c) { + struct Inner2 { + template<class T> T inner2_foo(T t) { + return t; + } + }; + return Inner2{}; + } + }; + return Inner1{}; +} + + +int test() { + auto A = nested_local_call_all(); + auto B = nested_local(); + auto C = B.inner1_foo('a'); + C.inner2_foo(3.14); + +} + + +#else + +// CHECK-PRINT: int nested_local_call_all +// CHECK-PRINT: nested_local +auto nested_local_call_all(); + +int test(int y) { + return nested_local_call_all(); +} + + +#endif _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
