Fixup the rest of the trivial cases of the codegen of volatile. If
any body can spot codegen bugs with volatile, or knows of any in the bug database, let me know. llvm-svn: 72572
This commit is contained in:
@@ -51,9 +51,10 @@ llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) {
|
|||||||
RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc,
|
RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc,
|
||||||
bool isAggLocVolatile, bool IgnoreResult) {
|
bool isAggLocVolatile, bool IgnoreResult) {
|
||||||
if (!hasAggregateLLVMType(E->getType()))
|
if (!hasAggregateLLVMType(E->getType()))
|
||||||
return RValue::get(EmitScalarExpr(E));
|
return RValue::get(EmitScalarExpr(E, IgnoreResult));
|
||||||
else if (E->getType()->isAnyComplexType())
|
else if (E->getType()->isAnyComplexType())
|
||||||
return RValue::getComplex(EmitComplexExpr(E));
|
return RValue::getComplex(EmitComplexExpr(E, false, false,
|
||||||
|
IgnoreResult, IgnoreResult));
|
||||||
|
|
||||||
EmitAggExpr(E, AggLoc, isAggLocVolatile, IgnoreResult);
|
EmitAggExpr(E, AggLoc, isAggLocVolatile, IgnoreResult);
|
||||||
return RValue::getAggregate(AggLoc, isAggLocVolatile);
|
return RValue::getAggregate(AggLoc, isAggLocVolatile);
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ void AggExprEmitter::VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
|
void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
|
||||||
CGF.EmitAnyExpr(E->getLHS());
|
CGF.EmitAnyExpr(E->getLHS(), 0, false, true);
|
||||||
CGF.EmitAggExpr(E->getRHS(), DestPtr, VolatileDest);
|
CGF.EmitAggExpr(E->getRHS(), DestPtr, VolatileDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,6 +311,7 @@ void AggExprEmitter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {
|
void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {
|
||||||
|
// FIXME: Ignore result?
|
||||||
// FIXME: Are initializers affected by volatile?
|
// FIXME: Are initializers affected by volatile?
|
||||||
if (isa<ImplicitValueInitExpr>(E)) {
|
if (isa<ImplicitValueInitExpr>(E)) {
|
||||||
EmitNullInitializationToLValue(LV, E->getType());
|
EmitNullInitializationToLValue(LV, E->getType());
|
||||||
|
|||||||
@@ -33,8 +33,17 @@ class VISIBILITY_HIDDEN ComplexExprEmitter
|
|||||||
: public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
|
: public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
|
||||||
CodeGenFunction &CGF;
|
CodeGenFunction &CGF;
|
||||||
CGBuilderTy &Builder;
|
CGBuilderTy &Builder;
|
||||||
|
// True is we should ignore the value of a
|
||||||
|
bool IgnoreReal;
|
||||||
|
bool IgnoreImag;
|
||||||
|
// True if we should ignore the value of a=b
|
||||||
|
bool IgnoreRealAssign;
|
||||||
|
bool IgnoreImagAssign;
|
||||||
public:
|
public:
|
||||||
ComplexExprEmitter(CodeGenFunction &cgf) : CGF(cgf), Builder(CGF.Builder) {
|
ComplexExprEmitter(CodeGenFunction &cgf, bool ir=false, bool ii=false,
|
||||||
|
bool irn=false, bool iin=false)
|
||||||
|
: CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii),
|
||||||
|
IgnoreRealAssign(irn), IgnoreImagAssign(iin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -42,6 +51,27 @@ public:
|
|||||||
// Utilities
|
// Utilities
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
bool TestAndClearIgnoreReal() {
|
||||||
|
bool I = IgnoreReal;
|
||||||
|
IgnoreReal = false;
|
||||||
|
return I;
|
||||||
|
}
|
||||||
|
bool TestAndClearIgnoreImag() {
|
||||||
|
bool I = IgnoreImag;
|
||||||
|
IgnoreImag = false;
|
||||||
|
return I;
|
||||||
|
}
|
||||||
|
bool TestAndClearIgnoreRealAssign() {
|
||||||
|
bool I = IgnoreRealAssign;
|
||||||
|
IgnoreRealAssign = false;
|
||||||
|
return I;
|
||||||
|
}
|
||||||
|
bool TestAndClearIgnoreImagAssign() {
|
||||||
|
bool I = IgnoreImagAssign;
|
||||||
|
IgnoreImagAssign = false;
|
||||||
|
return I;
|
||||||
|
}
|
||||||
|
|
||||||
/// EmitLoadOfLValue - Given an expression with complex type that represents a
|
/// EmitLoadOfLValue - Given an expression with complex type that represents a
|
||||||
/// value l-value, this method emits the address of the l-value, then loads
|
/// value l-value, this method emits the address of the l-value, then loads
|
||||||
/// and returns the result.
|
/// and returns the result.
|
||||||
@@ -111,6 +141,10 @@ public:
|
|||||||
}
|
}
|
||||||
ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
|
ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
|
||||||
ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) {
|
ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) {
|
||||||
|
TestAndClearIgnoreReal();
|
||||||
|
TestAndClearIgnoreImag();
|
||||||
|
TestAndClearIgnoreRealAssign();
|
||||||
|
TestAndClearIgnoreImagAssign();
|
||||||
return Visit(E->getSubExpr());
|
return Visit(E->getSubExpr());
|
||||||
}
|
}
|
||||||
ComplexPairTy VisitUnaryMinus (const UnaryOperator *E);
|
ComplexPairTy VisitUnaryMinus (const UnaryOperator *E);
|
||||||
@@ -206,19 +240,25 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr,
|
|||||||
llvm::SmallString<64> Name(SrcPtr->getNameStart(),
|
llvm::SmallString<64> Name(SrcPtr->getNameStart(),
|
||||||
SrcPtr->getNameStart()+SrcPtr->getNameLen());
|
SrcPtr->getNameStart()+SrcPtr->getNameLen());
|
||||||
|
|
||||||
|
llvm::Value *Real=0, *Imag=0;
|
||||||
|
|
||||||
|
if (!IgnoreReal) {
|
||||||
Name += ".realp";
|
Name += ".realp";
|
||||||
llvm::Value *RealPtr = Builder.CreateStructGEP(SrcPtr, 0, Name.c_str());
|
llvm::Value *RealPtr = Builder.CreateStructGEP(SrcPtr, 0, Name.c_str());
|
||||||
|
|
||||||
Name.pop_back(); // .realp -> .real
|
Name.pop_back(); // .realp -> .real
|
||||||
llvm::Value *Real = Builder.CreateLoad(RealPtr, isVolatile, Name.c_str());
|
Real = Builder.CreateLoad(RealPtr, isVolatile, Name.c_str());
|
||||||
|
|
||||||
Name.resize(Name.size()-4); // .real -> .imagp
|
Name.resize(Name.size()-4); // .real -> .imagp
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IgnoreImag) {
|
||||||
Name += "imagp";
|
Name += "imagp";
|
||||||
|
|
||||||
llvm::Value *ImagPtr = Builder.CreateStructGEP(SrcPtr, 1, Name.c_str());
|
llvm::Value *ImagPtr = Builder.CreateStructGEP(SrcPtr, 1, Name.c_str());
|
||||||
|
|
||||||
Name.pop_back(); // .imagp -> .imag
|
Name.pop_back(); // .imagp -> .imag
|
||||||
llvm::Value *Imag = Builder.CreateLoad(ImagPtr, isVolatile, Name.c_str());
|
Imag = Builder.CreateLoad(ImagPtr, isVolatile, Name.c_str());
|
||||||
|
}
|
||||||
return ComplexPairTy(Real, Imag);
|
return ComplexPairTy(Real, Imag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,6 +371,10 @@ ComplexPairTy ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
|
ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
|
||||||
|
TestAndClearIgnoreReal();
|
||||||
|
TestAndClearIgnoreImag();
|
||||||
|
TestAndClearIgnoreRealAssign();
|
||||||
|
TestAndClearIgnoreImagAssign();
|
||||||
ComplexPairTy Op = Visit(E->getSubExpr());
|
ComplexPairTy Op = Visit(E->getSubExpr());
|
||||||
llvm::Value *ResR = Builder.CreateNeg(Op.first, "neg.r");
|
llvm::Value *ResR = Builder.CreateNeg(Op.first, "neg.r");
|
||||||
llvm::Value *ResI = Builder.CreateNeg(Op.second, "neg.i");
|
llvm::Value *ResI = Builder.CreateNeg(Op.second, "neg.i");
|
||||||
@@ -338,6 +382,10 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
|
ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
|
||||||
|
TestAndClearIgnoreReal();
|
||||||
|
TestAndClearIgnoreImag();
|
||||||
|
TestAndClearIgnoreRealAssign();
|
||||||
|
TestAndClearIgnoreImagAssign();
|
||||||
// ~(a+ib) = a + i*-b
|
// ~(a+ib) = a + i*-b
|
||||||
ComplexPairTy Op = Visit(E->getSubExpr());
|
ComplexPairTy Op = Visit(E->getSubExpr());
|
||||||
llvm::Value *ResI = Builder.CreateNeg(Op.second, "conj.i");
|
llvm::Value *ResI = Builder.CreateNeg(Op.second, "conj.i");
|
||||||
@@ -404,6 +452,10 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
|
|||||||
|
|
||||||
ComplexExprEmitter::BinOpInfo
|
ComplexExprEmitter::BinOpInfo
|
||||||
ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
|
ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
|
||||||
|
TestAndClearIgnoreReal();
|
||||||
|
TestAndClearIgnoreImag();
|
||||||
|
TestAndClearIgnoreRealAssign();
|
||||||
|
TestAndClearIgnoreImagAssign();
|
||||||
BinOpInfo Ops;
|
BinOpInfo Ops;
|
||||||
Ops.LHS = Visit(E->getLHS());
|
Ops.LHS = Visit(E->getLHS());
|
||||||
Ops.RHS = Visit(E->getRHS());
|
Ops.RHS = Visit(E->getRHS());
|
||||||
@@ -416,20 +468,27 @@ ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
|
|||||||
ComplexPairTy ComplexExprEmitter::
|
ComplexPairTy ComplexExprEmitter::
|
||||||
EmitCompoundAssign(const CompoundAssignOperator *E,
|
EmitCompoundAssign(const CompoundAssignOperator *E,
|
||||||
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
|
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
|
||||||
|
TestAndClearIgnoreReal();
|
||||||
|
TestAndClearIgnoreImag();
|
||||||
|
bool ignreal = TestAndClearIgnoreRealAssign();
|
||||||
|
bool ignimag = TestAndClearIgnoreImagAssign();
|
||||||
QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType();
|
QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType();
|
||||||
|
|
||||||
// Load the LHS and RHS operands.
|
BinOpInfo OpInfo;
|
||||||
|
|
||||||
|
// Load the RHS and LHS operands.
|
||||||
|
// __block variables need to have the rhs evaluated first, plus this should
|
||||||
|
// improve codegen a little. It is possible for the RHS to be complex or
|
||||||
|
// scalar.
|
||||||
|
OpInfo.Ty = E->getComputationResultType();
|
||||||
|
OpInfo.RHS = EmitCast(E->getRHS(), OpInfo.Ty);
|
||||||
|
|
||||||
LValue LHSLV = CGF.EmitLValue(E->getLHS());
|
LValue LHSLV = CGF.EmitLValue(E->getLHS());
|
||||||
|
|
||||||
BinOpInfo OpInfo;
|
|
||||||
OpInfo.Ty = E->getComputationResultType();
|
|
||||||
|
|
||||||
// We know the LHS is a complex lvalue.
|
// We know the LHS is a complex lvalue.
|
||||||
OpInfo.LHS = EmitLoadOfComplex(LHSLV.getAddress(), LHSLV.isVolatileQualified());
|
OpInfo.LHS=EmitLoadOfComplex(LHSLV.getAddress(),LHSLV.isVolatileQualified());
|
||||||
OpInfo.LHS = EmitComplexToComplexCast(OpInfo.LHS, LHSTy, OpInfo.Ty);
|
OpInfo.LHS=EmitComplexToComplexCast(OpInfo.LHS, LHSTy, OpInfo.Ty);
|
||||||
|
|
||||||
// It is possible for the RHS to be complex or scalar.
|
|
||||||
OpInfo.RHS = EmitCast(E->getRHS(), OpInfo.Ty);
|
|
||||||
|
|
||||||
// Expand the binary operator.
|
// Expand the binary operator.
|
||||||
ComplexPairTy Result = (this->*Func)(OpInfo);
|
ComplexPairTy Result = (this->*Func)(OpInfo);
|
||||||
@@ -439,10 +498,19 @@ EmitCompoundAssign(const CompoundAssignOperator *E,
|
|||||||
|
|
||||||
// Store the result value into the LHS lvalue.
|
// Store the result value into the LHS lvalue.
|
||||||
EmitStoreOfComplex(Result, LHSLV.getAddress(), LHSLV.isVolatileQualified());
|
EmitStoreOfComplex(Result, LHSLV.getAddress(), LHSLV.isVolatileQualified());
|
||||||
return Result;
|
// And now return the LHS
|
||||||
|
IgnoreReal = ignreal;
|
||||||
|
IgnoreImag = ignimag;
|
||||||
|
IgnoreRealAssign = ignreal;
|
||||||
|
IgnoreImagAssign = ignimag;
|
||||||
|
return EmitLoadOfComplex(LHSLV.getAddress(), LHSLV.isVolatileQualified());
|
||||||
}
|
}
|
||||||
|
|
||||||
ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
||||||
|
TestAndClearIgnoreReal();
|
||||||
|
TestAndClearIgnoreImag();
|
||||||
|
bool ignreal = TestAndClearIgnoreRealAssign();
|
||||||
|
bool ignimag = TestAndClearIgnoreImagAssign();
|
||||||
assert(CGF.getContext().getCanonicalType(E->getLHS()->getType()) ==
|
assert(CGF.getContext().getCanonicalType(E->getLHS()->getType()) ==
|
||||||
CGF.getContext().getCanonicalType(E->getRHS()->getType()) &&
|
CGF.getContext().getCanonicalType(E->getRHS()->getType()) &&
|
||||||
"Invalid assignment");
|
"Invalid assignment");
|
||||||
@@ -454,7 +522,12 @@ ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
|||||||
|
|
||||||
// Store into it.
|
// Store into it.
|
||||||
EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified());
|
EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified());
|
||||||
return Val;
|
// And now return the LHS
|
||||||
|
IgnoreReal = ignreal;
|
||||||
|
IgnoreImag = ignimag;
|
||||||
|
IgnoreRealAssign = ignreal;
|
||||||
|
IgnoreImagAssign = ignimag;
|
||||||
|
return EmitLoadOfComplex(LHS.getAddress(), LHS.isVolatileQualified());
|
||||||
}
|
}
|
||||||
|
|
||||||
ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
|
ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
|
||||||
@@ -465,6 +538,10 @@ ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
|
|||||||
|
|
||||||
ComplexPairTy ComplexExprEmitter::
|
ComplexPairTy ComplexExprEmitter::
|
||||||
VisitConditionalOperator(const ConditionalOperator *E) {
|
VisitConditionalOperator(const ConditionalOperator *E) {
|
||||||
|
TestAndClearIgnoreReal();
|
||||||
|
TestAndClearIgnoreImag();
|
||||||
|
TestAndClearIgnoreRealAssign();
|
||||||
|
TestAndClearIgnoreImagAssign();
|
||||||
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
|
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
|
||||||
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
|
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
|
||||||
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
|
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
|
||||||
@@ -509,6 +586,12 @@ ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
||||||
|
bool Ignore = TestAndClearIgnoreReal();
|
||||||
|
(void)Ignore;
|
||||||
|
assert (Ignore == false && "init list ignored");
|
||||||
|
Ignore = TestAndClearIgnoreImag();
|
||||||
|
(void)Ignore;
|
||||||
|
assert (Ignore == false && "init list ignored");
|
||||||
if (E->getNumInits())
|
if (E->getNumInits())
|
||||||
return Visit(E->getInit(0));
|
return Visit(E->getInit(0));
|
||||||
|
|
||||||
@@ -541,11 +624,14 @@ ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
|
|||||||
|
|
||||||
/// EmitComplexExpr - Emit the computation of the specified expression of
|
/// EmitComplexExpr - Emit the computation of the specified expression of
|
||||||
/// complex type, ignoring the result.
|
/// complex type, ignoring the result.
|
||||||
ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E) {
|
ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal,
|
||||||
|
bool IgnoreImag, bool IgnoreRealAssign, bool IgnoreImagAssign) {
|
||||||
assert(E && E->getType()->isAnyComplexType() &&
|
assert(E && E->getType()->isAnyComplexType() &&
|
||||||
"Invalid complex expression to emit");
|
"Invalid complex expression to emit");
|
||||||
|
|
||||||
return ComplexExprEmitter(*this).Visit(const_cast<Expr*>(E));
|
return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag, IgnoreRealAssign,
|
||||||
|
IgnoreImagAssign)
|
||||||
|
.Visit(const_cast<Expr*>(E));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitComplexExprIntoAddr - Emit the computation of the specified expression
|
/// EmitComplexExprIntoAddr - Emit the computation of the specified expression
|
||||||
|
|||||||
@@ -48,17 +48,22 @@ class VISIBILITY_HIDDEN ScalarExprEmitter
|
|||||||
: public StmtVisitor<ScalarExprEmitter, Value*> {
|
: public StmtVisitor<ScalarExprEmitter, Value*> {
|
||||||
CodeGenFunction &CGF;
|
CodeGenFunction &CGF;
|
||||||
CGBuilderTy &Builder;
|
CGBuilderTy &Builder;
|
||||||
|
bool IgnoreResultAssign;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ScalarExprEmitter(CodeGenFunction &cgf) : CGF(cgf),
|
ScalarExprEmitter(CodeGenFunction &cgf, bool ira=false)
|
||||||
Builder(CGF.Builder) {
|
: CGF(cgf), Builder(CGF.Builder), IgnoreResultAssign(ira) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Utilities
|
// Utilities
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
bool TestAndClearIgnoreResultAssign() {
|
||||||
|
bool I = IgnoreResultAssign; IgnoreResultAssign = false;
|
||||||
|
return I; }
|
||||||
|
|
||||||
const llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); }
|
const llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); }
|
||||||
LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); }
|
LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); }
|
||||||
|
|
||||||
@@ -172,6 +177,9 @@ public:
|
|||||||
Value *VisitPredefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); }
|
Value *VisitPredefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); }
|
||||||
|
|
||||||
Value *VisitInitListExpr(InitListExpr *E) {
|
Value *VisitInitListExpr(InitListExpr *E) {
|
||||||
|
bool Ignore = TestAndClearIgnoreResultAssign();
|
||||||
|
(void)Ignore;
|
||||||
|
assert (Ignore == false && "init list ignored");
|
||||||
unsigned NumInitElements = E->getNumInits();
|
unsigned NumInitElements = E->getNumInits();
|
||||||
|
|
||||||
if (E->hadArrayRangeDesignator()) {
|
if (E->hadArrayRangeDesignator()) {
|
||||||
@@ -252,6 +260,8 @@ public:
|
|||||||
}
|
}
|
||||||
Value *VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
|
Value *VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
|
||||||
Value *VisitUnaryPlus(const UnaryOperator *E) {
|
Value *VisitUnaryPlus(const UnaryOperator *E) {
|
||||||
|
// This differs from gcc, though, most likely due to a bug in gcc.
|
||||||
|
TestAndClearIgnoreResultAssign();
|
||||||
return Visit(E->getSubExpr());
|
return Visit(E->getSubExpr());
|
||||||
}
|
}
|
||||||
Value *VisitUnaryMinus (const UnaryOperator *E);
|
Value *VisitUnaryMinus (const UnaryOperator *E);
|
||||||
@@ -543,6 +553,8 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
|
Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
|
||||||
|
TestAndClearIgnoreResultAssign();
|
||||||
|
|
||||||
// Emit subscript expressions in rvalue context's. For most cases, this just
|
// Emit subscript expressions in rvalue context's. For most cases, this just
|
||||||
// loads the lvalue formed by the subscript expr. However, we have to be
|
// loads the lvalue formed by the subscript expr. However, we have to be
|
||||||
// careful, because the base of a vector subscript is occasionally an rvalue,
|
// careful, because the base of a vector subscript is occasionally an rvalue,
|
||||||
@@ -603,6 +615,9 @@ Value *ScalarExprEmitter::VisitImplicitCastExpr(const ImplicitCastExpr *E) {
|
|||||||
// have to handle a more broad range of conversions than explicit casts, as they
|
// have to handle a more broad range of conversions than explicit casts, as they
|
||||||
// handle things like function to ptr-to-function decay etc.
|
// handle things like function to ptr-to-function decay etc.
|
||||||
Value *ScalarExprEmitter::EmitCastExpr(const Expr *E, QualType DestTy) {
|
Value *ScalarExprEmitter::EmitCastExpr(const Expr *E, QualType DestTy) {
|
||||||
|
if (!DestTy->isVoidType())
|
||||||
|
TestAndClearIgnoreResultAssign();
|
||||||
|
|
||||||
// Handle cases where the source is an non-complex type.
|
// Handle cases where the source is an non-complex type.
|
||||||
|
|
||||||
if (!CGF.hasAggregateLLVMType(E->getType())) {
|
if (!CGF.hasAggregateLLVMType(E->getType())) {
|
||||||
@@ -614,13 +629,25 @@ Value *ScalarExprEmitter::EmitCastExpr(const Expr *E, QualType DestTy) {
|
|||||||
|
|
||||||
if (E->getType()->isAnyComplexType()) {
|
if (E->getType()->isAnyComplexType()) {
|
||||||
// Handle cases where the source is a complex type.
|
// Handle cases where the source is a complex type.
|
||||||
return EmitComplexToScalarConversion(CGF.EmitComplexExpr(E), E->getType(),
|
bool IgnoreImag = true;
|
||||||
DestTy);
|
bool IgnoreImagAssign = true;
|
||||||
|
bool IgnoreReal = IgnoreResultAssign;
|
||||||
|
bool IgnoreRealAssign = IgnoreResultAssign;
|
||||||
|
if (DestTy->isBooleanType())
|
||||||
|
IgnoreImagAssign = IgnoreImag = false;
|
||||||
|
else if (DestTy->isVoidType()) {
|
||||||
|
IgnoreReal = IgnoreImag = false;
|
||||||
|
IgnoreRealAssign = IgnoreImagAssign = true;
|
||||||
|
}
|
||||||
|
CodeGenFunction::ComplexPairTy V
|
||||||
|
= CGF.EmitComplexExpr(E, IgnoreReal, IgnoreImag, IgnoreRealAssign,
|
||||||
|
IgnoreImagAssign);
|
||||||
|
return EmitComplexToScalarConversion(V, E->getType(), DestTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Okay, this is a cast from an aggregate. It must be a cast to void. Just
|
// Okay, this is a cast from an aggregate. It must be a cast to void. Just
|
||||||
// evaluate the result and return.
|
// evaluate the result and return.
|
||||||
CGF.EmitAggExpr(E, 0, false);
|
CGF.EmitAggExpr(E, 0, false, true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,11 +731,13 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
|
|||||||
|
|
||||||
|
|
||||||
Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
|
Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
|
||||||
|
TestAndClearIgnoreResultAssign();
|
||||||
Value *Op = Visit(E->getSubExpr());
|
Value *Op = Visit(E->getSubExpr());
|
||||||
return Builder.CreateNeg(Op, "neg");
|
return Builder.CreateNeg(Op, "neg");
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *ScalarExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
|
Value *ScalarExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
|
||||||
|
TestAndClearIgnoreResultAssign();
|
||||||
Value *Op = Visit(E->getSubExpr());
|
Value *Op = Visit(E->getSubExpr());
|
||||||
return Builder.CreateNot(Op, "neg");
|
return Builder.CreateNot(Op, "neg");
|
||||||
}
|
}
|
||||||
@@ -757,17 +786,20 @@ ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
|
|||||||
Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) {
|
Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) {
|
||||||
Expr *Op = E->getSubExpr();
|
Expr *Op = E->getSubExpr();
|
||||||
if (Op->getType()->isAnyComplexType())
|
if (Op->getType()->isAnyComplexType())
|
||||||
return CGF.EmitComplexExpr(Op).first;
|
return CGF.EmitComplexExpr(Op, false, true, false, true).first;
|
||||||
return Visit(Op);
|
return Visit(Op);
|
||||||
}
|
}
|
||||||
Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) {
|
Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) {
|
||||||
Expr *Op = E->getSubExpr();
|
Expr *Op = E->getSubExpr();
|
||||||
if (Op->getType()->isAnyComplexType())
|
if (Op->getType()->isAnyComplexType())
|
||||||
return CGF.EmitComplexExpr(Op).second;
|
return CGF.EmitComplexExpr(Op, true, false, true, false).second;
|
||||||
|
|
||||||
// __imag on a scalar returns zero. Emit it the subexpr to ensure side
|
// __imag on a scalar returns zero. Emit the subexpr to ensure side
|
||||||
// effects are evaluated.
|
// effects are evaluated, but not the actual value.
|
||||||
CGF.EmitScalarExpr(Op);
|
if (E->isLvalue(CGF.getContext()) == Expr::LV_Valid)
|
||||||
|
CGF.EmitLValue(Op);
|
||||||
|
else
|
||||||
|
CGF.EmitScalarExpr(Op, true);
|
||||||
return llvm::Constant::getNullValue(ConvertType(E->getType()));
|
return llvm::Constant::getNullValue(ConvertType(E->getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,6 +815,7 @@ Value *ScalarExprEmitter::VisitUnaryOffsetOf(const UnaryOperator *E)
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) {
|
BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) {
|
||||||
|
TestAndClearIgnoreResultAssign();
|
||||||
BinOpInfo Result;
|
BinOpInfo Result;
|
||||||
Result.LHS = Visit(E->getLHS());
|
Result.LHS = Visit(E->getLHS());
|
||||||
Result.RHS = Visit(E->getRHS());
|
Result.RHS = Visit(E->getRHS());
|
||||||
@@ -793,6 +826,7 @@ BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) {
|
|||||||
|
|
||||||
Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
|
Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
|
||||||
Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) {
|
Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) {
|
||||||
|
bool Ignore = TestAndClearIgnoreResultAssign();
|
||||||
QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType();
|
QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType();
|
||||||
|
|
||||||
BinOpInfo OpInfo;
|
BinOpInfo OpInfo;
|
||||||
@@ -827,13 +861,18 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
|
|||||||
// handled specially because the result is altered by the store,
|
// handled specially because the result is altered by the store,
|
||||||
// i.e., [C99 6.5.16p1] 'An assignment expression has the value of
|
// i.e., [C99 6.5.16p1] 'An assignment expression has the value of
|
||||||
// the left operand after the assignment...'.
|
// the left operand after the assignment...'.
|
||||||
if (LHSLV.isBitfield())
|
if (LHSLV.isBitfield()) {
|
||||||
|
if (!LHSLV.isVolatileQualified()) {
|
||||||
CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy,
|
CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy,
|
||||||
&Result);
|
&Result);
|
||||||
else
|
|
||||||
CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV, LHSTy);
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
|
} else
|
||||||
|
CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy);
|
||||||
|
} else
|
||||||
|
CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV, LHSTy);
|
||||||
|
if (Ignore)
|
||||||
|
return 0;
|
||||||
|
return EmitLoadOfLValue(LHSLV, E->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1125,6 +1164,7 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
|
|||||||
|
|
||||||
Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
|
Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
|
||||||
unsigned SICmpOpc, unsigned FCmpOpc) {
|
unsigned SICmpOpc, unsigned FCmpOpc) {
|
||||||
|
TestAndClearIgnoreResultAssign();
|
||||||
Value *Result;
|
Value *Result;
|
||||||
QualType LHSTy = E->getLHS()->getType();
|
QualType LHSTy = E->getLHS()->getType();
|
||||||
if (!LHSTy->isAnyComplexType() && !LHSTy->isVectorType()) {
|
if (!LHSTy->isAnyComplexType() && !LHSTy->isVectorType()) {
|
||||||
@@ -1193,8 +1233,10 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
||||||
// __block variables need to have the rhs evaluated first, plus
|
bool Ignore = TestAndClearIgnoreResultAssign();
|
||||||
// this should improve codegen just a little.
|
|
||||||
|
// __block variables need to have the rhs evaluated first, plus this should
|
||||||
|
// improve codegen just a little.
|
||||||
Value *RHS = Visit(E->getRHS());
|
Value *RHS = Visit(E->getRHS());
|
||||||
LValue LHS = EmitLValue(E->getLHS());
|
LValue LHS = EmitLValue(E->getLHS());
|
||||||
|
|
||||||
@@ -1202,14 +1244,18 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
|
|||||||
// because the result is altered by the store, i.e., [C99 6.5.16p1]
|
// because the result is altered by the store, i.e., [C99 6.5.16p1]
|
||||||
// 'An assignment expression has the value of the left operand after
|
// 'An assignment expression has the value of the left operand after
|
||||||
// the assignment...'.
|
// the assignment...'.
|
||||||
if (LHS.isBitfield())
|
if (LHS.isBitfield()) {
|
||||||
|
if (!LHS.isVolatileQualified()) {
|
||||||
CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, E->getType(),
|
CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, E->getType(),
|
||||||
&RHS);
|
&RHS);
|
||||||
else
|
|
||||||
CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS, E->getType());
|
|
||||||
|
|
||||||
// Return the RHS.
|
|
||||||
return RHS;
|
return RHS;
|
||||||
|
} else
|
||||||
|
CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, E->getType());
|
||||||
|
} else
|
||||||
|
CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS, E->getType());
|
||||||
|
if (Ignore)
|
||||||
|
return 0;
|
||||||
|
return EmitLoadOfLValue(LHS, E->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
|
Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
|
||||||
@@ -1339,6 +1385,7 @@ static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E) {
|
|||||||
|
|
||||||
Value *ScalarExprEmitter::
|
Value *ScalarExprEmitter::
|
||||||
VisitConditionalOperator(const ConditionalOperator *E) {
|
VisitConditionalOperator(const ConditionalOperator *E) {
|
||||||
|
TestAndClearIgnoreResultAssign();
|
||||||
// If the condition constant folds and can be elided, try to avoid emitting
|
// If the condition constant folds and can be elided, try to avoid emitting
|
||||||
// the condition and the dead arm.
|
// the condition and the dead arm.
|
||||||
if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getCond())){
|
if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getCond())){
|
||||||
@@ -1443,6 +1490,7 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
|
|||||||
if (!ArgPtr)
|
if (!ArgPtr)
|
||||||
return Builder.CreateVAArg(ArgValue, ConvertType(VE->getType()));
|
return Builder.CreateVAArg(ArgValue, ConvertType(VE->getType()));
|
||||||
|
|
||||||
|
// FIXME Volatility.
|
||||||
return Builder.CreateLoad(ArgPtr);
|
return Builder.CreateLoad(ArgPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1454,13 +1502,14 @@ Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *BE) {
|
|||||||
// Entry Point into this File
|
// Entry Point into this File
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// EmitComplexExpr - Emit the computation of the specified expression of
|
/// EmitScalarExpr - Emit the computation of the specified expression of
|
||||||
/// complex type, ignoring the result.
|
/// scalar type, ignoring the result.
|
||||||
Value *CodeGenFunction::EmitScalarExpr(const Expr *E) {
|
Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) {
|
||||||
assert(E && !hasAggregateLLVMType(E->getType()) &&
|
assert(E && !hasAggregateLLVMType(E->getType()) &&
|
||||||
"Invalid scalar expression to emit");
|
"Invalid scalar expression to emit");
|
||||||
|
|
||||||
return ScalarExprEmitter(*this).Visit(const_cast<Expr*>(E));
|
return ScalarExprEmitter(*this, IgnoreResultAssign)
|
||||||
|
.Visit(const_cast<Expr*>(E));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitScalarConversion - Emit a conversion from the specified type to the
|
/// EmitScalarConversion - Emit a conversion from the specified type to the
|
||||||
|
|||||||
@@ -727,7 +727,7 @@ public:
|
|||||||
|
|
||||||
/// EmitScalarExpr - Emit the computation of the specified expression of LLVM
|
/// EmitScalarExpr - Emit the computation of the specified expression of LLVM
|
||||||
/// scalar type, returning the result.
|
/// scalar type, returning the result.
|
||||||
llvm::Value *EmitScalarExpr(const Expr *E);
|
llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign=false);
|
||||||
|
|
||||||
/// EmitScalarConversion - Emit a conversion from the specified type to the
|
/// EmitScalarConversion - Emit a conversion from the specified type to the
|
||||||
/// specified destination type, both of which are LLVM scalar types.
|
/// specified destination type, both of which are LLVM scalar types.
|
||||||
@@ -749,7 +749,10 @@ public:
|
|||||||
|
|
||||||
/// EmitComplexExpr - Emit the computation of the specified expression of
|
/// EmitComplexExpr - Emit the computation of the specified expression of
|
||||||
/// complex type, returning the result.
|
/// complex type, returning the result.
|
||||||
ComplexPairTy EmitComplexExpr(const Expr *E);
|
ComplexPairTy EmitComplexExpr(const Expr *E, bool IgnoreReal = false,
|
||||||
|
bool IgnoreImag = false,
|
||||||
|
bool IgnoreRealAssign = false,
|
||||||
|
bool IgnoreImagAssign = false);
|
||||||
|
|
||||||
/// EmitComplexExprIntoAddr - Emit the computation of the specified expression
|
/// EmitComplexExprIntoAddr - Emit the computation of the specified expression
|
||||||
/// of complex type, storing into the specified Value*.
|
/// of complex type, storing into the specified Value*.
|
||||||
|
|||||||
139
clang/test/CodeGen/volatile-1.c
Normal file
139
clang/test/CodeGen/volatile-1.c
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
// RUN: clang-cc -Wno-unused-value -emit-llvm < %s -o %t &&
|
||||||
|
// RUN: grep volatile %t | count 145 &&
|
||||||
|
// RUN: grep memcpy %t | count 4
|
||||||
|
|
||||||
|
volatile int i, j, k;
|
||||||
|
volatile int ar[5];
|
||||||
|
volatile char c;
|
||||||
|
volatile _Complex int ci;
|
||||||
|
volatile struct S {
|
||||||
|
#ifdef __cplusplus
|
||||||
|
void operator =(volatile struct S&o) volatile;
|
||||||
|
#endif
|
||||||
|
int i;
|
||||||
|
} a, b;
|
||||||
|
|
||||||
|
//void operator =(volatile struct S&o1, volatile struct S&o2) volatile;
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// A use.
|
||||||
|
i;
|
||||||
|
// A use of the real part
|
||||||
|
(float)(ci);
|
||||||
|
// A use.
|
||||||
|
(void)ci;
|
||||||
|
// A use.
|
||||||
|
(void)a;
|
||||||
|
// Not a use.
|
||||||
|
(void)(ci=ci);
|
||||||
|
// Not a use.
|
||||||
|
(void)(i=j);
|
||||||
|
ci+=ci;
|
||||||
|
(ci += ci) + ci;
|
||||||
|
asm("nop");
|
||||||
|
(i += j) + k;
|
||||||
|
asm("nop");
|
||||||
|
// A use
|
||||||
|
(i += j) + 1;
|
||||||
|
asm("nop");
|
||||||
|
ci+ci;
|
||||||
|
// A use.
|
||||||
|
__real i;
|
||||||
|
// A use.
|
||||||
|
+ci;
|
||||||
|
asm("nop");
|
||||||
|
// Not a use.
|
||||||
|
(void)(i=i);
|
||||||
|
(float)(i=i);
|
||||||
|
// A use.
|
||||||
|
(void)i;
|
||||||
|
i=i;
|
||||||
|
i=i=i;
|
||||||
|
#ifndef __cplusplus
|
||||||
|
// Not a use.
|
||||||
|
(void)__builtin_choose_expr(0, i=i, j=j);
|
||||||
|
#endif
|
||||||
|
// A use.
|
||||||
|
k ? (i=i) : (j=j);
|
||||||
|
(void)(i,(i=i));
|
||||||
|
i=i,i;
|
||||||
|
(i=j,k=j);
|
||||||
|
(i=j,k);
|
||||||
|
(i,j);
|
||||||
|
i=c=k;
|
||||||
|
i+=k;
|
||||||
|
// A use of both.
|
||||||
|
ci;
|
||||||
|
#ifndef __cplusplus
|
||||||
|
// A use of _real.
|
||||||
|
(int)ci;
|
||||||
|
// A use of both.
|
||||||
|
(_Bool)ci;
|
||||||
|
#endif
|
||||||
|
ci=ci;
|
||||||
|
ci=ci=ci;
|
||||||
|
__imag ci = __imag ci = __imag ci;
|
||||||
|
// Not a use.
|
||||||
|
__real (i = j);
|
||||||
|
// Not a use.
|
||||||
|
__imag i;
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Test cases we get wrong.
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Test cases where we intentionally differ from gcc, due to suspected bugs in
|
||||||
|
// gcc.
|
||||||
|
|
||||||
|
// Not a use. gcc forgets to do the assignment.
|
||||||
|
((a=a),a);
|
||||||
|
|
||||||
|
// Not a use. gcc gets this wrong, it doesn't emit the copy!
|
||||||
|
// (void)(a=a);
|
||||||
|
|
||||||
|
// Not a use. gcc got this wrong in 4.2 and omitted the side effects
|
||||||
|
// entirely, but it is fixed in 4.4.0.
|
||||||
|
__imag (i = j);
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
// A use of the real part
|
||||||
|
(float)(ci=ci);
|
||||||
|
// Not a use, bug? gcc treats this as not a use, that's probably a bug due to
|
||||||
|
// tree folding ignoring volatile.
|
||||||
|
(int)(ci=ci);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// A use.
|
||||||
|
(float)(i=i);
|
||||||
|
// A use. gcc treats this as not a use, that's probably a bug due to tree
|
||||||
|
// folding ignoring volatile.
|
||||||
|
(int)(i=i);
|
||||||
|
|
||||||
|
// A use.
|
||||||
|
-(i=j);
|
||||||
|
// A use. gcc treats this a not a use, that's probably a bug due to tree
|
||||||
|
// folding ignoring volatile.
|
||||||
|
+(i=k);
|
||||||
|
|
||||||
|
// A use. gcc treats this a not a use, that's probably a bug due to tree
|
||||||
|
// folding ignoring volatile.
|
||||||
|
__real (ci=ci);
|
||||||
|
|
||||||
|
// A use.
|
||||||
|
i + 0;
|
||||||
|
// A use.
|
||||||
|
(i=j) + i;
|
||||||
|
// A use. gcc treats this as not a use, that's probably a bug due to tree
|
||||||
|
// folding ignoring volatile.
|
||||||
|
(i=j) + 0;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
(i,j)=k;
|
||||||
|
(j=k,i)=i;
|
||||||
|
struct { int x; } s, s1;
|
||||||
|
printf("s is at %p\n", &s);
|
||||||
|
printf("s is at %p\n", &(s = s1));
|
||||||
|
printf("s.x is at %p\n", &((s = s1).x));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user