Centralize and refine the __unknown_anytype argument rules

and be sure to apply them whether or not the debugger gave
us a method declaration.

rdar://12565338

llvm-svn: 176432
This commit is contained in:
John McCall 2013-03-04 07:34:02 +00:00
parent a37c2fa409
commit cc5788c5ce
4 changed files with 62 additions and 31 deletions

View File

@ -6911,12 +6911,10 @@ public:
/// given type.
ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
/// \brief Handle an expression that's being passed to an
/// \brief Type-check an expression that's being passed to an
/// __unknown_anytype parameter.
///
/// \return the effective parameter type to use, or null if the
/// argument is invalid.
QualType checkUnknownAnyArg(Expr *&result);
ExprResult checkUnknownAnyArg(SourceLocation callLoc,
Expr *result, QualType &paramType);
// CheckVectorCast - check type constraints for vectors.
// Since vectors are an extension, there are no C standard reference for this.

View File

@ -3835,11 +3835,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
if (Proto->getResultType() == Context.UnknownAnyTy &&
FDecl && FDecl->isExternC()) {
for (unsigned i = ArgIx; i != NumArgs; ++i) {
ExprResult arg;
if (isa<ExplicitCastExpr>(Args[i]->IgnoreParens()))
arg = DefaultFunctionArrayLvalueConversion(Args[i]);
else
arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
QualType paramType; // ignored
ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType);
Invalid |= arg.isInvalid();
AllArgs.push_back(arg.take());
}
@ -12013,20 +12010,27 @@ ExprResult Sema::forceUnknownAnyToType(Expr *E, QualType ToType) {
return RebuildUnknownAnyExpr(*this, ToType).Visit(E);
}
QualType Sema::checkUnknownAnyArg(Expr *&arg) {
// Filter out placeholders.
ExprResult argR = CheckPlaceholderExpr(arg);
if (argR.isInvalid()) return QualType();
arg = argR.take();
// If the argument is an explicit cast, use that exact type as the
// effective parameter type.
if (ExplicitCastExpr *castArg = dyn_cast<ExplicitCastExpr>(arg)) {
return castArg->getTypeAsWritten();
ExprResult Sema::checkUnknownAnyArg(SourceLocation callLoc,
Expr *arg, QualType &paramType) {
// If the syntactic form of the argument is not an explicit cast of
// any sort, just do default argument promotion.
ExplicitCastExpr *castArg = dyn_cast<ExplicitCastExpr>(arg->IgnoreParens());
if (!castArg) {
ExprResult result = DefaultArgumentPromotion(arg);
if (result.isInvalid()) return ExprError();
paramType = result.get()->getType();
return result;
}
// Otherwise, try to pass by value.
return arg->getType().getUnqualifiedType();
// Otherwise, use the type that was written in the explicit cast.
assert(!arg->hasPlaceholderType());
paramType = castArg->getTypeAsWritten();
// Copy-initialize a parameter of that type.
InitializedEntity entity =
InitializedEntity::InitializeParameter(Context, paramType,
/*consumed*/ false);
return PerformCopyInitialization(entity, callLoc, Owned(arg));
}
static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {

View File

@ -1135,10 +1135,16 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
if (Args[i]->isTypeDependent())
continue;
ExprResult Result = DefaultArgumentPromotion(Args[i]);
if (Result.isInvalid())
ExprResult result;
if (getLangOpts().DebuggerSupport) {
QualType paramTy; // ignored
result = checkUnknownAnyArg(lbrac, Args[i], paramTy);
} else {
result = DefaultArgumentPromotion(Args[i]);
}
if (result.isInvalid())
return true;
Args[i] = Result.take();
Args[i] = result.take();
}
unsigned DiagID;
@ -1199,14 +1205,17 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
// If the parameter is __unknown_anytype, infer its type
// from the argument.
if (param->getType() == Context.UnknownAnyTy) {
QualType paramType = checkUnknownAnyArg(argExpr);
if (paramType.isNull()) {
QualType paramType;
ExprResult argE = checkUnknownAnyArg(lbrac, argExpr, paramType);
if (argE.isInvalid()) {
IsError = true;
continue;
}
} else {
Args[i] = argE.take();
// Update the parameter type in-place.
param->setType(paramType);
// Update the parameter type in-place.
param->setType(paramType);
}
continue;
}
if (RequireCompleteType(argExpr->getSourceRange().getBegin(),

View File

@ -0,0 +1,20 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdebugger-support -funknown-anytype -emit-llvm -o - %s | FileCheck %s
// rdar://12565338
@interface A @end
void test0(A *a) {
(void) [a test0: (float) 2.0];
}
// CHECK: define void @_Z5test0P1A(
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, float)*)(
@interface B
- (void) test1: (__unknown_anytype) x;
@end
void test1(B *b) {
(void) [b test1: (float) 2.0];
}
// CHECK: define void @_Z5test1P1B(
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, float)*)(