<div dir="ltr"><span style="font-family:arial,sans-serif;font-size:13px">@@ -3940,6 +3940,9 @@</span><br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px">                               diag::err_call_incomplete_</span><span style="font-family:arial,sans-serif;font-size:13px">argument, Arg))</span><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px">         return true;</span><br style="font-family:arial,sans-serif;font-size:13px"><br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px">+      // Decay array and function types to pointers.</span><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px">+      ProtoArgType = Context.</span><span style="font-family:arial,sans-serif;font-size:13px">getAdjustedParameterType(</span><span style="font-family:arial,sans-serif;font-size:13px">ProtoArgType);</span><br style="font-family:arial,sans-serif;font-size:13px">
<br style="font-family:arial,sans-serif;font-size:13px"><div><font face="arial, sans-serif">You have to decay the type before the RequireCompleteType call, else you'll reject a call to a function like "void f(A x[2]);", where A is incomplete.</font></div>
<div><font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">-Eli</font></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Jun 11, 2013 at 12:49 PM, Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">    - Move adjustment out to GatherArgumentsForCall.<br>
<br>
<a href="http://llvm-reviews.chandlerc.com/D957" target="_blank">http://llvm-reviews.chandlerc.com/D957</a><br>
<br>
CHANGE SINCE LAST DIFF<br>
  <a href="http://llvm-reviews.chandlerc.com/D957?vs=2358&id=2360#toc" target="_blank">http://llvm-reviews.chandlerc.com/D957?vs=2358&id=2360#toc</a><br>
<br>
Files:<br>
  lib/Sema/SemaDecl.cpp<br>
  lib/Sema/SemaExpr.cpp<br>
<div class="im">  lib/Sema/SemaType.cpp<br>
  test/Index/print-type.c<br>
  test/Index/print-type.cpp<br>
  test/Sema/function-redecl.c<br>
  test/Sema/function.c<br>
</div>  test/SemaObjCXX/<a href="http://arc-type-conversion.mm" target="_blank">arc-type-conversion.mm</a><br>
<br>
Index: lib/Sema/SemaDecl.cpp<br>
===================================================================<br>
--- lib/Sema/SemaDecl.cpp<br>
+++ lib/Sema/SemaDecl.cpp<br>
@@ -5897,20 +5897,40 @@<br>
       << DeclSpec::getSpecifierName(TSCS);<br>
<br>
   // Do not allow returning a objc interface by-value.<br>
-  if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) {<br>
+  bool NeedsAdjustment = false;<br>
+  const FunctionType *FT = R->castAs<FunctionType>();<br>
+  QualType ResultTy = FT->getResultType();<br>
+  if (ResultTy->isObjCObjectType()) {<br>
     Diag(D.getIdentifierLoc(),<br>
-         diag::err_object_cannot_be_passed_returned_by_value) << 0<br>
-    << R->getAs<FunctionType>()->getResultType()<br>
-    << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");<br>
+         diag::err_object_cannot_be_passed_returned_by_value) << 0 << ResultTy<br>
+        << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");<br>
+    ResultTy = Context.getObjCObjectPointerType(ResultTy);<br>
+    NeedsAdjustment = true;<br>
+  }<br>
<br>
-    QualType T = R->getAs<FunctionType>()->getResultType();<br>
-    T = Context.getObjCObjectPointerType(T);<br>
-    if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) {<br>
+  // Adjust parameter types from the type as written.<br>
+  SmallVector<QualType, 16> AdjustedParms;<br>
+  const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT);<br>
+  if (FPT) {<br>
+    for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(),<br>
+                                              E = FPT->arg_type_end();<br>
+         I != E; ++I) {<br>
+      AdjustedParms.push_back(Context.getAdjustedParameterType(*I));<br>
+      NeedsAdjustment |= AdjustedParms.back() != *I;<br>
+    }<br>
+  }<br>
+<br>
+  // Skip the type recreation if it isn't needed, for performance and to avoid<br>
+  // prematurely desugaring things like typedefs and __typeofs.<br>
+  if (NeedsAdjustment) {<br>
+    if (FPT) {<br>
       FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();<br>
-      R = Context.getFunctionType(T, FPT->getArgTypes(), EPI);<br>
+      R = Context.getFunctionType(ResultTy, AdjustedParms, EPI);<br>
+    } else {<br>
+      assert(isa<FunctionNoProtoType>(FT));<br>
+      FunctionType::ExtInfo EI = FT->getExtInfo();<br>
+      R = Context.getFunctionNoProtoType(ResultTy, EI);<br>
     }<br>
-    else if (isa<FunctionNoProtoType>(R))<br>
-      R = Context.getFunctionNoProtoType(T);<br>
   }<br>
<br>
   bool isFriend = false;<br>
Index: lib/Sema/SemaExpr.cpp<br>
===================================================================<br>
--- lib/Sema/SemaExpr.cpp<br>
+++ lib/Sema/SemaExpr.cpp<br>
@@ -3940,6 +3940,9 @@<br>
                               diag::err_call_incomplete_argument, Arg))<br>
         return true;<br>
