Skip to content

Replace current_expr_value with expression temporaries. #561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Sep 10, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Semantic/codegen support for _Current_expr_value.
This change adds support during bounds declaration checking for
_Current_expr_value.   It fills in the missing bounds for string
and array literals by using _Current_expr_value.  It also adds
code generation support for _Current_expr_value.

Existing Checked C and clang Checked C tests pass.   We need to
add tests of inferred bounds for string/array literals and of
them LLVM IR generated for _Current_expr_value.
  • Loading branch information
dtarditi committed Aug 13, 2018
commit 5d6e4e2a4b6cb467eed4f41055fb8ec01b7b3d02
11 changes: 8 additions & 3 deletions include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -4721,21 +4721,26 @@ class Sema {
// parameter bounds.
};

/// /brief Checks whether an expression is non-modifying
/// (see Checked C Spec, 3.6.1). Returns true if the expression is non-modifying,
/// false otherwise.

enum NonModifyingMessage {
NMM_None,
NMM_Error,
NMM_Note
};

/// \brief Checks whether an expression is non-modifying
/// (see Checked C Spec, 3.6.1). Returns true if the expression is non-modifying,
/// false otherwise.
bool CheckIsNonModifying(Expr *E, NonModifyingContext Req =
NonModifyingContext::NMC_Unknown,
NonModifyingMessage = NMM_Error);

BoundsExpr *CheckNonModifyingBounds(BoundsExpr *Bounds, Expr *E);

/// \brief Determine if this bounds expression contains a use of
/// _Current_expr_value.
bool ContainsCurrentExprValue(BoundsExpr *Bounds);

bool AbstractForFunctionType(BoundsAnnotations &BA,
ArrayRef<DeclaratorChunk::ParamInfo> Params);
/// \brief Take a bounds expression with positional parameters from a function
Expand Down
5 changes: 2 additions & 3 deletions lib/AST/CanonBounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,9 +749,8 @@ Result
Lexicographic::CompareImpl(const BoundsValueExpr *E1,
const BoundsValueExpr *E2) {
Result Cmp = CompareInteger(E1->getKind(), E2->getKind());
if (Cmp != Result::Equal)
return Cmp;
return CompareType(E1->getType(), E2->getType());
// The type doesn't matter - the value is the same no matter what the type.
return Cmp;
}


Expand Down
9 changes: 7 additions & 2 deletions lib/CodeGen/CGDynamicCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ void CodeGenFunction::EmitDynamicOverflowCheck(const Address BaseAddr, const Qua
// EmitDynamicCheckBlocks(Condition);
}

void CodeGenFunction::EmitDynamicBoundsCheck(const Address PtrAddr, const BoundsExpr *Bounds,
BoundsCheckKind CheckKind, llvm::Value *Val) {
void CodeGenFunction::EmitDynamicBoundsCheck(const Address PtrAddr,
llvm::Value *ValueWithBounds,
const BoundsExpr *Bounds,
BoundsCheckKind CheckKind,
llvm::Value *Val) {
if (!getLangOpts().CheckedC)
return;

Expand All @@ -99,6 +102,8 @@ void CodeGenFunction::EmitDynamicBoundsCheck(const Address PtrAddr, const Bounds

++NumDynamicChecksRange;

CurrentExprValueRAII SetCurrentValue(*this, ValueWithBounds);

// Emit the code to generate the pointer values
Address Lower = EmitPointerWithAlignment(BoundsRange->getLowerExpr());

Expand Down
28 changes: 17 additions & 11 deletions lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2469,8 +2469,8 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
LV.getQuals().setAddressSpace(ExprTy.getAddressSpace());

EmitDynamicNonNullCheck(Addr, BaseTy);
EmitDynamicBoundsCheck(Addr, E->getBoundsExpr(), E->getBoundsCheckKind(),
nullptr);
EmitDynamicBoundsCheck(Addr, Addr.getPointer(), E->getBoundsExpr(),
E->getBoundsCheckKind(), nullptr);
// We should not generate __weak write barrier on indirect reference
// of a pointer to object; as in void foo (__weak id *param); *param = 0;
// But, we continue to generate __strong write barrier on indirect write
Expand Down Expand Up @@ -3230,8 +3230,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
LValue LV = LValue::MakeVectorElt(LHS.getAddress(), Idx,
E->getBase()->getType(), LHS.getBaseInfo(), TBAAAccessInfo());

EmitDynamicBoundsCheck(LV.getVectorAddress(), E->getBoundsExpr(),
E->getBoundsCheckKind(), nullptr);
EmitDynamicBoundsCheck(LV.getVectorAddress(), LHS.getPointer(),
E->getBoundsExpr(), E->getBoundsCheckKind(), nullptr);

return LV;
}
Expand All @@ -3250,21 +3250,23 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
SignedIndices, E->getExprLoc());
LValue AddrLV = MakeAddrLValue(Addr, EltType, LV.getBaseInfo(),
CGM.getTBAAInfoForSubobject(LV, EltType));
EmitDynamicBoundsCheck(Addr, E->getBoundsExpr(), E->getBoundsCheckKind(),
nullptr);
EmitDynamicBoundsCheck(Addr, LV.getPointer(), E->getBoundsExpr(),
E->getBoundsCheckKind(), nullptr);

return AddrLV;
}

LValueBaseInfo EltBaseInfo;
TBAAAccessInfo EltTBAAInfo;
Address Addr = Address::invalid();
Address BaseAddr = Address::invalid();
if (const VariableArrayType *vla =
getContext().getAsVariableArrayType(E->getType())) {
// The base must be a pointer, which is not an aggregate. Emit
// it. It needs to be emitted first in case it's what captures
// the VLA bounds.
Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
BaseAddr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
Addr = BaseAddr;
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
EmitDynamicNonNullCheck(Addr, BaseTy);

Expand All @@ -3289,7 +3291,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// Indexing over an interface, as in "NSString *P; P[4];"

// Emit the base pointer.
Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
BaseAddr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
Addr = BaseAddr;
auto *Idx = EmitIdxAfterBase(/*Promote*/true);

CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT);
Expand Down Expand Up @@ -3332,6 +3335,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
ArrayLV = EmitLValue(Array);
auto *Idx = EmitIdxAfterBase(/*Promote*/true);

BaseAddr = ArrayLV.getAddress();
EmitDynamicNonNullCheck(ArrayLV.getAddress(), BaseTy);

// Propagate the alignment from the array itself to the result.
Expand All @@ -3343,7 +3347,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType());
} else {
// The base must be a pointer; emit it with an estimate of its alignment.
Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
BaseAddr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
Addr = BaseAddr;
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
EmitDynamicNonNullCheck(Addr, BaseTy);
Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(),
Expand All @@ -3353,7 +3358,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,

LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);

EmitDynamicBoundsCheck(Addr, E->getBoundsExpr(), E->getBoundsCheckKind(),
EmitDynamicBoundsCheck(Addr, BaseAddr.getPointer(), E->getBoundsExpr(), E->getBoundsCheckKind(),
nullptr);

if (getLangOpts().ObjC1 &&
Expand Down Expand Up @@ -3648,7 +3653,8 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
// unchecked, or is a checked array with its own bounds.
// A second reason for always checking the BaseLV is that it is the same for
// all the fields in the struct, so more of the checks should optimize away.
EmitDynamicBoundsCheck(Addr, E->getBoundsExpr(), BCK_Normal, nullptr);
EmitDynamicBoundsCheck(Addr, Addr.getPointer(), E->getBoundsExpr(),
BCK_Normal, nullptr);
} else
BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess);

Expand Down
9 changes: 8 additions & 1 deletion lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,13 @@ class ScalarExprEmitter
}
Value *VisitAsTypeExpr(AsTypeExpr *CE);
Value *VisitAtomicExpr(AtomicExpr *AE);

