[PATCH] Allow return type deduction for templates in delayed parsing mode.
Faisal Vali
faisalv at yahoo.com
Tue Oct 29 18:57:04 PDT 2013
- added some tests
- use of canSkipFunctionBody in ParseCXXInilineMethod causes code to crash.
- at the parsing stage, we just need to check if the trailing return type contains an 'auto' - is not necessary to check if it is deduced (this seems to introduce the problem).
- can't use canSkipFunctionBody in ParseFunctionBody without some other non-trivial(? converting the Declarator to a Decl*) changes.
Thanks!
Hi rsmith, doug.gregor, majnemer,
http://llvm-reviews.chandlerc.com/D2053
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D2053?vs=5231&id=5247#toc
Files:
lib/Parse/ParseCXXInlineMethods.cpp
lib/Parse/Parser.cpp
test/SemaCXX/cxx1y-deduced-return-type.cpp
Index: lib/Parse/ParseCXXInlineMethods.cpp
===================================================================
--- lib/Parse/ParseCXXInlineMethods.cpp
+++ lib/Parse/ParseCXXInlineMethods.cpp
@@ -109,13 +109,15 @@
return FnD;
}
-
+
// In delayed template parsing mode, if we are within a class template
// or if we are about to parse function member template then consume
// the tokens and store them for parsing at the end of the translation unit.
if (getLangOpts().DelayedTemplateParsing &&
DefinitionKind == FDK_Definition &&
- !D.getDeclSpec().isConstexprSpecified() &&
+ !D.getDeclSpec().isConstexprSpecified() &&
+ !(FnD && getFunctionDecl(FnD) &&
+ getFunctionDecl(FnD)->getResultType()->getContainedAutoType()) &&
((Actions.CurContext->isDependentContext() ||
(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) &&
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -919,6 +919,26 @@
}
}
+
+static inline bool isFunctionDeclaratorRequiringReturnTypeDeduction(
+ const Declarator &D) {
+ if (!D.isFunctionDeclarator() || !D.getDeclSpec().containsPlaceholderType())
+ return false;
+ for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
+ unsigned chunkIndex = E - I - 1;
+ const DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
+ if (DeclType.Kind == DeclaratorChunk::Function) {
+ const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+ if (!FTI.hasTrailingReturnType())
+ return true;
+ QualType TrailingRetType = FTI.getTrailingReturnType().get();
+ return TrailingRetType->getCanonicalTypeInternal()
+ ->getContainedAutoType();
+ }
+ }
+ return false;
+}
+
/// ParseFunctionDefinition - We parsed and verified that the specified
/// Declarator is well formed. If this is a K&R-style function, read the
/// parameters declaration-list, then start the compound-statement.
@@ -992,7 +1012,8 @@
// tokens and store them for late parsing at the end of the translation unit.
if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) &&
TemplateInfo.Kind == ParsedTemplateInfo::Template &&
- !D.getDeclSpec().isConstexprSpecified()) {
+ !D.getDeclSpec().isConstexprSpecified() &&
+ !isFunctionDeclaratorRequiringReturnTypeDeduction(D)) {
MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams);
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
Index: test/SemaCXX/cxx1y-deduced-return-type.cpp
===================================================================
--- test/SemaCXX/cxx1y-deduced-return-type.cpp
+++ test/SemaCXX/cxx1y-deduced-return-type.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
auto f(); // expected-note {{previous}}
int f(); // expected-error {{differ only in their return type}}
@@ -392,10 +393,19 @@
int k2 = S<int>().h(false);
template<typename T> struct U {
+ #ifndef DELAYED_TEMPLATE_PARSING
auto f(); // expected-note {{here}}
int g() { return f(); } // expected-error {{cannot be used before it is defined}}
+ #else
+ auto f();
+ int g() { return f(); }
+ #endif
};
+ #ifndef DELAYED_TEMPLATE_PARSING
template int U<int>::g(); // expected-note {{in instantiation of}}
+ #else
+ template int U<int>::g();
+ #endif
template<typename T> auto U<T>::f() { return T(); }
template int U<short>::g(); // ok
}
@@ -408,3 +418,42 @@
using T = decltype(f(A<int>()));
using T = decltype(f<int>(A<int>()));
}
+
+namespace MultilevelDeduction {
+
+auto F() -> auto* { return (int*)0; }
+
+auto (*G())() -> int* { return F; }
+
+auto run = G();
+
+namespace Templated {
+template<class T>
+auto F(T t) -> auto* { return (T*)0; }
+
+template<class T>
+auto (*G(T t))(T) -> T* { return &F<T>; }
+
+
+template<class T>
+auto (*G2(T t))(T) -> auto* { return &F<T>; }
+
+auto run_int = G(1);
+auto run_char = G2('a');
+
+}
+}
+
+namespace rnk {
+extern "C" int puts(const char *s);
+template <typename T>
+auto foo(T x) -> decltype(x) {
+#ifdef DELAYED_TEMPLATE_PARSING
+ ::rnk::bar();
+#endif
+ return x;
+}
+void bar() { puts("bar"); }
+int main() { return foo(0); }
+
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2053.2.patch
Type: text/x-patch
Size: 4510 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131029/328db935/attachment.bin>
More information about the cfe-commits
mailing list