[PATCH] [Sema] Re-land "Make FunctionType's TSI use unadjusted argument types"

Eli Friedman eli.friedman at gmail.com
Tue Jun 11 13:01:36 PDT 2013


@@ -3940,6 +3940,9 @@
                               diag::err_call_incomplete_argument, Arg))
         return true;

+      // Decay array and function types to pointers.
+      ProtoArgType = Context.getAdjustedParameterType(ProtoArgType);

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.

-Eli


On Tue, Jun 11, 2013 at 12:49 PM, Reid Kleckner <rnk at google.com> wrote:

>     - Move adjustment out to GatherArgumentsForCall.
>
> http://llvm-reviews.chandlerc.com/D957
>
> CHANGE SINCE LAST DIFF
>   http://llvm-reviews.chandlerc.com/D957?vs=2358&id=2360#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/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
> @@ -3940,6 +3940,9 @@
>                                diag::err_call_incomplete_argument, Arg))
>          return true;
>
> +      // Decay array and function types to pointers.
> +      ProtoArgType = Context.getAdjustedParameterType(ProtoArgType);
> +
>        // Pass the argument
>        Param = 0;
>        if (FDecl && i < FDecl->getNumParams())
> 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,8 @@
>    }
>    return x + 3;
>  }
> +
> +void t22(void (*take_array(int array[1]))) {
> +  int arr[1];
> +  take_array(arr);
> +}
> 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 --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130611/be70c604/attachment.html>


More information about the cfe-commits mailing list