Value *VisitBoundsValueExpr(BoundsValueExpr *E) {
assert(E->getKind() == BoundsValueExpr::Kind::Current);
Value *Result = CGF.GetCurrentExprValue();
assert(Result);
return Result;
}
};
} // end anonymous namespace.

Expand Down Expand Up @@ -3337,7 +3344,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
if (E->getOpcode() == BO_Assign) {
BoundsExpr *BoundsCheck = CGF.GetNullTermBoundsCheck(E->getLHS());
if (BoundsCheck)
CGF.EmitDynamicBoundsCheck(LHS.getAddress(), BoundsCheck,
CGF.EmitDynamicBoundsCheck(LHS.getAddress(), LHS.getPointer(), BoundsCheck,
BoundsCheckKind::BCK_NullTermWriteAssign,
RHS);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
CurLexicalScope(nullptr), TerminateLandingPad(nullptr),
TerminateHandler(nullptr), TrapBB(nullptr),
ShouldEmitLifetimeMarkers(
shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) {
shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())),
CurrentExprValue(nullptr) {
if (!suppressNewContext)
CGM.getCXXABI().getMangleContext().startNewFunction();

Expand Down
37 changes: 35 additions & 2 deletions lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,36 @@ class CodeGenFunction : public CodeGenTypeCache {
/// specified stmt yet.
void ErrorUnsupported(const Stmt *S, const char *Type);

//===--------------------------------------------------------------------===//
// Checked C extension
//===--------------------------------------------------------------------===//

// During evaluation of bounds expressions, _Current_expr_value holds the value
// for which bounds are being computed.
llvm::Value *CurrentExprValue;
public:
llvm::Value *GetCurrentExprValue() {
return CurrentExprValue;
}

// \brief RAII object used to temporarily set the the type of
// _Current_expr_value
class CurrentExprValueRAII {
CodeGenFunction &CGF;
llvm::Value *Old;
public:
CurrentExprValueRAII(CodeGenFunction &CGF, llvm::Value *Val) : CGF(CGF) {
Old = CGF.CurrentExprValue;
CGF.CurrentExprValue = Val;
}

~CurrentExprValueRAII() {
CGF.CurrentExprValue = Old;
}
};



//===--------------------------------------------------------------------===//
// Helpers
//===--------------------------------------------------------------------===//
Expand Down Expand Up @@ -2628,8 +2658,11 @@ class CodeGenFunction : public CodeGenTypeCache {
const Address PtrAddr);
/// \brief Emit a dynamic bounds check. ValueToStore is optional and is
/// used for bounds checking writes to NUL-terminated pointers.
void EmitDynamicBoundsCheck(const Address PtrAddr, const BoundsExpr *Bounds,
BoundsCheckKind Kind, llvm::Value *ValueToStore);
void EmitDynamicBoundsCheck(const Address PtrAddr,
llvm::Value *ValueWithBounds,
const BoundsExpr *Bounds,
BoundsCheckKind Kind,
llvm::Value *ValueToStore);
void EmitDynamicBoundsCastCheck(const Address BaseAddr,
const BoundsExpr *CastBounds,
const BoundsExpr *SubExprBounds);
Expand Down
18 changes: 18 additions & 0 deletions lib/Sema/CheckedCAlias.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,3 +632,21 @@ void Sema::ComputeBoundsDependencies(ModifiedBoundsDependencies &Tracker,
Tracker.Dump(llvm::outs());
#endif
}

namespace {
bool UsesCurrentExprValue(Stmt *S) {
if (BoundsValueExpr *BE = dyn_cast<BoundsValueExpr>(S))
if (BE->getKind() == BoundsValueExpr::Kind::Current)
return true;

for (Stmt *Child : S->children())
if (UsesCurrentExprValue(Child))
return true;

return false;
}
}

bool Sema::ContainsCurrentExprValue(BoundsExpr *Bounds) {
return UsesCurrentExprValue(Bounds);
}
Loading