break;
case Decl::Function: {
+ const FunctionType *fty = type->castAs<FunctionType>();
+
+ // If we're referring to a function with an __unknown_anytype
+ // result type, make the entire expression __unknown_anytype.
+ if (fty->getResultType() == Context.UnknownAnyTy) {
+ type = Context.UnknownAnyTy;
+ valueKind = VK_RValue;
+ break;
+ }
+
// Functions are l-values in C++.
if (getLangOptions().CPlusPlus) {
valueKind = VK_LValue;
// used for checking compatibility. Therefore, when referencing
// the function, we pretend that we don't have the full function
// type.
- if (!cast<FunctionDecl>(VD)->hasPrototype())
- if (const FunctionProtoType *proto = type->getAs<FunctionProtoType>())
- type = Context.getFunctionNoProtoType(proto->getResultType(),
- proto->getExtInfo());
+ if (!cast<FunctionDecl>(VD)->hasPrototype() &&
+ isa<FunctionProtoType>(fty))
+ type = Context.getFunctionNoProtoType(fty->getResultType(),
+ fty->getExtInfo());
// Functions are r-values in C.
valueKind = VK_RValue;
}
case Decl::CXXMethod:
+ // If we're referring to a method with an __unknown_anytype
+ // result type, make the entire expression __unknown_anytype.
+ // This should only be possible with a type written directly.
+ if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(VD->getType()))
+ if (proto->getResultType() == Context.UnknownAnyTy) {
+ type = Context.UnknownAnyTy;
+ valueKind = VK_RValue;
+ break;
+ }
+
// C++ methods are l-values if static, r-values if non-static.
if (cast<CXXMethodDecl>(VD)->isStatic()) {
valueKind = VK_LValue;
return ExprError();
}
-ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
- tok::TokenKind Kind) {
+ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
PredefinedExpr::IdentType IT;
switch (Kind) {
// If this is a variadic call, handle args passed through "...".
if (CallType != VariadicDoesNotApply) {
- // Promote the arguments (C99 6.5.2.2p7).
- for (unsigned i = ArgIx; i != NumArgs; ++i) {
- ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
- Invalid |= Arg.isInvalid();
- AllArgs.push_back(Arg.take());
+
+ // Assume that extern "C" functions with variadic arguments that
+ // return __unknown_anytype aren't *really* variadic.
+ 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);
+ Invalid |= arg.isInvalid();
+ AllArgs.push_back(arg.take());
+ }
+
+ // Otherwise do argument promotion, (C99 6.5.2.2p7).
+ } else {
+ for (unsigned i = ArgIx; i != NumArgs; ++i) {
+ ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
+ Invalid |= Arg.isInvalid();
+ AllArgs.push_back(Arg.take());
+ }
}
}
return Invalid;
}
+/// Given a function expression of unknown-any type, try to rebuild it
+/// to have a function type.
+static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn);
+
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
RParenLoc));
+ if (Fn->getType() == Context.UnknownAnyTy) {
+ ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
+ if (result.isInvalid()) return ExprError();
+ Fn = result.take();
+ }
+
Expr *NakedFn = Fn->IgnoreParens();
// Determine whether this is a call to an unresolved member function.
return ActOnCallExpr(S, ConfigDR, LLLLoc, execConfig, GGGLoc, 0);
}
-/// Given a function expression of unknown-any type, rebuild it to
-/// have a type appropriate for being called with the given arguments,
-/// yielding a value of unknown-any type.
-static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn,
- Expr **args, unsigned numArgs) {
- // Strip an lvalue-to-rvalue conversion off.
- if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(fn))
- if (ice->getCastKind() == CK_LValueToRValue)
- fn = ice->getSubExpr();
-
- // Build a simple function type exactly matching the arguments.
- llvm::SmallVector<QualType, 8> argTypes;
- argTypes.reserve(numArgs);
- for (unsigned i = 0; i != numArgs; ++i) {
- // Require all the sub-expression to not be placeholders.
- ExprResult result = S.CheckPlaceholderExpr(args[i]);
- if (result.isInvalid()) return ExprError();
- args[i] = result.take();
-
- QualType argType;
-
- // If the argument is an explicit cast (possibly parenthesized),
- // use that type exactly. This allows users to pass by reference.
- if (ExplicitCastExpr *castExpr
- = dyn_cast<ExplicitCastExpr>(args[i]->IgnoreParens())) {
- argType = castExpr->getTypeAsWritten();
-
- // Otherwise, do an l2r conversion on the argument before grabbing
- // its type.
- } else {
- ExprResult result = S.DefaultLvalueConversion(args[i]);
- if (result.isInvalid()) return ExprError();
- args[i] = result.take();
- argType = args[i]->getType();
- }
-
- argTypes.push_back(argType);
- }
-
- // Resolve the symbol to a function type that returns an unknown-any
- // type. In the fully resolved expression, this cast will surround
- // the DeclRefExpr.
- FunctionProtoType::ExtProtoInfo extInfo;
- QualType fnType = S.Context.getFunctionType(S.Context.UnknownAnyTy,
- argTypes.data(), numArgs,
- extInfo);
- fn = ImplicitCastExpr::Create(S.Context, fnType,
- CK_ResolveUnknownAnyType,
- fn, /*path*/ 0,
- (S.getLangOptions().CPlusPlus ? VK_LValue : VK_RValue));
-
- // Decay that to a pointer.
- fnType = S.Context.getPointerType(fnType);
- fn = ImplicitCastExpr::Create(S.Context, fnType,
- CK_FunctionToPointerDecay,
- fn, /*path*/ 0, VK_RValue);
-
- return S.Owned(fn);
-}
-
/// BuildResolvedCallExpr - Build a call to a resolved expression,
/// i.e. an expression not of \p OverloadTy. The expression should
/// unary-convert to an expression of function-pointer or
} else {
// Handle calls to expressions of unknown-any type.
if (Fn->getType() == Context.UnknownAnyTy) {
- ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn, Args, NumArgs);
+ ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
if (rewrite.isInvalid()) return ExprError();
Fn = rewrite.take();
TheCall->setCallee(Fn);
- NDecl = FDecl = 0;
goto retry;
}
return S.Context.DependentTy;
if (OrigOp->getType() == S.Context.OverloadTy)
return S.Context.OverloadTy;
+ if (OrigOp->getType() == S.Context.UnknownAnyTy)
+ return S.Context.UnknownAnyTy;
- ExprResult PR = S.CheckPlaceholderExpr(OrigOp);
- if (PR.isInvalid()) return QualType();
- OrigOp = PR.take();
+ assert(!OrigOp->getType()->isPlaceholderType());
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp->IgnoreParens();
return CheckBooleanCondition(Sub, Loc);
}
+namespace {
+ /// A visitor for rebuilding a call to an __unknown_any expression
+ /// to have an appropriate type.
+ struct RebuildUnknownAnyFunction
+ : StmtVisitor<RebuildUnknownAnyFunction, ExprResult> {
+
+ Sema &S;
+
+ RebuildUnknownAnyFunction(Sema &S) : S(S) {}
+
+ ExprResult VisitStmt(Stmt *S) {
+ llvm_unreachable("unexpected statement!");
+ return ExprError();
+ }
+
+ ExprResult VisitExpr(Expr *expr) {
+ S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_call)
+ << expr->getSourceRange();
+ return ExprError();
+ }
+
+ /// Rebuild an expression which simply semantically wraps another
+ /// expression which it shares the type and value kind of.
+ template <class T> ExprResult rebuildSugarExpr(T *expr) {
+ ExprResult subResult = Visit(expr->getSubExpr());
+ if (subResult.isInvalid()) return ExprError();
+
+ Expr *subExpr = subResult.take();
+ expr->setSubExpr(subExpr);
+ expr->setType(subExpr->getType());
+ expr->setValueKind(subExpr->getValueKind());
+ assert(expr->getObjectKind() == OK_Ordinary);
+ return expr;
+ }
+
+ ExprResult VisitParenExpr(ParenExpr *paren) {
+ return rebuildSugarExpr(paren);
+ }
+
+ ExprResult VisitUnaryExtension(UnaryOperator *op) {
+ return rebuildSugarExpr(op);
+ }
+
+ ExprResult VisitUnaryAddrOf(UnaryOperator *op) {
+ ExprResult subResult = Visit(op->getSubExpr());
+ if (subResult.isInvalid()) return ExprError();
+
+ Expr *subExpr = subResult.take();
+ op->setSubExpr(subExpr);
+ op->setType(S.Context.getPointerType(subExpr->getType()));
+ assert(op->getValueKind() == VK_RValue);
+ assert(op->getObjectKind() == OK_Ordinary);
+ return op;
+ }
+
+ ExprResult resolveDecl(Expr *expr, ValueDecl *decl) {
+ if (!isa<FunctionDecl>(decl)) return VisitExpr(expr);
+
+ expr->setType(decl->getType());
+
+ assert(expr->getValueKind() == VK_RValue);
+ if (S.getLangOptions().CPlusPlus &&
+ !(isa<CXXMethodDecl>(decl) &&
+ cast<CXXMethodDecl>(decl)->isInstance()))
+ expr->setValueKind(VK_LValue);
+
+ return expr;
+ }
+
+ ExprResult VisitMemberExpr(MemberExpr *mem) {
+ return resolveDecl(mem, mem->getMemberDecl());
+ }
+
+ ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
+ return resolveDecl(ref, ref->getDecl());
+ }
+ };
+}
+
+/// Given a function expression of unknown-any type, try to rebuild it
+/// to have a function type.
+static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn) {
+ ExprResult result = RebuildUnknownAnyFunction(S).Visit(fn);
+ if (result.isInvalid()) return ExprError();
+ return S.DefaultFunctionArrayConversion(result.take());
+}
+
namespace {
/// A visitor for rebuilding an expression of type __unknown_anytype
/// into one which resolves the type directly on the referring
/// expression which it shares the type and value kind of.
template <class T> ExprResult rebuildSugarExpr(T *expr) {
ExprResult subResult = Visit(expr->getSubExpr());
- if (!subResult.isUsable()) return ExprError();
+ if (subResult.isInvalid()) return ExprError();
Expr *subExpr = subResult.take();
expr->setSubExpr(subExpr);
expr->setType(subExpr->getType());
return rebuildSugarExpr(op);
}
+ ExprResult VisitUnaryAddrOf(UnaryOperator *op) {
+ const PointerType *ptr = DestType->getAs<PointerType>();
+ if (!ptr) {
+ S.Diag(op->getOperatorLoc(), diag::err_unknown_any_addrof)
+ << op->getSourceRange();
+ return ExprError();
+ }
+ assert(op->getValueKind() == VK_RValue);
+ assert(op->getObjectKind() == OK_Ordinary);
+ op->setType(DestType);
+
+ // Build the sub-expression as if it were an object of the pointee type.
+ DestType = ptr->getPointeeType();
+ ExprResult subResult = Visit(op->getSubExpr());
+ if (subResult.isInvalid()) return ExprError();
+ op->setSubExpr(subResult.take());
+ return op;
+ }
+
ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice);
- ExprResult resolveDecl(Expr *expr, NamedDecl *decl);
+ ExprResult resolveDecl(Expr *expr, ValueDecl *decl);
- ExprResult VisitMemberExpr(MemberExpr *mem);
+ ExprResult VisitMemberExpr(MemberExpr *mem) {
+ return resolveDecl(mem, mem->getMemberDecl());
+ }
ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
return resolveDecl(ref, ref->getDecl());
}
ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *msg) {
- // This is a long series of hacks around the problem that:
- // - we can't just cast the method because it's not an expr,
- // - we don't want to modify it in place, and
- // - there's no way to override the declared result type
- // of a method on a per-call basis.
+ ObjCMethodDecl *method = msg->getMethodDecl();
+ assert(method && "__unknown_anytype message without result type?");
- const ReferenceType *refTy = DestType->getAs<ReferenceType>();
- if (refTy) {
- // Hack 1: if we're returning a reference, make the message
- // send return a pointer instead.
- DestType = S.Context.getPointerType(refTy->getPointeeType());
+ // Verify that this is a legal result type of a call.
+ if (DestType->isArrayType() || DestType->isFunctionType()) {
+ S.Diag(msg->getExprLoc(), diag::err_func_returning_array_function)
+ << DestType->isFunctionType() << DestType;
+ return ExprError();
}
- // Change the type of the message.
- msg->setType(DestType);
- assert(msg->getValueKind() == VK_RValue);
-
- // Hack 2: remove the method decl so that clients won't just
- // ignore the expression's type. This is imperfect and can lead
- // to expressions being completely lost.
- msg->setSelector(msg->getMethodDecl()->getSelector());
+ assert(method->getResultType() == S.Context.UnknownAnyTy);
+ method->setResultType(DestType);
- // Hack 3: if we're returning a reference, dereference the
- // pointer return.
- Expr *result = msg;
- if (refTy) {
- SourceLocation loc;
- result = new (S.Context) UnaryOperator(result, UO_Deref,
- refTy->getPointeeType(),
- VK_LValue, OK_Ordinary, loc);
-
- // Hack 4: if we're returning an *rvalue* reference, cast to that.
- if (isa<RValueReferenceType>(refTy)) {
- TypeSourceInfo *tsi =
- S.Context.getTrivialTypeSourceInfo(QualType(refTy, 0), loc);
- result = CStyleCastExpr::Create(S.Context, refTy->getPointeeType(),
- VK_XValue, CK_LValueBitCast,
- result, 0, tsi, loc, loc);
- }
- }
+ // Change the type of the message.
+ msg->setType(DestType.getNonReferenceType());
+ msg->setValueKind(Expr::getValueKindForType(DestType));
- return S.MaybeBindToTemporary(result);
+ return S.MaybeBindToTemporary(msg);
}
ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *ice) {
- // Rebuild an inner resolution by stripping it and propagating
- // the new type down.
- if (ice->getCastKind() == CK_ResolveUnknownAnyType)
- return Visit(ice->getSubExpr());
-
- // The only other case we should be able to get here is a
- // function-to-pointer decay.
+ // The only case we should ever see here is a function-to-pointer decay.
assert(ice->getCastKind() == CK_FunctionToPointerDecay);
- ice->setType(DestType);
assert(ice->getValueKind() == VK_RValue);
assert(ice->getObjectKind() == OK_Ordinary);
+ ice->setType(DestType);
+
// Rebuild the sub-expression as the pointee (function) type.
DestType = DestType->castAs<PointerType>()->getPointeeType();
return S.Owned(ice);
}
-ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, NamedDecl *decl) {
+ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, ValueDecl *decl) {
ExprValueKind valueKind = VK_LValue;
- CastKind castKind = CK_ResolveUnknownAnyType;
QualType type = DestType;
// We know how to make this work for certain kinds of decls:
// - functions
- if (isa<FunctionDecl>(decl)) {
- if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl))
+ if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+ if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(fn))
if (method->isInstance()) valueKind = VK_RValue;
// This is true because FunctionDecls must always have function
// - variables
} else if (isa<VarDecl>(decl)) {
- if (S.getLangOptions().CPlusPlus) {
- // If we're resolving to a reference type, the type of the
- // expression is the pointee type, and we need to use a
- // different cast kind so that we know to do the extra load.
- if (const ReferenceType *refTy = type->getAs<ReferenceType>()) {
- type = refTy->getPointeeType();
- castKind = CK_ResolveUnknownAnyTypeToReference;
- }
+ if (const ReferenceType *refTy = type->getAs<ReferenceType>()) {
+ type = refTy->getPointeeType();
} else if (type->isFunctionType()) {
- // Function references aren't l-values in C.
- valueKind = VK_RValue;
+ S.Diag(expr->getExprLoc(), diag::err_unknown_any_var_function_type)
+ << decl << expr->getSourceRange();
+ return ExprError();
}
// - nothing else
return ExprError();
}
- return S.Owned(ImplicitCastExpr::Create(S.Context, type, castKind,
- expr, 0, valueKind));
-}
-
-ExprResult RebuildUnknownAnyExpr::VisitMemberExpr(MemberExpr *mem) {
- NamedDecl *decl = mem->getMemberDecl();
- CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl);
- if (!method || !method->isInstance())
- return resolveDecl(mem, decl);
-
- // Rebuild instance-method references as applications of .* or ->*.
- Expr *base = mem->getBase();
-
- assert(DestType->isFunctionType());
-
- // Make a decl ref.
- TemplateArgumentListInfo explicitArgs;
- mem->copyTemplateArgumentsInto(explicitArgs);
- Expr *rhs = DeclRefExpr::Create(S.Context, mem->getQualifierLoc(),
- method, mem->getMemberNameInfo(),
- method->getType(), VK_RValue, &explicitArgs);
-
- // Turn that into a member pointer constant.
- const Type *recordTy =
- S.Context.getTypeDeclType(method->getParent()).getTypePtr();
- QualType mpt = S.Context.getMemberPointerType(method->getType(), recordTy);
- rhs = new (S.Context) UnaryOperator(rhs, UO_AddrOf, mpt, VK_RValue,
- OK_Ordinary, SourceLocation());
-
- // Resolve that.
- rhs = ImplicitCastExpr::Create(S.Context,
- S.Context.getMemberPointerType(DestType, recordTy),
- CK_ResolveUnknownAnyType, rhs, 0, VK_RValue);
-
- // Turn that into a binary .* or ->*.
- Expr *result = new (S.Context) BinaryOperator(base, rhs,
- mem->isArrow() ? BO_PtrMemI : BO_PtrMemD,
- DestType, VK_RValue,
- OK_Ordinary, SourceLocation());
-
- return S.Owned(result);
+ decl->setType(DestType);
+ expr->setType(type);
+ expr->setValueKind(valueKind);
+ return S.Owned(expr);
}
/// Check a cast of an unknown-any type. We intentionally only