r184903 - Fix PCH bug with member templates of local classes in nontemplate functions.
Faisal Vali
faisalv at yahoo.com
Tue Jun 25 19:34:24 PDT 2013
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
More information about the cfe-commits
mailing list