mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-07 16:42:34 +00:00
PR10405 - Desugar FunctionType and TemplateSpecializationType if any type that appears inside needs to be desugared.
llvm-svn: 242371
This commit is contained in:
parent
e2041b68b1
commit
fa00728f58
@ -66,11 +66,63 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
|
||||
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. Preserve nullability attribute on desugared types.
|
||||
if (const FunctionType *FT = dyn_cast<FunctionType>(Ty)) {
|
||||
bool DesugarReturn = false;
|
||||
QualType SugarRT = FT->getReturnType();
|
||||
QualType RT = Desugar(Context, SugarRT, DesugarReturn);
|
||||
if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {
|
||||
RT = Context.getAttributedType(
|
||||
AttributedType::getNullabilityAttrKind(*nullability), RT, RT);
|
||||
}
|
||||
|
||||
bool DesugarArgument = false;
|
||||
SmallVector<QualType, 4> Args;
|
||||
const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT);
|
||||
if (FPT) {
|
||||
for (QualType SugarPT : FPT->param_types()) {
|
||||
QualType PT = Desugar(Context, SugarPT, DesugarArgument);
|
||||
if (auto nullability =
|
||||
AttributedType::stripOuterNullability(SugarPT)) {
|
||||
PT = Context.getAttributedType(
|
||||
AttributedType::getNullabilityAttrKind(*nullability), PT, PT);
|
||||
}
|
||||
Args.push_back(PT);
|
||||
}
|
||||
}
|
||||
|
||||
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() ||
|
||||
|
@ -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)'
|
||||
|
@ -45,3 +45,20 @@ void helper(callback cb) {} // expected-note{{candidate function not viable: no
|
||||
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'}}
|
||||
|
@ -47,6 +47,7 @@ typedef _Nonnull int *(^ block_type_3)(int, int);
|
||||
typedef _Nonnull int *(* function_pointer_type_3)(int, int);
|
||||
typedef _Nonnull int_ptr (^ block_type_4)(int, int);
|
||||
typedef _Nonnull int_ptr (* function_pointer_type_4)(int, int);
|
||||
typedef void (* function_pointer_type_5)(int_ptr _Nonnull);
|
||||
|
||||
void acceptFunctionPtr(_Nonnull int *(*)(void));
|
||||
void acceptBlockPtr(_Nonnull int *(^)(void));
|
||||
@ -55,7 +56,8 @@ void testBlockFunctionPtrNullability() {
|
||||
float *fp;
|
||||
fp = (function_pointer_type_3)0; // expected-warning{{from 'function_pointer_type_3' (aka 'int * _Nonnull (*)(int, int)')}}
|
||||
fp = (block_type_3)0; // expected-error{{from incompatible type 'block_type_3' (aka 'int * _Nonnull (^)(int, int)')}}
|
||||
fp = (function_pointer_type_4)0; // expected-warning{{from 'function_pointer_type_4' (aka 'int_ptr _Nonnull (*)(int, int)')}}
|
||||
fp = (function_pointer_type_4)0; // expected-warning{{from 'function_pointer_type_4' (aka 'int * _Nonnull (*)(int, int)')}}
|
||||
fp = (function_pointer_type_5)0; // expected-warning{{from 'function_pointer_type_5' (aka 'void (*)(int * _Nonnull)')}}
|
||||
fp = (block_type_4)0; // expected-error{{from incompatible type 'block_type_4' (aka 'int_ptr _Nonnull (^)(int, int)')}}
|
||||
|
||||
acceptFunctionPtr(0); // no-warning
|
||||
|
@ -14,10 +14,10 @@ void a(S* b, void* c) {
|
||||
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}}
|
||||
}
|
||||
|
@ -9,9 +9,9 @@ A<int, FLOAT> *foo(A<int> *ptr, A<int> const *ptr2, A<int, double> *ptr3) {
|
||||
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> *'}}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user