From 688fc9b9b4323a294f5bf4f8a83f7c365edec573 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 21 Apr 2010 23:24:10 +0000 Subject: [PATCH] Switch the initialization of Objective-C message parameters (as occurs during message sends) over to the new initialization code and away from the C-only CheckSingleAssignmentConstraints. The enables the use of C++ types in method parameters and message arguments, as well as unifying more initialiation code overall. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102035 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExprObjC.cpp | 36 ++++++++++++---------------- lib/Sema/SemaInit.cpp | 5 +++- lib/Sema/SemaInit.h | 7 +++++- test/SemaObjCXX/message.mm | 15 ++++++++++++ test/SemaObjCXX/objc-pointer-conv.mm | 2 +- 5 files changed, 41 insertions(+), 24 deletions(-) diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 3af0cfc2c4..e6884bac33 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -13,6 +13,7 @@ #include "Sema.h" #include "Lookup.h" +#include "SemaInit.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" @@ -204,30 +205,23 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, bool IsError = false; for (unsigned i = 0; i < NumNamedArgs; i++) { Expr *argExpr = Args[i]; + ParmVarDecl *Param = Method->param_begin()[i]; assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); - QualType lhsType = Method->param_begin()[i]->getType(); - QualType rhsType = argExpr->getType(); - - // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8]. - if (lhsType->isArrayType()) - lhsType = Context.getArrayDecayedType(lhsType); - else if (lhsType->isFunctionType()) - lhsType = Context.getPointerType(lhsType); - - AssignConvertType Result = - CheckSingleAssignmentConstraints(lhsType, argExpr); - if (Result == Incompatible && !getLangOptions().CPlusPlus && - CheckTransparentUnionArgumentConstraints(lhsType, argExpr) - == Sema::Compatible) - Result = Compatible; - - if (Args[i] != argExpr) // The expression was converted. - Args[i] = argExpr; // Make sure we store the converted expression. + if (RequireCompleteType(argExpr->getSourceRange().getBegin(), + Param->getType(), + PDiag(diag::err_call_incomplete_argument) + << argExpr->getSourceRange())) + return true; - IsError |= - DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, - argExpr, AA_Sending); + InitializedEntity Entity = InitializedEntity::InitializeParameter(Param); + OwningExprResult ArgE = PerformCopyInitialization(Entity, + SourceLocation(), + Owned(argExpr->Retain())); + if (ArgE.isInvalid()) + IsError = true; + else + Args[i] = ArgE.takeAs(); } // Promote additional arguments to variadic methods. diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index a015dd7104..6a9efbddbd 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3088,7 +3088,10 @@ getAssignmentAction(const InitializedEntity &Entity) { return Sema::AA_Initializing; case InitializedEntity::EK_Parameter: - // FIXME: Can we tell when we're sending vs. passing? + if (Entity.getDecl() && + isa(Entity.getDecl()->getDeclContext())) + return Sema::AA_Sending; + return Sema::AA_Passing; case InitializedEntity::EK_Result: diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h index bfbb0f4049..ba11470d24 100644 --- a/lib/Sema/SemaInit.h +++ b/lib/Sema/SemaInit.h @@ -142,7 +142,12 @@ public: /// \brief Create the initialization entity for a parameter that is /// only known by its type. static InitializedEntity InitializeParameter(QualType Type) { - return InitializedEntity(EK_Parameter, SourceLocation(), Type); + InitializedEntity Entity; + Entity.Kind = EK_Parameter; + Entity.Type = Type; + Entity.Parent = 0; + Entity.VariableOrMember = 0; + return Entity; } /// \brief Create the initialization entity for the result of a function. diff --git a/test/SemaObjCXX/message.mm b/test/SemaObjCXX/message.mm index 91b11f146c..97ee499aff 100644 --- a/test/SemaObjCXX/message.mm +++ b/test/SemaObjCXX/message.mm @@ -75,3 +75,18 @@ struct identity { return [super method]; } @end + +struct String { + String(const char *); +}; + +struct MutableString : public String { }; + +// C++-specific parameter types +@interface I5 +- method:(const String&)str1 other:(String&)str2; +@end + +void test_I5(I5 *i5, String s) { + [i5 method:"hello" other:s]; +} diff --git a/test/SemaObjCXX/objc-pointer-conv.mm b/test/SemaObjCXX/objc-pointer-conv.mm index 02ed58b012..2504dcedb8 100644 --- a/test/SemaObjCXX/objc-pointer-conv.mm +++ b/test/SemaObjCXX/objc-pointer-conv.mm @@ -32,7 +32,7 @@ void RandomFunc(CFMDRef theDict, const void *key, const void *value); void Func (I* arg); // expected-note {{candidate function not viable: no known conversion from 'I const *' to 'I *' for 1st argument}} void foo(const I *p, I* sel) { - [sel Meth : p]; // expected-error {{sending 'I const *' to parameter of incompatible type 'I *'}} + [sel Meth : p]; // expected-error {{cannot initialize a parameter of type 'I *' with an lvalue of type 'I const *'}} Func(p); // expected-error {{no matching function for call to 'Func'}} } -- 2.40.0