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. llvm-svn: 102035
This commit is contained in:
parent
14b1d758c6
commit
6b7f12c039
|
@ -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 (RequireCompleteType(argExpr->getSourceRange().getBegin(),
|
||||
Param->getType(),
|
||||
PDiag(diag::err_call_incomplete_argument)
|
||||
<< argExpr->getSourceRange()))
|
||||
return true;
|
||||
|
||||
// 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.
|
||||
|
||||
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<Expr>();
|
||||
}
|
||||
|
||||
// Promote additional arguments to variadic methods.
|
||||
|
|
|
@ -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<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
|
||||
return Sema::AA_Sending;
|
||||
|
||||
return Sema::AA_Passing;
|
||||
|
||||
case InitializedEntity::EK_Result:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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'}}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue