summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp94
1 files changed, 76 insertions, 18 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 3da21cebd9d6..abb88477062f 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -569,7 +569,15 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
// initialized it.
if (!Var->hasInitializer()) {
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
- EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
+ QualType RefType = M->getType().withoutLocalFastQualifiers();
+ if (RefType.getPointerAuth()) {
+ // Use the qualifier of the reference temporary to sign the pointer.
+ LValue LV = MakeRawAddrLValue(Object.getPointer(), RefType,
+ Object.getAlignment());
+ EmitScalarInit(E, M->getExtendingDecl(), LV, false);
+ } else {
+ EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/ true);
+ }
}
} else {
switch (M->getStorageDuration()) {
@@ -1770,16 +1778,16 @@ static ConstantEmissionKind checkVarTypeForConstantEmission(QualType type) {
/// for instance if a block or lambda or a member of a local class uses a
/// const int variable or constexpr variable from an enclosing function.
CodeGenFunction::ConstantEmission
-CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
- ValueDecl *value = refExpr->getDecl();
+CodeGenFunction::tryEmitAsConstant(const DeclRefExpr *RefExpr) {
+ const ValueDecl *Value = RefExpr->getDecl();
// The value needs to be an enum constant or a constant variable.
ConstantEmissionKind CEK;
- if (isa<ParmVarDecl>(value)) {
+ if (isa<ParmVarDecl>(Value)) {
CEK = CEK_None;
- } else if (auto *var = dyn_cast<VarDecl>(value)) {
+ } else if (const auto *var = dyn_cast<VarDecl>(Value)) {
CEK = checkVarTypeForConstantEmission(var->getType());
- } else if (isa<EnumConstantDecl>(value)) {
+ } else if (isa<EnumConstantDecl>(Value)) {
CEK = CEK_AsValueOnly;
} else {
CEK = CEK_None;
@@ -1792,15 +1800,15 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
// It's best to evaluate all the way as an r-value if that's permitted.
if (CEK != CEK_AsReferenceOnly &&
- refExpr->EvaluateAsRValue(result, getContext())) {
+ RefExpr->EvaluateAsRValue(result, getContext())) {
resultIsReference = false;
- resultType = refExpr->getType();
+ resultType = RefExpr->getType().getUnqualifiedType();
// Otherwise, try to evaluate as an l-value.
} else if (CEK != CEK_AsValueOnly &&
- refExpr->EvaluateAsLValue(result, getContext())) {
+ RefExpr->EvaluateAsLValue(result, getContext())) {
resultIsReference = true;
- resultType = value->getType();
+ resultType = Value->getType();
// Failure.
} else {
@@ -1819,7 +1827,7 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
// accessible on device. The DRE of the captured reference variable has to be
// loaded from captures.
if (CGM.getLangOpts().CUDAIsDevice && result.Val.isLValue() &&
- refExpr->refersToEnclosingVariableOrCapture()) {
+ RefExpr->refersToEnclosingVariableOrCapture()) {
auto *MD = dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl);
if (isLambdaMethod(MD) && MD->getOverloadedOperator() == OO_Call) {
const APValue::LValueBase &base = result.Val.getLValueBase();
@@ -1834,17 +1842,17 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
}
// Emit as a constant.
- auto C = ConstantEmitter(*this).emitAbstract(refExpr->getLocation(),
- result.Val, resultType);
+ llvm::Constant *C = ConstantEmitter(*this).emitAbstract(
+ RefExpr->getLocation(), result.Val, resultType);
// Make sure we emit a debug reference to the global variable.
// This should probably fire even for
- if (isa<VarDecl>(value)) {
- if (!getContext().DeclMustBeEmitted(cast<VarDecl>(value)))
- EmitDeclRefExprDbgValue(refExpr, result.Val);
+ if (isa<VarDecl>(Value)) {
+ if (!getContext().DeclMustBeEmitted(cast<VarDecl>(Value)))
+ EmitDeclRefExprDbgValue(RefExpr, result.Val);
} else {
- assert(isa<EnumConstantDecl>(value));
- EmitDeclRefExprDbgValue(refExpr, result.Val);
+ assert(isa<EnumConstantDecl>(Value));
+ EmitDeclRefExprDbgValue(RefExpr, result.Val);
}
// If we emitted a reference constant, we need to dereference that.
@@ -2235,6 +2243,15 @@ RValue CodeGenFunction::EmitLoadOfAnyValue(LValue LV, AggValueSlot Slot,
/// method emits the address of the lvalue, then loads the result as an rvalue,
/// returning the rvalue.
RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
+ // Load from __ptrauth.
+ if (PointerAuthQualifier PtrAuth = LV.getQuals().getPointerAuth()) {
+ LV.getQuals().removePointerAuth();
+ llvm::Value *Value = EmitLoadOfLValue(LV, Loc).getScalarVal();
+ return RValue::get(EmitPointerAuthUnqualify(PtrAuth, Value, LV.getType(),
+ LV.getAddress(),
+ /*known nonnull*/ false));
+ }
+
if (LV.isObjCWeak()) {
// load of a __weak object.
Address AddrWeakObj = LV.getAddress();
@@ -2490,6 +2507,13 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
return EmitStoreThroughBitfieldLValue(Src, Dst);
}
+ // Handle __ptrauth qualification by re-signing the value.
+ if (PointerAuthQualifier PointerAuth = Dst.getQuals().getPointerAuth()) {
+ Src = RValue::get(EmitPointerAuthQualify(PointerAuth, Src.getScalarVal(),
+ Dst.getType(), Dst.getAddress(),
+ /*known nonnull*/ false));
+ }
+
// There's special magic for assigning into an ARC-qualified l-value.
if (Qualifiers::ObjCLifetime Lifetime = Dst.getQuals().getObjCLifetime()) {
switch (Lifetime) {
@@ -5792,6 +5816,28 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
return EmitCallee(ICE->getSubExpr());
}
+ // Try to remember the original __ptrauth qualifier for loads of
+ // function pointers.
+ if (ICE->getCastKind() == CK_LValueToRValue) {
+ const Expr *SubExpr = ICE->getSubExpr();
+ if (const auto *PtrType = SubExpr->getType()->getAs<PointerType>()) {
+ std::pair<llvm::Value *, CGPointerAuthInfo> Result =
+ EmitOrigPointerRValue(E);
+
+ QualType FunctionType = PtrType->getPointeeType();
+ assert(FunctionType->isFunctionType());
+
+ GlobalDecl GD;
+ if (const auto *VD =
+ dyn_cast_or_null<VarDecl>(E->getReferencedDeclOfCallee())) {
+ GD = GlobalDecl(VD);
+ }
+ CGCalleeInfo CalleeInfo(FunctionType->getAs<FunctionProtoType>(), GD);
+ CGCallee Callee(CalleeInfo, Result.first, Result.second);
+ return Callee;
+ }
+ }
+
// Resolve direct calls.
} else if (auto DRE = dyn_cast<DeclRefExpr>(E)) {
if (auto FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
@@ -5854,6 +5900,18 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
switch (getEvaluationKind(E->getType())) {
case TEK_Scalar: {
+ if (PointerAuthQualifier PtrAuth =
+ E->getLHS()->getType().getPointerAuth()) {
+ LValue LV = EmitCheckedLValue(E->getLHS(), TCK_Store);
+ LValue CopiedLV = LV;
+ CopiedLV.getQuals().removePointerAuth();
+ llvm::Value *RV =
+ EmitPointerAuthQualify(PtrAuth, E->getRHS(), CopiedLV.getAddress());
+ EmitNullabilityCheck(CopiedLV, RV, E->getExprLoc());
+ EmitStoreThroughLValue(RValue::get(RV), CopiedLV);
+ return LV;
+ }
+
switch (E->getLHS()->getType().getObjCLifetime()) {
case Qualifiers::OCL_Strong:
return EmitARCStoreStrong(E, /*ignored*/ false).first;