It's been some time since we looked at this.

I'm having issues addressing your last comment, non type template parameters. 
What's the idea here, to turn A<1+2> into A<int>? While tinkering with this I 
managed to produce desugar A<1+2> as A<3> by accident so I'm not really sure 
what you meant.

I was surprised to see that both A<1> and A<1+2> have a TemplateArgument with 
Expression kind. Having 'aka A<int>' for each A<1> seems too spammy but I 
couldn't figure out how to differentiate them.


http://reviews.llvm.org/D3588

Files:
  lib/AST/ASTDiagnostic.cpp
  test/ASTMerge/function.c
  test/Misc/diag-aka-types.cpp
  test/Sema/pointer-addition.c
  test/SemaTemplate/class-template-id.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lib/AST/ASTDiagnostic.cpp
===================================================================
--- lib/AST/ASTDiagnostic.cpp
+++ lib/AST/ASTDiagnostic.cpp
@@ -66,11 +66,51 @@
       continue;
     }
 
-    // Don't desugar template specializations, unless it's an alias template.
-    if (const TemplateSpecializationType *TST
-          = dyn_cast<TemplateSpecializationType>(Ty))
-      if (!TST->isTypeAlias())
+    // Desugar FunctionType if return type or any parameter type should be
+    // desugared.
+    if (const FunctionType *FT = dyn_cast<FunctionType>(Ty)) {
+      bool DesugarReturn = false;
+      QualType RT = Desugar(Context, FT->getReturnType(), DesugarReturn);
+
+      bool DesugarArgument = false;
+      SmallVector<QualType, 4> Args;
+      const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT);
+      if (FPT) {
+        for (const auto &ParamType : FPT->param_types())
+          Args.push_back(Desugar(Context, ParamType, DesugarArgument));
+      }
+
+      if (DesugarReturn || DesugarArgument) {
+        ShouldAKA = true;
+        QT = FPT ? Context.getFunctionType(RT, Args, FPT->getExtProtoInfo())
+                 : Context.getFunctionNoProtoType(RT, FT->getExtInfo());
         break;
+      }
+    }
+
+    // Desugar template specializations if any template argument should be
+    // desugared.
+    if (const TemplateSpecializationType *TST =
+            dyn_cast<TemplateSpecializationType>(Ty)) {
+      if (!TST->isTypeAlias()) {
+        bool DesugarArgument = false;
+        SmallVector<TemplateArgument, 4> Args;
+        for (unsigned I = 0, N = TST->getNumArgs(); I != N; ++I) {
+          const TemplateArgument &Arg = TST->getArg(I);
+          if (Arg.getKind() == TemplateArgument::Type)
+            Args.push_back(Desugar(Context, Arg.getAsType(), DesugarArgument));
+          else
+            Args.push_back(Arg);
+        }
+
+        if (DesugarArgument) {
+          ShouldAKA = true;
+          QT = Context.getTemplateSpecializationType(
+              TST->getTemplateName(), Args.data(), Args.size(), QT);
+        }
+        break;
+      }
+    }
 
     // Don't desugar magic Objective-C types.
     if (QualType(Ty,0) == Context.getObjCIdType() ||
Index: test/ASTMerge/function.c
===================================================================
--- test/ASTMerge/function.c
+++ test/ASTMerge/function.c
@@ -3,7 +3,7 @@
 // RUN: not %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only -verify %s
 
-// CHECK: function2.c:3:6: error: external function 'f1' declared with incompatible types in different translation units ('void (Int, double)' vs. 'void (int, float)')
+// CHECK: function2.c:3:6: error: external function 'f1' declared with incompatible types in different translation units ('void (Int, double)' (aka 'void (int, double)') vs. 'void (int, float)')
 // CHECK: function1.c:2:6: note: declared here with type 'void (int, float)'
 // CHECK: function2.c:5:6: error: external function 'f3' declared with incompatible types in different translation units ('void (int)' vs. 'void (void)')
 // CHECK: function1.c:4:6: note: declared here with type 'void (void)'
Index: test/Misc/diag-aka-types.cpp
===================================================================
--- test/Misc/diag-aka-types.cpp
+++ test/Misc/diag-aka-types.cpp
@@ -45,3 +45,20 @@
 void test() {
  helper(&ns::str::method); // expected-error{{no matching function for call to 'helper'}}
 }
+
+template <typename T>
+class A {};
+
+int a1 = A<decltype(1 + 2)>(); // expected-error{{no viable conversion from 'A<decltype(1 + 2)>' (aka 'A<int>') to 'int'}}
+int a2 = A<A<decltype(1 + 2)>>(); // expected-error{{no viable conversion from 'A<A<decltype(1 + 2)> >' (aka 'A<A<int> >') to 'int'}}
+int a3 = A<__typeof(1 + 2)>(); // expected-error{{no viable conversion from 'A<typeof (1 + 2)>' (aka 'A<int>') to 'int'}}
+int a4 = A<A<__typeof(1 + 2)>>(); // expected-error{{no viable conversion from 'A<A<typeof (1 + 2)> >' (aka 'A<A<int> >') to 'int'}}
+
+using B = A<decltype(1+2)>;
+int a5 = B(); // expected-error{{no viable conversion from 'B' (aka 'A<int>') to 'int'}}
+
+decltype(void()) (&f1)() = 0; // expected-error{{non-const lvalue reference to type 'decltype(void()) ()' (aka 'void ()') cannot bind to a temporary of type 'int'}}
+decltype(void()) (&f2)(int) = 0; // expected-error{{non-const lvalue reference to type 'decltype(void()) (int)' (aka 'void (int)') cannot bind to a temporary of type 'int'}}
+void (&f3)(decltype(1 + 2)) = 0; // expected-error{{non-const lvalue reference to type 'void (decltype(1 + 2))' (aka 'void (int)') cannot bind to a temporary of type 'int'}}
+decltype(1+2) (&f4)(double, decltype(1 + 2)) = 0; // expected-error{{non-const lvalue reference to type 'decltype(1 + 2) (double, decltype(1 + 2))' (aka 'int (double, int)') cannot bind to a temporary of type 'int'}}
+auto (&f5)() -> decltype(1+2) = 0; // expected-error{{non-const lvalue reference to type 'auto () -> decltype(1 + 2)' (aka 'auto () -> int') cannot bind to a temporary of type 'int'}}
Index: test/Sema/pointer-addition.c
===================================================================
--- test/Sema/pointer-addition.c
+++ test/Sema/pointer-addition.c
@@ -14,10 +14,10 @@
   b = 1+b;   // expected-error {{arithmetic on a pointer to an incomplete type}}
   /* The next couple tests are only pedantic warnings in gcc */
   void (*d)(S*,void*) = a;
-  d += 1;    // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' is a GNU extension}}
-  d++;       // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' is a GNU extension}}
-  d--;       // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' is a GNU extension}}
-  d -= 1;    // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' is a GNU extension}}
-  (void)(1 + d); // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' is a GNU extension}}
+  d += 1;    // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
+  d++;       // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
+  d--;       // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
+  d -= 1;    // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
+  (void)(1 + d); // expected-warning {{arithmetic on a pointer to the function type 'void (S *, void *)' (aka 'void (struct S *, void *)') is a GNU extension}}
   e++;       // expected-error {{arithmetic on a pointer to an incomplete type}}
 }
Index: test/SemaTemplate/class-template-id.cpp
===================================================================
--- test/SemaTemplate/class-template-id.cpp
+++ test/SemaTemplate/class-template-id.cpp
@@ -9,9 +9,9 @@
   if (ptr)
     return ptr; // okay
   else if (ptr2)
-    return ptr2; // expected-error{{cannot initialize return object of type 'A<int, FLOAT> *' with an lvalue of type 'const A<int> *'}}
+    return ptr2; // expected-error{{cannot initialize return object of type 'A<int, FLOAT> *' (aka 'A<int, float> *') with an lvalue of type 'const A<int> *'}}
   else {
-    return ptr3; // expected-error{{cannot initialize return object of type 'A<int, FLOAT> *' with an lvalue of type 'A<int, double> *'}}
+    return ptr3; // expected-error{{cannot initialize return object of type 'A<int, FLOAT> *' (aka 'A<int, float> *') with an lvalue of type 'A<int, double> *'}}
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to