[PATCH] [Sema] Re-land "Make FunctionType's TSI use unadjusted argument types"
Reid Kleckner
rnk at google.com
Tue Jun 11 13:27:45 PDT 2013
- Reorder the type adjustment and add a test for it.
http://llvm-reviews.chandlerc.com/D957
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D957?vs=2360&id=2362#toc
Files:
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaType.cpp
test/Index/print-type.c
test/Index/print-type.cpp
test/Sema/function-redecl.c
test/Sema/function.c
test/SemaCXX/incomplete-call.cpp
test/SemaObjCXX/arc-type-conversion.mm
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5897,20 +5897,40 @@
<< DeclSpec::getSpecifierName(TSCS);
// Do not allow returning a objc interface by-value.
- if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) {
+ bool NeedsAdjustment = false;
+ const FunctionType *FT = R->castAs<FunctionType>();
+ QualType ResultTy = FT->getResultType();
+ if (ResultTy->isObjCObjectType()) {
Diag(D.getIdentifierLoc(),
- diag::err_object_cannot_be_passed_returned_by_value) << 0
- << R->getAs<FunctionType>()->getResultType()
- << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
+ diag::err_object_cannot_be_passed_returned_by_value) << 0 << ResultTy
+ << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
+ ResultTy = Context.getObjCObjectPointerType(ResultTy);
+ NeedsAdjustment = true;
+ }
- QualType T = R->getAs<FunctionType>()->getResultType();
- T = Context.getObjCObjectPointerType(T);
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) {
+ // Adjust parameter types from the type as written.
+ SmallVector<QualType, 16> AdjustedParms;
+ const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT);
+ if (FPT) {
+ for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(),
+ E = FPT->arg_type_end();
+ I != E; ++I) {
+ AdjustedParms.push_back(Context.getAdjustedParameterType(*I));
+ NeedsAdjustment |= AdjustedParms.back() != *I;
+ }
+ }
+
+ // Skip the type recreation if it isn't needed, for performance and to avoid
+ // prematurely desugaring things like typedefs and __typeofs.
+ if (NeedsAdjustment) {
+ if (FPT) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- R = Context.getFunctionType(T, FPT->getArgTypes(), EPI);
+ R = Context.getFunctionType(ResultTy, AdjustedParms, EPI);
+ } else {
+ assert(isa<FunctionNoProtoType>(FT));
+ FunctionType::ExtInfo EI = FT->getExtInfo();
+ R = Context.getFunctionNoProtoType(ResultTy, EI);
}
- else if (isa<FunctionNoProtoType>(R))
- R = Context.getFunctionNoProtoType(T);
}
bool isFriend = false;
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -3935,6 +3935,9 @@
if (ArgIx < Args.size()) {
Arg = Args[ArgIx++];
+ // Decay array and function types to pointers.
+ ProtoArgType = Context.getAdjustedParameterType(ProtoArgType);
+
if (RequireCompleteType(Arg->getLocStart(),
ProtoArgType,
diag::err_call_incomplete_argument, Arg))
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -1674,7 +1674,7 @@
bool Invalid = false;
for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) {
// FIXME: Loc is too inprecise here, should use proper locations for args.
- QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
+ QualType ParamType = ParamTypes[Idx];
if (ParamType->isVoidType()) {
Diag(Loc, diag::err_param_with_void_type);
Invalid = true;
@@ -2798,13 +2798,10 @@
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
- QualType ArgTy = Param->getType();
+ // If this is an array or function type, callers will adjust it later.
+ QualType ArgTy = Param->getTypeSourceInfo()->getType();
assert(!ArgTy.isNull() && "Couldn't parse type?");
- // Adjust the parameter type.
- assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) &&
- "Unadjusted type?");
-
// Look for 'void'. void is allowed only as a single argument to a
// function with no other parameters (C99 6.7.5.3p10). We record
// int(void) as a FunctionProtoType with an empty argument list.
Index: test/Index/print-type.c
===================================================================
--- test/Index/print-type.c
+++ test/Index/print-type.c
@@ -11,7 +11,7 @@
typedef int __attribute__((vector_size(16))) int4_t;
// RUN: c-index-test -test-print-type %s | FileCheck %s
-// CHECK: FunctionDecl=f:3:6 (Definition) [type=int *(int *, char *, FooType, int *, void (*)(int))] [typekind=FunctionProto] [canonicaltype=int *(int *, char *, int, int *, void (*)(int))] [canonicaltypekind=FunctionProto] [resulttype=int *] [resulttypekind=Pointer] [args= [int *] [Pointer] [char *] [Pointer] [FooType] [Typedef] [int [5]] [ConstantArray] [void (*)(int)] [Pointer]] [isPOD=0]
+// CHECK: FunctionDecl=f:3:6 (Definition) [type=int *(int *, char *, FooType, int [5], void (*)(int))] [typekind=FunctionProto] [canonicaltype=int *(int *, char *, int, int *, void (*)(int))] [canonicaltypekind=FunctionProto] [resulttype=int *] [resulttypekind=Pointer] [args= [int *] [Pointer] [char *] [Pointer] [FooType] [Typedef] [int [5]] [ConstantArray] [void (*)(int)] [Pointer]] [isPOD=0]
// CHECK: ParmDecl=p:3:13 (Definition) [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: ParmDecl=x:3:22 (Definition) [type=char *] [typekind=Pointer] [isPOD=1]
// CHECK: ParmDecl=z:3:33 (Definition) [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
Index: test/Index/print-type.cpp
===================================================================
--- test/Index/print-type.cpp
+++ test/Index/print-type.cpp
@@ -62,5 +62,5 @@
// CHECK: TypedefDecl=ArrayType:20:15 (Definition) [type=ArrayType] [typekind=Typedef] [canonicaltype=int [5]] [canonicaltypekind=ConstantArray] [isPOD=1]
// CHECK: FunctionTemplate=tbar:27:3 [type=T (int)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0]
// CHECK: TemplateTypeParameter=T:26:20 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
-// CHECK: FunctionTemplate=tbar:30:3 [type=T (int *)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int *)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0]
+// CHECK: FunctionTemplate=tbar:30:3 [type=T (int [5])] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int *)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0]
// CHECK: ParmDecl=:30:11 (Definition) [type=int [5]] [typekind=ConstantArray] [isPOD=1]
Index: test/Sema/function-redecl.c
===================================================================
--- test/Sema/function-redecl.c
+++ test/Sema/function-redecl.c
@@ -115,6 +115,11 @@
extern __typeof (i0) i1;
extern __typeof (i1) i1;
+// Try __typeof with a parameter that needs adjustment.
+void j0 (int a0[1], ...);
+extern __typeof (j0) j1;
+extern __typeof (j1) j1;
+
typedef int a();
typedef int a2(int*);
a x;
Index: test/Sema/function.c
===================================================================
--- test/Sema/function.c
+++ test/Sema/function.c
@@ -103,3 +103,11 @@
}
return x + 3;
}
+
+void t22(void (*take_array(int array[1]))) {
+ int arr[1];
+ take_array(arr);
+}
+
+struct incomplete_elt; // expected-note {{forward declaration of 'struct incomplete_elt'}}
+void t23(struct incomplete_elt arr[3]); // expected-error {{array has incomplete element type 'struct incomplete_elt'}}
Index: test/SemaCXX/incomplete-call.cpp
===================================================================
--- test/SemaCXX/incomplete-call.cpp
+++ test/SemaCXX/incomplete-call.cpp
@@ -47,3 +47,8 @@
void test_incomplete_object_call(C& c) {
c(); // expected-error{{incomplete type in call to object of type}}
}
+
+struct D;
+void test_incomplete_array_call(void (*fp)(D arr[3]), D *p) {
+ fp(p);
+}
Index: test/SemaObjCXX/arc-type-conversion.mm
===================================================================
--- test/SemaObjCXX/arc-type-conversion.mm
+++ test/SemaObjCXX/arc-type-conversion.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -fblocks %s
// rdar://8843600
-void * cvt(id arg) // expected-note{{candidate function not viable: cannot convert argument of incomplete type 'void *' to '__strong id'}}
+void * cvt(id arg) // expected-note{{candidate function not viable: cannot convert argument of incomplete type 'void *' to 'id'}}
{
void* voidp_val;
(void)(int*)arg; // expected-error {{cast of an Objective-C pointer to 'int *' is disallowed with ARC}}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D957.3.patch
Type: text/x-patch
Size: 8871 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130611/7983510c/attachment.bin>
More information about the cfe-commits
mailing list