parent
62920834fa
commit
2d2e870745
|
@ -2222,6 +2222,7 @@ private:
|
|||
case CK_FloatingComplexToBoolean:
|
||||
case CK_IntegralComplexToBoolean:
|
||||
case CK_ResolveUnknownAnyType:
|
||||
case CK_ResolveUnknownAnyTypeToReference:
|
||||
case CK_LValueBitCast: // -> bool&
|
||||
case CK_UserDefinedConversion: // operator bool()
|
||||
assert(path_empty() && "Cast kind should not have a base path!");
|
||||
|
|
|
@ -248,7 +248,10 @@ enum CastKind {
|
|||
CK_IntegralComplexToFloatingComplex,
|
||||
|
||||
/// \brief Assign an unknown-any declaration a type.
|
||||
CK_ResolveUnknownAnyType
|
||||
CK_ResolveUnknownAnyType,
|
||||
|
||||
/// \brief Assign an unknown-any declaration a reference type.
|
||||
CK_ResolveUnknownAnyTypeToReference
|
||||
};
|
||||
|
||||
#define CK_Invalid ((CastKind) -1)
|
||||
|
|
|
@ -3851,8 +3851,14 @@ def err_sizeof_pack_no_pack_name_suggest : Error<
|
|||
"%0 does not refer to the name of a parameter pack; did you mean %1?">;
|
||||
def note_parameter_pack_here : Note<"parameter pack %0 declared here">;
|
||||
|
||||
def err_bad_use_of_unknown_any : Error<
|
||||
"no known type for %0; must explicitly cast this expression to use it">;
|
||||
def err_uncasted_use_of_unknown_any : Error<
|
||||
"%0 has unknown type; cast it to its declared type to use it">;
|
||||
def err_uncasted_call_of_unknown_any : Error<
|
||||
"%0 has unknown return type; cast the call to its declared return type">;
|
||||
def err_unsupported_unknown_any_decl : Error<
|
||||
"%0 has unknown type, which is unsupported for this kind of declaration">;
|
||||
def err_unsupported_unknown_any_expr : Error<
|
||||
"unsupported expression with unknown type">;
|
||||
|
||||
} // end of sema category
|
||||
|
||||
|
|
|
@ -1057,6 +1057,8 @@ const char *CastExpr::getCastKindName() const {
|
|||
return "IntegralComplexToFloatingComplex";
|
||||
case CK_ResolveUnknownAnyType:
|
||||
return "ResolveUnknownAnyType";
|
||||
case CK_ResolveUnknownAnyTypeToReference:
|
||||
return "ResolveUnknownAnyTypeToReference";
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled cast kind!");
|
||||
|
|
|
@ -1799,6 +1799,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
|
|||
case CK_LValueBitCast:
|
||||
case CK_UserDefinedConversion:
|
||||
case CK_ResolveUnknownAnyType:
|
||||
case CK_ResolveUnknownAnyTypeToReference:
|
||||
return false;
|
||||
|
||||
case CK_LValueToRValue:
|
||||
|
@ -2353,6 +2354,7 @@ bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) {
|
|||
case CK_LValueBitCast:
|
||||
case CK_UserDefinedConversion:
|
||||
case CK_ResolveUnknownAnyType:
|
||||
case CK_ResolveUnknownAnyTypeToReference:
|
||||
return false;
|
||||
|
||||
case CK_FloatingRealToComplex: {
|
||||
|
|
|
@ -99,7 +99,8 @@ CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
|
|||
return GetBogusMemberPointer(CGM, QualType(MPT, 0));
|
||||
}
|
||||
|
||||
llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
|
||||
llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
|
||||
QualType unknownType) {
|
||||
return GetBogusMemberPointer(CGM,
|
||||
CGM.getContext().getMemberPointerType(MD->getType(),
|
||||
MD->getParent()->getTypeForDecl()));
|
||||
|
|
|
@ -119,7 +119,12 @@ public:
|
|||
virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
|
||||
|
||||
/// Create a member pointer for the given method.
|
||||
virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
|
||||
///
|
||||
/// \param unknownType - if non-null, use this type as the operand
|
||||
/// to CodeGenModule::getAddrOfUnknownAnyDecl instead of
|
||||
/// fetching the method's address in the normal way
|
||||
virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD,
|
||||
QualType unknownType = QualType());
|
||||
|
||||
/// Create a member pointer for the given field.
|
||||
virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
|
||||
|
|
|
@ -1792,6 +1792,35 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
|
|||
return MakeAddrLValue(phi, expr->getType());
|
||||
}
|
||||
|
||||
static LValue emitUnknownAnyLValue(CodeGenFunction &CGF,
|
||||
const Expr *operand,
|
||||
QualType resolvedType) {
|
||||
const ValueDecl *decl;
|
||||
if (const DeclRefExpr *ref = dyn_cast<DeclRefExpr>(operand)) {
|
||||
decl = ref->getDecl();
|
||||
} else if (const MemberExpr *mem = dyn_cast<MemberExpr>(operand)) {
|
||||
decl = mem->getMemberDecl();
|
||||
|
||||
// Emit (and ignore) the base.
|
||||
if (mem->isArrow())
|
||||
CGF.EmitScalarExpr(mem->getBase());
|
||||
else
|
||||
CGF.EmitLValue(mem->getBase());
|
||||
} else {
|
||||
llvm_unreachable("unexpected operand of unknown-any resolution!");
|
||||
decl = 0;
|
||||
}
|
||||
llvm::Value *addr = CGF.CGM.getAddrOfUnknownAnyDecl(decl, resolvedType);
|
||||
|
||||
QualType type = resolvedType;
|
||||
if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
|
||||
addr = CGF.Builder.CreateLoad(addr, "ref.value");
|
||||
type = ref->getPointeeType();
|
||||
}
|
||||
|
||||
return CGF.MakeAddrLValue(addr, type);
|
||||
}
|
||||
|
||||
/// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
|
||||
/// If the cast is a dynamic_cast, we can have the usual lvalue result,
|
||||
/// otherwise if a cast is needed by the code generator in an lvalue context,
|
||||
|
@ -1930,11 +1959,12 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
|||
ConvertType(ToType));
|
||||
return MakeAddrLValue(V, E->getType());
|
||||
}
|
||||
case CK_ResolveUnknownAnyType: {
|
||||
const DeclRefExpr *declRef = cast<DeclRefExpr>(E->getSubExpr());
|
||||
llvm::Constant *addr = CGM.getAddrOfUnknownAnyDecl(declRef->getDecl(),
|
||||
E->getType());
|
||||
return MakeAddrLValue(addr, E->getType());
|
||||
case CK_ResolveUnknownAnyType:
|
||||
return emitUnknownAnyLValue(*this, E->getSubExpr(), E->getType());
|
||||
case CK_ResolveUnknownAnyTypeToReference: {
|
||||
// l-value vs. r-value reference type shouldn't matter here.
|
||||
QualType type = getContext().getLValueReferenceType(E->getType());
|
||||
return emitUnknownAnyLValue(*this, E->getSubExpr(), type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -311,6 +311,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
|
|||
break;
|
||||
|
||||
case CK_ResolveUnknownAnyType:
|
||||
case CK_ResolveUnknownAnyTypeToReference:
|
||||
EmitAggLoadOfLValue(E);
|
||||
break;
|
||||
|
||||
|
|
|
@ -167,10 +167,12 @@ static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context,
|
|||
// extensions allowing explicit constructor function call.
|
||||
RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
|
||||
ReturnValueSlot ReturnValue) {
|
||||
if (isa<BinaryOperator>(CE->getCallee()->IgnoreParens()))
|
||||
const Expr *callee = CE->getCallee()->IgnoreParens();
|
||||
|
||||
if (isa<BinaryOperator>(callee))
|
||||
return EmitCXXMemberPointerCallExpr(CE, ReturnValue);
|
||||
|
||||
const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()->IgnoreParens());
|
||||
|
||||
const MemberExpr *ME = cast<MemberExpr>(callee);
|
||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
|
||||
|
||||
CGDebugInfo *DI = getDebugInfo();
|
||||
|
|
|
@ -553,6 +553,7 @@ public:
|
|||
case CK_ToVoid:
|
||||
case CK_Dynamic:
|
||||
case CK_ResolveUnknownAnyType:
|
||||
case CK_ResolveUnknownAnyTypeToReference:
|
||||
return 0;
|
||||
|
||||
// These might need to be supported for constexpr.
|
||||
|
|
|
@ -1128,6 +1128,19 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
|
|||
}
|
||||
|
||||
case CK_ResolveUnknownAnyType:
|
||||
// Special case: resolving a member pointer constant.
|
||||
if (const UnaryOperator *uo = dyn_cast<UnaryOperator>(E)) {
|
||||
DeclRefExpr *declRef = cast<DeclRefExpr>(uo->getSubExpr());
|
||||
const CXXMethodDecl *method = cast<CXXMethodDecl>(declRef->getDecl());
|
||||
|
||||
const MemberPointerType *mpt = CE->getType()->castAs<MemberPointerType>();
|
||||
QualType resolvedType = mpt->getPointeeType();
|
||||
|
||||
return CGF.CGM.getCXXABI().EmitMemberPointer(method, resolvedType);
|
||||
}
|
||||
// fallthrough
|
||||
|
||||
case CK_ResolveUnknownAnyTypeToReference:
|
||||
return EmitLoadOfLValue(CE);
|
||||
|
||||
case CK_LValueToRValue:
|
||||
|
|
|
@ -78,7 +78,8 @@ public:
|
|||
|
||||
llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
|
||||
|
||||
llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
|
||||
llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD,
|
||||
QualType unknownType);
|
||||
llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
|
||||
CharUnits offset);
|
||||
|
||||
|
@ -502,7 +503,8 @@ ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
|
|||
return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity());
|
||||
}
|
||||
|
||||
llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
|
||||
llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD,
|
||||
QualType unknownType) {
|
||||
assert(MD->isInstance() && "Member function must not be static!");
|
||||
MD = MD->getCanonicalDecl();
|
||||
|
||||
|
@ -537,20 +539,27 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
|
|||
MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
|
||||
}
|
||||
} else {
|
||||
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
|
||||
const llvm::Type *Ty;
|
||||
// Check whether the function has a computable LLVM signature.
|
||||
if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
|
||||
// The function has a computable LLVM signature; use the correct type.
|
||||
Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic());
|
||||
llvm::Constant *addr;
|
||||
if (!unknownType.isNull()) {
|
||||
addr = CGM.getAddrOfUnknownAnyDecl(MD, unknownType);
|
||||
} else {
|
||||
// Use an arbitrary non-function type to tell GetAddrOfFunction that the
|
||||
// function type is incomplete.
|
||||
Ty = ptrdiff_t;
|
||||
QualType fnType = MD->getType();
|
||||
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
|
||||
const llvm::Type *Ty;
|
||||
// Check whether the function has a computable LLVM signature.
|
||||
if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
|
||||
// The function has a computable LLVM signature; use the correct type.
|
||||
Ty = Types.GetFunctionType(Types.getFunctionInfo(MD),
|
||||
FPT->isVariadic());
|
||||
} else {
|
||||
// Use an arbitrary non-function type to tell GetAddrOfFunction that the
|
||||
// function type is incomplete.
|
||||
Ty = ptrdiff_t;
|
||||
}
|
||||
addr = CGM.GetAddrOfFunction(MD, Ty);
|
||||
}
|
||||
|
||||
llvm::Constant *Addr = CGM.GetAddrOfFunction(MD, Ty);
|
||||
MemPtr[0] = llvm::ConstantExpr::getPtrToInt(Addr, ptrdiff_t);
|
||||
MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t);
|
||||
MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -4734,10 +4734,24 @@ static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn,
|
|||
if (result.isInvalid()) return ExprError();
|
||||
args[i] = result.take();
|
||||
|
||||
// Do l2r conversions on all the arguments.
|
||||
S.DefaultLvalueConversion(args[i]);
|
||||
QualType argType;
|
||||
|
||||
argTypes.push_back(args[i]->getType());
|
||||
// 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
|
||||
|
@ -10145,6 +10159,10 @@ ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc,
|
|||
}
|
||||
|
||||
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
|
||||
/// structure is not a goal.
|
||||
struct RebuildUnknownAnyExpr
|
||||
: StmtVisitor<RebuildUnknownAnyExpr, ExprResult> {
|
||||
|
||||
|
@ -10157,64 +10175,19 @@ namespace {
|
|||
: S(S), DestType(castType) {}
|
||||
|
||||
ExprResult VisitStmt(Stmt *S) {
|
||||
llvm_unreachable("unexpected expression kind!");
|
||||
llvm_unreachable("unexpected statement!");
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
ExprResult VisitCallExpr(CallExpr *call) {
|
||||
Expr *callee = call->getCallee();
|
||||
|
||||
bool wasBlock;
|
||||
QualType type = callee->getType();
|
||||
if (const PointerType *ptr = type->getAs<PointerType>()) {
|
||||
type = ptr->getPointeeType();
|
||||
wasBlock = false;
|
||||
} else {
|
||||
type = type->castAs<BlockPointerType>()->getPointeeType();
|
||||
wasBlock = true;
|
||||
}
|
||||
const FunctionType *fnType = type->castAs<FunctionType>();
|
||||
|
||||
// Verify that this is a legal result type of a function.
|
||||
if (DestType->isArrayType() || DestType->isFunctionType()) {
|
||||
unsigned diagID = diag::err_func_returning_array_function;
|
||||
if (wasBlock) diagID = diag::err_block_returning_array_function;
|
||||
|
||||
S.Diag(call->getExprLoc(), diagID)
|
||||
<< DestType->isFunctionType() << DestType;
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
// Otherwise, go ahead and set DestType as the call's result.
|
||||
call->setType(DestType.getNonLValueExprType(S.Context));
|
||||
call->setValueKind(Expr::getValueKindForType(DestType));
|
||||
assert(call->getObjectKind() == OK_Ordinary);
|
||||
|
||||
// Rebuild the function type, replacing the result type with DestType.
|
||||
if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType))
|
||||
DestType = S.Context.getFunctionType(DestType,
|
||||
proto->arg_type_begin(),
|
||||
proto->getNumArgs(),
|
||||
proto->getExtProtoInfo());
|
||||
else
|
||||
DestType = S.Context.getFunctionNoProtoType(DestType,
|
||||
fnType->getExtInfo());
|
||||
|
||||
// Rebuild the appropriate pointer-to-function type.
|
||||
if (wasBlock)
|
||||
DestType = S.Context.getBlockPointerType(DestType);
|
||||
else
|
||||
DestType = S.Context.getPointerType(DestType);
|
||||
|
||||
// Finally, we can recurse.
|
||||
ExprResult calleeResult = Visit(callee);
|
||||
if (!calleeResult.isUsable()) return ExprError();
|
||||
call->setCallee(calleeResult.take());
|
||||
|
||||
// Bind a temporary if necessary.
|
||||
return S.MaybeBindToTemporary(call);
|
||||
ExprResult VisitExpr(Expr *expr) {
|
||||
S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_expr)
|
||||
<< expr->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
ExprResult VisitCallExpr(CallExpr *call);
|
||||
ExprResult VisitObjCMessageExpr(ObjCMessageExpr *message);
|
||||
|
||||
/// 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) {
|
||||
|
@ -10236,47 +10209,245 @@ namespace {
|
|||
return rebuildSugarExpr(op);
|
||||
}
|
||||
|
||||
ExprResult 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());
|
||||
ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice);
|
||||
|
||||
// The only other case we should be able to get 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);
|
||||
ExprResult resolveDecl(Expr *expr, NamedDecl *decl);
|
||||
|
||||
// Rebuild the sub-expression as the pointee (function) type.
|
||||
DestType = DestType->castAs<PointerType>()->getPointeeType();
|
||||
|
||||
ExprResult result = Visit(ice->getSubExpr());
|
||||
if (!result.isUsable()) return ExprError();
|
||||
|
||||
ice->setSubExpr(result.take());
|
||||
return S.Owned(ice);
|
||||
}
|
||||
ExprResult VisitMemberExpr(MemberExpr *mem);
|
||||
|
||||
ExprResult VisitDeclRefExpr(DeclRefExpr *ref) {
|
||||
ExprValueKind valueKind = VK_LValue;
|
||||
if (S.getLangOptions().CPlusPlus) {
|
||||
// FIXME: if the value was resolved as a reference type, we
|
||||
// should really remember that somehow, or else we'll be
|
||||
// missing a load.
|
||||
DestType = DestType.getNonReferenceType();
|
||||
} else if (DestType->isFunctionType()) {
|
||||
valueKind = VK_RValue;
|
||||
}
|
||||
|
||||
return S.Owned(ImplicitCastExpr::Create(S.Context, DestType,
|
||||
CK_ResolveUnknownAnyType,
|
||||
ref, 0, valueKind));
|
||||
return resolveDecl(ref, ref->getDecl());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Rebuilds a call expression which yielded __unknown_anytype.
|
||||
ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *call) {
|
||||
Expr *callee = call->getCallee();
|
||||
|
||||
enum FnKind {
|
||||
FK_Function,
|
||||
FK_FunctionPointer,
|
||||
FK_BlockPointer
|
||||
};
|
||||
|
||||
FnKind kind;
|
||||
QualType type = callee->getType();
|
||||
if (type->isFunctionType()) {
|
||||
assert(isa<CXXMemberCallExpr>(call) || isa<CXXOperatorCallExpr>(call));
|
||||
kind = FK_Function;
|
||||
} else if (const PointerType *ptr = type->getAs<PointerType>()) {
|
||||
type = ptr->getPointeeType();
|
||||
kind = FK_FunctionPointer;
|
||||
} else {
|
||||
type = type->castAs<BlockPointerType>()->getPointeeType();
|
||||
kind = FK_BlockPointer;
|
||||
}
|
||||
const FunctionType *fnType = type->castAs<FunctionType>();
|
||||
|
||||
// Verify that this is a legal result type of a function.
|
||||
if (DestType->isArrayType() || DestType->isFunctionType()) {
|
||||
unsigned diagID = diag::err_func_returning_array_function;
|
||||
if (kind == FK_BlockPointer)
|
||||
diagID = diag::err_block_returning_array_function;
|
||||
|
||||
S.Diag(call->getExprLoc(), diagID)
|
||||
<< DestType->isFunctionType() << DestType;
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
// Otherwise, go ahead and set DestType as the call's result.
|
||||
call->setType(DestType.getNonLValueExprType(S.Context));
|
||||
call->setValueKind(Expr::getValueKindForType(DestType));
|
||||
assert(call->getObjectKind() == OK_Ordinary);
|
||||
|
||||
// Rebuild the function type, replacing the result type with DestType.
|
||||
if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType))
|
||||
DestType = S.Context.getFunctionType(DestType,
|
||||
proto->arg_type_begin(),
|
||||
proto->getNumArgs(),
|
||||
proto->getExtProtoInfo());
|
||||
else
|
||||
DestType = S.Context.getFunctionNoProtoType(DestType,
|
||||
fnType->getExtInfo());
|
||||
|
||||
// Rebuild the appropriate pointer-to-function type.
|
||||
switch (kind) {
|
||||
case FK_Function:
|
||||
// Nothing to do.
|
||||
break;
|
||||
|
||||
case FK_FunctionPointer:
|
||||
DestType = S.Context.getPointerType(DestType);
|
||||
break;
|
||||
|
||||
case FK_BlockPointer:
|
||||
DestType = S.Context.getBlockPointerType(DestType);
|
||||
break;
|
||||
}
|
||||
|
||||
// Finally, we can recurse.
|
||||
ExprResult calleeResult = Visit(callee);
|
||||
if (!calleeResult.isUsable()) return ExprError();
|
||||
call->setCallee(calleeResult.take());
|
||||
|
||||
// Bind a temporary if necessary.
|
||||
return S.MaybeBindToTemporary(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.
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
return S.MaybeBindToTemporary(result);
|
||||
}
|
||||
|
||||
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.
|
||||
assert(ice->getCastKind() == CK_FunctionToPointerDecay);
|
||||
ice->setType(DestType);
|
||||
assert(ice->getValueKind() == VK_RValue);
|
||||
assert(ice->getObjectKind() == OK_Ordinary);
|
||||
|
||||
// Rebuild the sub-expression as the pointee (function) type.
|
||||
DestType = DestType->castAs<PointerType>()->getPointeeType();
|
||||
|
||||
ExprResult result = Visit(ice->getSubExpr());
|
||||
if (!result.isUsable()) return ExprError();
|
||||
|
||||
ice->setSubExpr(result.take());
|
||||
return S.Owned(ice);
|
||||
}
|
||||
|
||||
ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, NamedDecl *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 (method->isInstance()) valueKind = VK_RValue;
|
||||
|
||||
// This is true because FunctionDecls must always have function
|
||||
// type, so we can't be resolving the entire thing at once.
|
||||
assert(type->isFunctionType());
|
||||
|
||||
// Function references aren't l-values in C.
|
||||
if (!S.getLangOptions().CPlusPlus)
|
||||
valueKind = VK_RValue;
|
||||
|
||||
// - 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;
|
||||
}
|
||||
} else if (type->isFunctionType()) {
|
||||
// Function references aren't l-values in C.
|
||||
valueKind = VK_RValue;
|
||||
}
|
||||
|
||||
// - nothing else
|
||||
} else {
|
||||
S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_decl)
|
||||
<< decl << expr->getSourceRange();
|
||||
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);
|
||||
}
|
||||
|
||||
/// Check a cast of an unknown-any type. We intentionally only
|
||||
/// trigger this for C-style casts.
|
||||
ExprResult Sema::checkUnknownAnyCast(SourceRange typeRange, QualType castType,
|
||||
|
@ -10295,18 +10466,37 @@ ExprResult Sema::checkUnknownAnyCast(SourceRange typeRange, QualType castType,
|
|||
|
||||
static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *e) {
|
||||
Expr *orig = e;
|
||||
unsigned diagID = diag::err_uncasted_use_of_unknown_any;
|
||||
while (true) {
|
||||
e = e->IgnoreParenImpCasts();
|
||||
if (CallExpr *call = dyn_cast<CallExpr>(e))
|
||||
if (CallExpr *call = dyn_cast<CallExpr>(e)) {
|
||||
e = call->getCallee();
|
||||
else
|
||||
diagID = diag::err_uncasted_call_of_unknown_any;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(isa<DeclRefExpr>(e) && "unexpected form of unknown-any expression");
|
||||
DeclRefExpr *ref = cast<DeclRefExpr>(e);
|
||||
S.Diag(ref->getLocation(), diag::err_bad_use_of_unknown_any)
|
||||
<< ref->getDecl() << orig->getSourceRange();
|
||||
SourceLocation loc;
|
||||
NamedDecl *d;
|
||||
if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) {
|
||||
loc = ref->getLocation();
|
||||
d = ref->getDecl();
|
||||
} else if (MemberExpr *mem = dyn_cast<MemberExpr>(e)) {
|
||||
loc = mem->getMemberLoc();
|
||||
d = mem->getMemberDecl();
|
||||
} else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(e)) {
|
||||
diagID = diag::err_uncasted_call_of_unknown_any;
|
||||
loc = msg->getSelectorLoc();
|
||||
d = msg->getMethodDecl();
|
||||
assert(d && "unknown method returning __unknown_any?");
|
||||
} else {
|
||||
S.Diag(e->getExprLoc(), diag::err_unsupported_unknown_any_expr)
|
||||
<< e->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
S.Diag(loc, diagID) << d << orig->getSourceRange();
|
||||
|
||||
// Never recoverable.
|
||||
return ExprError();
|
||||
|
|
|
@ -2177,6 +2177,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
|
|||
}
|
||||
// Various C++ casts that are not handled yet.
|
||||
case CK_ResolveUnknownAnyType:
|
||||
case CK_ResolveUnknownAnyTypeToReference:
|
||||
case CK_Dynamic:
|
||||
case CK_ToUnion:
|
||||
case CK_BaseToDerived:
|
||||
|
|
|
@ -55,3 +55,22 @@ Test7 test7() {
|
|||
// CHECK: call void @test7_any({{%.*}}* sret {{%.*}}, i32 5)
|
||||
return (Test7) test7_any(5);
|
||||
}
|
||||
|
||||
struct Test8 {
|
||||
__unknown_anytype foo();
|
||||
__unknown_anytype foo(int);
|
||||
|
||||
void test();
|
||||
};
|
||||
void Test8::test() {
|
||||
(int) foo();
|
||||
(int) foo(5);
|
||||
(float) this->foo();
|
||||
(float) this->foo(5);
|
||||
}
|
||||
void test8(Test8 *p) {
|
||||
(double) p->foo();
|
||||
(double) p->foo(5);
|
||||
(bool) (*p).foo();
|
||||
(bool) (*p).foo(5);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,14 @@ namespace test1 {
|
|||
// properly.
|
||||
|
||||
int x = foo; // expected-error {{cannot initialize}}
|
||||
int y = 0 + foo; // expected-error {{no known type for 'foo'; must explicitly cast this expression to use it}}
|
||||
int y = 0 + foo; // expected-error {{'foo' has unknown type}}
|
||||
return foo; // expected-error {{cannot initialize}}
|
||||
}
|
||||
}
|
||||
|
||||
namespace test2 {
|
||||
extern __unknown_anytype foo();
|
||||
void test() {
|
||||
foo(); // expected-error {{'foo' has unknown return type}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue