r193849 - Support return type deduction for templates in -fdelayed-template-parsing (microsoft) mode

Faisal Vali faisalv at yahoo.com
Thu Oct 31 19:01:01 PDT 2013


Author: faisalv
Date: Thu Oct 31 21:01:01 2013
New Revision: 193849

URL: http://llvm.org/viewvc/llvm-project?rev=193849&view=rev
Log:
Support return type deduction for templates in -fdelayed-template-parsing (microsoft) mode

Please see http://llvm-reviews.chandlerc.com/D2053 for discussion and Richard's stamp.

Modified:
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp
    cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=193849&r1=193848&r2=193849&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Thu Oct 31 21:01:01 2013
@@ -109,13 +109,15 @@ NamedDecl *Parser::ParseCXXInlineMethodD
 
     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)) &&

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=193849&r1=193848&r2=193849&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Thu Oct 31 21:01:01 2013
@@ -919,6 +919,26 @@ Parser::ParseDeclarationOrFunctionDefini
   }
 }
 
+
+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 @@ Decl *Parser::ParseFunctionDefinition(Pa
   // 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);

Modified: cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp?rev=193849&r1=193848&r2=193849&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp Thu Oct 31 21:01:01 2013
@@ -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 @@ namespace CurrentInstantiation {
   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 @@ namespace WithDefaultArgs {
   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); }
+
+}

Modified: cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp?rev=193849&r1=193848&r2=193849&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp Thu Oct 31 21:01:01 2013
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only %s
-// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
-// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
-// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
 
 namespace explicit_call {
 int test() {
@@ -560,6 +560,48 @@ namespace at_ns_scope_within_class_membe
 };
 X x;
 auto L = x.test();
+auto L_test = L('4');
+auto M = L('3');
+auto M_test = M('a');
+auto N = M('x');
+auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
+char (*np)(const char*, int, const char*, double, const char*, int) = O;
+auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456);
+int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}}
+  
+} //end at_ns_scope_within_class_member
+
+
+namespace at_ns_scope_within_class_template_member {
+ struct X {
+  static void foo(double d) { } 
+  template<class T = int>
+  auto test(T = T{}) {
+    auto L = [](auto a) {
+      print("a = ", a, "\n");
+      foo(a);
+      return [](decltype(a) b) {
+        foo(b);
+        foo(sizeof(a) + sizeof(b));
+        return [](auto ... c) {
+          print("c = ", c ..., "\n");
+          foo(decltype(b){});
+          foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
+          return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}}
+            print("d = ", d ..., "\n");
+            foo(decltype(b){});
+            foo(sizeof(decltype(a)*) + sizeof(decltype(b)*));
+            return decltype(a){};
+          };
+        };
+      };
+    };
+    return L;
+  }
+  
+};
+X x;
+auto L = x.test();
 auto L_test = L('4');
 auto M = L('3');
 auto M_test = M('a');





More information about the cfe-commits mailing list