From c4a839101e883261d038a1d5ea718dd46abd1d2d Mon Sep 17 00:00:00 2001
From: Richard Smith <richard-llvm@metafoo.co.uk>
Date: Mon, 1 Oct 2012 20:35:07 +0000
Subject: [PATCH] PR13978: A 'decltype' DeclSpec has an expression
 representation, not a type representation. Fix crash if it appears in the
 return type of a member function definition.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164967 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaDecl.cpp                          |  2 +-
 test/SemaCXX/decltype-overloaded-functions.cpp | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 593c110c8a2..4382432a6fe 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3400,7 +3400,6 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
   switch (DS.getTypeSpecType()) {
   case DeclSpec::TST_typename:
   case DeclSpec::TST_typeofType:
-  case DeclSpec::TST_decltype:
   case DeclSpec::TST_underlyingType:
   case DeclSpec::TST_atomic: {
     // Grab the type from the parser.
@@ -3424,6 +3423,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
     break;
   }
 
+  case DeclSpec::TST_decltype:
   case DeclSpec::TST_typeofExpr: {
     Expr *E = DS.getRepAsExpr();
     ExprResult Result = S.RebuildExprInCurrentInstantiation(E);
diff --git a/test/SemaCXX/decltype-overloaded-functions.cpp b/test/SemaCXX/decltype-overloaded-functions.cpp
index b0a43a999bb..2ed4465b5b9 100644
--- a/test/SemaCXX/decltype-overloaded-functions.cpp
+++ b/test/SemaCXX/decltype-overloaded-functions.cpp
@@ -13,3 +13,18 @@ struct K {
   void f(int); // expected-note{{possible target for call}}
 };
 S<K> b; // expected-note{{in instantiation of template class 'S<K>' requested here}}
+
+namespace PR13978 {
+  template<typename T> struct S { decltype(1) f(); };
+  template<typename T> decltype(1) S<T>::f() { return 1; }
+
+  // This case is ill-formed (no diagnostic required) because the decltype
+  // expressions are functionally equivalent but not equivalent. It would
+  // be acceptable for us to reject this case.
+  template<typename T> struct U { struct A {}; decltype(A{}) f(); };
+  template<typename T> decltype(typename U<T>::A{}) U<T>::f() {}
+
+  // This case is valid.
+  template<typename T> struct V { struct A {}; decltype(typename V<T>::A{}) f(); };
+  template<typename T> decltype(typename V<T>::A{}) V<T>::f() {}
+}
-- 
GitLab