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(Ty)) - if (!TST->isTypeAlias()) + // Desugar FunctionType if return type or any parameter type should be + // desugared. + if (const FunctionType *FT = dyn_cast(Ty)) { + bool DesugarReturn = false; + QualType RT = Desugar(Context, FT->getReturnType(), DesugarReturn); + + bool DesugarArgument = false; + SmallVector Args; + const FunctionProtoType *FPT = dyn_cast(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(Ty)) { + if (!TST->isTypeAlias()) { + bool DesugarArgument = false; + SmallVector 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 +class A {}; + +int a1 = A(); // expected-error{{no viable conversion from 'A' (aka 'A') to 'int'}} +int a2 = A>(); // expected-error{{no viable conversion from 'A >' (aka 'A >') to 'int'}} +int a3 = A<__typeof(1 + 2)>(); // expected-error{{no viable conversion from 'A' (aka 'A') to 'int'}} +int a4 = A>(); // expected-error{{no viable conversion from 'A >' (aka 'A >') to 'int'}} + +using B = A; +int a5 = B(); // expected-error{{no viable conversion from 'B' (aka 'A') 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 *' with an lvalue of type 'const A *'}} + return ptr2; // expected-error{{cannot initialize return object of type 'A *' (aka 'A *') with an lvalue of type 'const A *'}} else { - return ptr3; // expected-error{{cannot initialize return object of type 'A *' with an lvalue of type 'A *'}} + return ptr3; // expected-error{{cannot initialize return object of type 'A *' (aka 'A *') with an lvalue of type 'A *'}} } }