[PATCH] Allow return type deduction for templates in delayed parsing mode.

Faisal Vali faisalv at yahoo.com
Tue Oct 29 07:46:28 PDT 2013


Hi rsmith, doug.gregor, majnemer,

If the function has a declarator consistent with requiring return type deduction or if a member function (or a conversion function) whose return type contains auto - go ahead and parse the template even in delayed template parsing mode.

This implementation was inspired by:  http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20131021/091589.html

http://llvm-reviews.chandlerc.com/D2053

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,25 @@
   }
 }
 
+
+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 +1011,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
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2053.1.patch
Type: text/x-patch
Size: 3729 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131029/a456b097/attachment.bin>


More information about the cfe-commits mailing list