diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXXABI.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXABI.h | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 40 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 35 |
8 files changed, 85 insertions, 23 deletions
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index 92f1c63a38..e8b6f56724 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -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())); diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index de4df3dcbe..a34ca9bcdc 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -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, diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index a35f81ca20..496c3fc0aa 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -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); } } diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 75e3a7879d..5d22fc3304 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -311,6 +311,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { break; case CK_ResolveUnknownAnyType: + case CK_ResolveUnknownAnyTypeToReference: EmitAggLoadOfLValue(E); break; diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index a3d3f439b6..ef71e89077 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -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(); diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 822a999b96..b04ff0aefb 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -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. diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 65aa46fff0..f2ab0a2e06 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -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: diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 53163ed6a5..6c864ca7f4 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -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); } |