aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGCXXABI.cpp3
-rw-r--r--lib/CodeGen/CGCXXABI.h7
-rw-r--r--lib/CodeGen/CGExpr.cpp40
-rw-r--r--lib/CodeGen/CGExprAgg.cpp1
-rw-r--r--lib/CodeGen/CGExprCXX.cpp8
-rw-r--r--lib/CodeGen/CGExprConstant.cpp1
-rw-r--r--lib/CodeGen/CGExprScalar.cpp13
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp35
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);
}