From aa0373107968aa7a26bf63f4a2673b8325b800af Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 22 Dec 2009 07:24:36 +0000 Subject: [PATCH] Switch initialization of parameters in a call over to InitializationSequence (when a FunctionDecl is present). This required a few small fixes to initialization sequences: - Make sure to use the adjusted parameter type for initialization of function parameters. - Implement transparent union calling semantics in C git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91902 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 16 +++++++++++-- lib/Sema/SemaInit.cpp | 23 +++++++++++++++---- test/SemaCXX/conditional-expr.cpp | 11 ++++----- test/SemaCXX/elaborated-type-specifier.cpp | 2 +- test/SemaCXX/member-location.cpp | 2 +- test/SemaObjCXX/blocks.mm | 4 ++-- .../instantiate-member-template.cpp | 2 +- 7 files changed, 43 insertions(+), 17 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 181d6d1c8f..718d5ab577 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3182,8 +3182,20 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, return true; // Pass the argument. - if (PerformCopyInitialization(Arg, ProtoArgType, AA_Passing)) - return true; + if (FDecl && i < FDecl->getNumParams()) { + ParmVarDecl *Param = FDecl->getParamDecl(i); + InitializedEntity Entity =InitializedEntity::InitializeParameter(Param); + OwningExprResult ArgE = PerformCopyInitialization(Entity, + SourceLocation(), + Owned(Arg)); + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs(); + } else { + if (PerformCopyInitialization(Arg, ProtoArgType, AA_Passing)) + return true; + } if (!ProtoArgType->isReferenceType()) Arg = MaybeBindToTemporary(Arg).takeAs(); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 80cfc3637e..f831b41512 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1811,8 +1811,15 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, void InitializedEntity::InitDeclLoc() { assert((Kind == EK_Variable || Kind == EK_Parameter || Kind == EK_Member) && "InitDeclLoc cannot be used with non-declaration entities."); - - if (TypeSourceInfo *DI = VariableOrMember->getTypeSourceInfo()) { + + ASTContext &Context = VariableOrMember->getASTContext(); + if (Kind == EK_Parameter && + !Context.hasSameUnqualifiedType( + cast(VariableOrMember)->getOriginalType(), + VariableOrMember->getType())) { + // For a parameter whose type has decayed, use the decayed type to + // build new source information. + } else if (TypeSourceInfo *DI = VariableOrMember->getTypeSourceInfo()) { TL = DI->getTypeLoc(); return; } @@ -1820,8 +1827,8 @@ void InitializedEntity::InitDeclLoc() { // FIXME: Once we've gone through the effort to create the fake // TypeSourceInfo, should we cache it in the declaration? // (If not, we "leak" it). - TypeSourceInfo *DI = VariableOrMember->getASTContext() - .CreateTypeSourceInfo(VariableOrMember->getType()); + TypeSourceInfo *DI + = Context.CreateTypeSourceInfo(VariableOrMember->getType()); DI->getTypeLoc().initialize(VariableOrMember->getLocation()); TL = DI->getTypeLoc(); } @@ -3346,6 +3353,14 @@ InitializationSequence::Perform(Sema &S, QualType SourceType = CurInitExpr->getType(); Sema::AssignConvertType ConvTy = S.CheckSingleAssignmentConstraints(Step->Type, CurInitExpr); + + // If this is a call, allow conversion to a transparent union. + if (ConvTy != Sema::Compatible && + Entity.getKind() == InitializedEntity::EK_Parameter && + S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExpr) + == Sema::Compatible) + ConvTy = Sema::Compatible; + if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), Step->Type, SourceType, CurInitExpr, getAssignmentAction(Entity))) diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index 0f71b49466..0617cd5702 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -25,7 +25,7 @@ struct Derived : Base { void fn2(); }; struct Convertible { operator Base&(); }; -struct Priv : private Base {}; // expected-note 2 {{'private' inheritance specifier here}} +struct Priv : private Base {}; // expected-note 4 {{'private' inheritance specifier here}} struct Mid : Base {}; struct Fin : Mid, Derived {}; typedef void (Derived::*DFnPtr)(); @@ -109,13 +109,12 @@ void test() (void)(i1 ? Base() : constder()); // expected-error {{incompatible operand types ('struct Base' and 'struct Derived const')}} (void)(i1 ? constder() : Base()); // expected-error {{incompatible operand types ('struct Derived const' and 'struct Base')}} - // FIXME: these are invalid hierarchy conversions Priv priv; Fin fin; - (void)(i1 ? Base() : Priv()); // xpected-error private base - (void)(i1 ? Priv() : Base()); // xpected-error private base - (void)(i1 ? Base() : Fin()); // xpected-error ambiguous base - (void)(i1 ? Fin() : Base()); // xpected-error ambiguous base + (void)(i1 ? Base() : Priv()); // expected-error{{conversion from 'struct Priv' to inaccessible base class 'struct Base'}} + (void)(i1 ? Priv() : Base()); // expected-error{{error: conversion from 'struct Priv' to inaccessible base class 'struct Base'}} + (void)(i1 ? Base() : Fin()); // expected-error{{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} + (void)(i1 ? Fin() : Base()); // expected-error{{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} (void)(i1 ? base : priv); // expected-error {{conversion from 'struct Priv' to inaccessible base class 'struct Base'}} (void)(i1 ? priv : base); // expected-error {{conversion from 'struct Priv' to inaccessible base class 'struct Base'}} (void)(i1 ? base : fin); // expected-error {{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} diff --git a/test/SemaCXX/elaborated-type-specifier.cpp b/test/SemaCXX/elaborated-type-specifier.cpp index 40816d8823..8d2d67f705 100644 --- a/test/SemaCXX/elaborated-type-specifier.cpp +++ b/test/SemaCXX/elaborated-type-specifier.cpp @@ -27,7 +27,7 @@ namespace NS { void test_X_elab(NS::X x) { struct S4 *s4 = 0; - x.test_elab2(s4); // expected-error{{incompatible type passing 'struct S4 *', expected 'struct NS::S4 *'}} + x.test_elab2(s4); // expected-error{{cannot initialize a parameter of type 'struct NS::S4 *' with an lvalue of type 'struct S4 *'}} } namespace NS { diff --git a/test/SemaCXX/member-location.cpp b/test/SemaCXX/member-location.cpp index 42e7c799a8..c3099d25e0 100644 --- a/test/SemaCXX/member-location.cpp +++ b/test/SemaCXX/member-location.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // PR4103: Make sure we have a location for the error class A { float a(int *); int b(); }; -int A::b() { return a(a((int*)0)); } // expected-error {{incompatible type}} +int A::b() { return a(a((int*)0)); } // expected-error {{cannot initialize a parameter of type 'int *' with an rvalue of type 'float'}} diff --git a/test/SemaObjCXX/blocks.mm b/test/SemaObjCXX/blocks.mm index 8dcf8089d3..72de171336 100644 --- a/test/SemaObjCXX/blocks.mm +++ b/test/SemaObjCXX/blocks.mm @@ -3,12 +3,12 @@ void bar(id(^)(void)); void foo(id (^objectCreationBlock)(void)) { - return bar(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (^)()', expected 'id (^)()'}} + return bar(objectCreationBlock); // expected-warning{{incompatible pointer types converting 'id (^)()', expected 'id (^)()'}} } void bar2(id(*)(void)); void foo2(id (*objectCreationBlock)(void)) { - return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (*)()', expected 'id (*)()'}} + return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types converting 'id (*)()', expected 'id (*)()'}} } void bar3(id(*)()); // expected-note{{candidate function}} diff --git a/test/SemaTemplate/instantiate-member-template.cpp b/test/SemaTemplate/instantiate-member-template.cpp index 2b5ba5c891..b4f0a9c650 100644 --- a/test/SemaTemplate/instantiate-member-template.cpp +++ b/test/SemaTemplate/instantiate-member-template.cpp @@ -90,7 +90,7 @@ void test_X1(int *ip, int i, double *dp) { X1::Inner3 id3; id3.f0(ip, i); - id3.f0(dp, i); // expected-error{{incompatible type}} + id3.f0(dp, i); // expected-error{{cannot initialize a parameter of type 'int *' with an lvalue of type 'double *'}} id3.f1(ip, i, ip); id3.f1(ip, i, dp); // expected-note{{instantiation}} -- 2.40.0