<br>
+      // Decay array and function types to pointers.<br>
+      ProtoArgType = Context.getAdjustedParameterType(ProtoArgType);<br>
+<br>
       // Pass the argument<br>
       Param = 0;<br>
       if (FDecl && i < FDecl->getNumParams())<br>
Index: lib/Sema/SemaType.cpp<br>
===================================================================<br>
--- lib/Sema/SemaType.cpp<br>
+++ lib/Sema/SemaType.cpp<br>
@@ -1674,7 +1674,7 @@<br>
   bool Invalid = false;<br>
   for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) {<br>
     // FIXME: Loc is too inprecise here, should use proper locations for args.<br>
-    QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);<br>
+    QualType ParamType = ParamTypes[Idx];<br>
     if (ParamType->isVoidType()) {<br>
       Diag(Loc, diag::err_param_with_void_type);<br>
       Invalid = true;<br>
@@ -2798,13 +2798,10 @@<br>
<br>
         for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {<br>
           ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);<br>
-          QualType ArgTy = Param->getType();<br>
+          // If this is an array or function type, callers will adjust it later.<br>
+          QualType ArgTy = Param->getTypeSourceInfo()->getType();<br>
           assert(!ArgTy.isNull() && "Couldn't parse type?");<br>
<br>
-          // Adjust the parameter type.<br>
-          assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) &&<br>
-                 "Unadjusted type?");<br>
-<br>
           // Look for 'void'.  void is allowed only as a single argument to a<br>
           // function with no other parameters (C99 6.7.5.3p10).  We record<br>
           // int(void) as a FunctionProtoType with an empty argument list.<br>
Index: test/Index/print-type.c<br>
===================================================================<br>
--- test/Index/print-type.c<br>
+++ test/Index/print-type.c<br>
@@ -11,7 +11,7 @@<br>
 typedef int __attribute__((vector_size(16))) int4_t;<br>
<br>
 // RUN: c-index-test -test-print-type %s | FileCheck %s<br>
-// 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]<br>

+// 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]<br>

 // CHECK: ParmDecl=p:3:13 (Definition) [type=int *] [typekind=Pointer] [isPOD=1]<br>
 // CHECK: ParmDecl=x:3:22 (Definition) [type=char *] [typekind=Pointer] [isPOD=1]<br>
 // CHECK: ParmDecl=z:3:33 (Definition) [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]<br>
Index: test/Index/print-type.cpp<br>
===================================================================<br>
--- test/Index/print-type.cpp<br>
+++ test/Index/print-type.cpp<br>
@@ -62,5 +62,5 @@<br>
 // CHECK: TypedefDecl=ArrayType:20:15 (Definition) [type=ArrayType] [typekind=Typedef] [canonicaltype=int [5]] [canonicaltypekind=ConstantArray] [isPOD=1]<br>
 // CHECK: FunctionTemplate=tbar:27:3 [type=T (int)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0]<br>
 // CHECK: TemplateTypeParameter=T:26:20 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]<br>
-// CHECK: FunctionTemplate=tbar:30:3 [type=T (int *)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int *)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0]<br>
+// 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]<br>
 // CHECK: ParmDecl=:30:11 (Definition) [type=int [5]] [typekind=ConstantArray] [isPOD=1]<br>
Index: test/Sema/function-redecl.c<br>
===================================================================<br>
--- test/Sema/function-redecl.c<br>
+++ test/Sema/function-redecl.c<br>
@@ -115,6 +115,11 @@<br>
 extern __typeof (i0) i1;<br>
 extern __typeof (i1) i1;<br>
<br>
+// Try __typeof with a parameter that needs adjustment.<br>
+void j0 (int a0[1], ...);<br>
+extern __typeof (j0) j1;<br>
+extern __typeof (j1) j1;<br>
+<br>
 typedef int a();<br>
 typedef int a2(int*);<br>
 a x;<br>
Index: test/Sema/function.c<br>
===================================================================<br>
--- test/Sema/function.c<br>
+++ test/Sema/function.c<br>
@@ -103,3 +103,8 @@<br>
   }<br>
   return x + 3;<br>
 }<br>
+<br>
+void t22(void (*take_array(int array[1]))) {<br>
+  int arr[1];<br>
+  take_array(arr);<br>
+}<br>
Index: test/SemaObjCXX/<a href="http://arc-type-conversion.mm" target="_blank">arc-type-conversion.mm</a><br>
===================================================================<br>
--- test/SemaObjCXX/<a href="http://arc-type-conversion.mm" target="_blank">arc-type-conversion.mm</a><br>
+++ test/SemaObjCXX/<a href="http://arc-type-conversion.mm" target="_blank">arc-type-conversion.mm</a><br>
@@ -1,7 +1,7 @@<br>
 // RUN: %clang_cc1 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -fblocks %s<br>
 // rdar://8843600<br>
<br>
-void * cvt(id arg) // expected-note{{candidate function not viable: cannot convert argument of incomplete type 'void *' to '__strong id'}}<br>
+void * cvt(id arg) // expected-note{{candidate function not viable: cannot convert argument of incomplete type 'void *' to 'id'}}<br>
 {<br>
   void* voidp_val;<br>
   (void)(int*)arg; // expected-error {{cast of an Objective-C pointer to 'int *' is disallowed with ARC}}<br>
</blockquote></div><br></div>