diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 379 |
1 files changed, 200 insertions, 179 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ca06decaf98..be1d666c3a1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2488,6 +2488,16 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, 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; @@ -2499,10 +2509,10 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // 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; @@ -2510,6 +2520,16 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, } 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; @@ -2533,8 +2553,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, return ExprError(); } -ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, - tok::TokenKind Kind) { +ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { PredefinedExpr::IdentType IT; switch (Kind) { @@ -4532,16 +4551,37 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, // 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. @@ -4602,6 +4642,12 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, 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. @@ -4715,66 +4761,6 @@ Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, 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 @@ -4834,11 +4820,10 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } 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; } @@ -8103,10 +8088,10 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, 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(); @@ -10159,6 +10144,93 @@ ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation 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. Strict preservation of the original source @@ -10192,7 +10264,7 @@ namespace { /// 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()); @@ -10209,11 +10281,32 @@ namespace { 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()); @@ -10296,63 +10389,34 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *call) { } 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(); @@ -10363,16 +10427,15 @@ ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *ice) { 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 @@ -10385,17 +10448,12 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, NamedDecl *decl) { // - 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 @@ -10405,47 +10463,10 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, NamedDecl *decl) { 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 |