Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -1011,66 +1011,97 @@ /// type of the same size of the lvalue's type. If the lvalue has a variable /// length type, this is not possible. /// + +/// Hacks to remove TBAA information from LValues that represent union members. +/// The TBAA in the current form does not work for union members: the aliasing +/// information emitted in such cases may be incorrect (leading to incorrect +/// optimizations). +static bool isUnionAccess(const Expr *E) { + switch (E->getStmtClass()) { + case Stmt::MemberExprClass: + return cast(E)->getBase()->getType()->isUnionType(); + case Stmt::ImplicitCastExprClass: + return isUnionAccess(cast(E)->getSubExpr()); + case Stmt::ArraySubscriptExprClass: + return isUnionAccess(cast(E)->getBase()); + default: + break; + } + return false; +} + +static LValue ClearTBAA(LValue &&LV, bool Reset) { + if (Reset) + LV.setTBAAInfo(nullptr); + return LV; +} + LValue CodeGenFunction::EmitLValue(const Expr *E) { + bool R = CGM.shouldUseTBAA() && isUnionAccess(E); ApplyDebugLocation DL(*this, E); switch (E->getStmtClass()) { - default: return EmitUnsupportedLValue(E, "l-value expression"); + default: return ClearTBAA(EmitUnsupportedLValue(E, "l-value expression"), R); case Expr::ObjCPropertyRefExprClass: llvm_unreachable("cannot emit a property reference directly"); case Expr::ObjCSelectorExprClass: - return EmitObjCSelectorLValue(cast(E)); + return ClearTBAA(EmitObjCSelectorLValue(cast(E)), R); case Expr::ObjCIsaExprClass: - return EmitObjCIsaExpr(cast(E)); + return ClearTBAA(EmitObjCIsaExpr(cast(E)), R); case Expr::BinaryOperatorClass: - return EmitBinaryOperatorLValue(cast(E)); + return ClearTBAA(EmitBinaryOperatorLValue(cast(E)), R); case Expr::CompoundAssignOperatorClass: { QualType Ty = E->getType(); if (const AtomicType *AT = Ty->getAs()) Ty = AT->getValueType(); + const auto *CA = cast(E); if (!Ty->isAnyComplexType()) - return EmitCompoundAssignmentLValue(cast(E)); - return EmitComplexCompoundAssignmentLValue(cast(E)); + return ClearTBAA(EmitCompoundAssignmentLValue(CA), R); + return ClearTBAA(EmitComplexCompoundAssignmentLValue(CA), R); } case Expr::CallExprClass: case Expr::CXXMemberCallExprClass: case Expr::CXXOperatorCallExprClass: case Expr::UserDefinedLiteralClass: - return EmitCallExprLValue(cast(E)); + return ClearTBAA(EmitCallExprLValue(cast(E)), R); case Expr::VAArgExprClass: - return EmitVAArgExprLValue(cast(E)); + return ClearTBAA(EmitVAArgExprLValue(cast(E)), R); case Expr::DeclRefExprClass: - return EmitDeclRefLValue(cast(E)); + return ClearTBAA(EmitDeclRefLValue(cast(E)), R); case Expr::ParenExprClass: - return EmitLValue(cast(E)->getSubExpr()); - case Expr::GenericSelectionExprClass: - return EmitLValue(cast(E)->getResultExpr()); + return ClearTBAA(EmitLValue(cast(E)->getSubExpr()), R); + case Expr::GenericSelectionExprClass: { + const auto *GS = cast(E); + return ClearTBAA(EmitLValue(GS->getResultExpr()), R); + } case Expr::PredefinedExprClass: - return EmitPredefinedLValue(cast(E)); + return ClearTBAA(EmitPredefinedLValue(cast(E)), R); case Expr::StringLiteralClass: - return EmitStringLiteralLValue(cast(E)); + return ClearTBAA(EmitStringLiteralLValue(cast(E)), R); case Expr::ObjCEncodeExprClass: - return EmitObjCEncodeExprLValue(cast(E)); + return ClearTBAA(EmitObjCEncodeExprLValue(cast(E)), R); case Expr::PseudoObjectExprClass: - return EmitPseudoObjectLValue(cast(E)); + return ClearTBAA(EmitPseudoObjectLValue(cast(E)), R); case Expr::InitListExprClass: - return EmitInitListLValue(cast(E)); + return ClearTBAA(EmitInitListLValue(cast(E)), R); case Expr::CXXTemporaryObjectExprClass: case Expr::CXXConstructExprClass: - return EmitCXXConstructLValue(cast(E)); - case Expr::CXXBindTemporaryExprClass: - return EmitCXXBindTemporaryLValue(cast(E)); + return ClearTBAA(EmitCXXConstructLValue(cast(E)), R); + case Expr::CXXBindTemporaryExprClass: { + const auto *BT = cast(E); + return ClearTBAA(EmitCXXBindTemporaryLValue(BT), R); + } case Expr::CXXUuidofExprClass: - return EmitCXXUuidofLValue(cast(E)); + return ClearTBAA(EmitCXXUuidofLValue(cast(E)), R); case Expr::LambdaExprClass: - return EmitLambdaLValue(cast(E)); + return ClearTBAA(EmitLambdaLValue(cast(E)), R); case Expr::ExprWithCleanupsClass: { const auto *cleanups = cast(E); enterFullExpression(cleanups); RunCleanupsScope Scope(*this); - LValue LV = EmitLValue(cleanups->getSubExpr()); + LValue LV = ClearTBAA(EmitLValue(cleanups->getSubExpr()), R); if (LV.isSimple()) { // Defend against branches out of gnu statement expressions surrounded by // cleanups. @@ -1086,42 +1117,52 @@ } case Expr::CXXDefaultArgExprClass: - return EmitLValue(cast(E)->getExpr()); + return ClearTBAA(EmitLValue(cast(E)->getExpr()), R); case Expr::CXXDefaultInitExprClass: { CXXDefaultInitExprScope Scope(*this); - return EmitLValue(cast(E)->getExpr()); + return ClearTBAA(EmitLValue(cast(E)->getExpr()), R); } case Expr::CXXTypeidExprClass: - return EmitCXXTypeidLValue(cast(E)); + return ClearTBAA(EmitCXXTypeidLValue(cast(E)), R); case Expr::ObjCMessageExprClass: - return EmitObjCMessageExprLValue(cast(E)); + return ClearTBAA(EmitObjCMessageExprLValue(cast(E)), R); case Expr::ObjCIvarRefExprClass: - return EmitObjCIvarRefLValue(cast(E)); + return ClearTBAA(EmitObjCIvarRefLValue(cast(E)), R); case Expr::StmtExprClass: - return EmitStmtExprLValue(cast(E)); + return ClearTBAA(EmitStmtExprLValue(cast(E)), R); case Expr::UnaryOperatorClass: - return EmitUnaryOpLValue(cast(E)); + return ClearTBAA(EmitUnaryOpLValue(cast(E)), R); case Expr::ArraySubscriptExprClass: - return EmitArraySubscriptExpr(cast(E)); + return ClearTBAA(EmitArraySubscriptExpr(cast(E)), R); case Expr::OMPArraySectionExprClass: - return EmitOMPArraySectionExpr(cast(E)); - case Expr::ExtVectorElementExprClass: - return EmitExtVectorElementExpr(cast(E)); + return ClearTBAA(EmitOMPArraySectionExpr(cast(E)), R); + case Expr::ExtVectorElementExprClass: { + const auto *EVE = cast(E); + return ClearTBAA(EmitExtVectorElementExpr(EVE), R); + } case Expr::MemberExprClass: - return EmitMemberExpr(cast(E)); - case Expr::CompoundLiteralExprClass: - return EmitCompoundLiteralLValue(cast(E)); - case Expr::ConditionalOperatorClass: - return EmitConditionalOperatorLValue(cast(E)); - case Expr::BinaryConditionalOperatorClass: - return EmitConditionalOperatorLValue(cast(E)); + return ClearTBAA(EmitMemberExpr(cast(E)), R); + case Expr::CompoundLiteralExprClass: { + const auto *CL = cast(E); + return ClearTBAA(EmitCompoundLiteralLValue(CL), R); + } + case Expr::ConditionalOperatorClass: { + const auto *CO = cast(E); + return ClearTBAA(EmitConditionalOperatorLValue(CO), R); + } + case Expr::BinaryConditionalOperatorClass: { + const auto *BCO = cast(E); + return ClearTBAA(EmitConditionalOperatorLValue(BCO), R); + } case Expr::ChooseExprClass: - return EmitLValue(cast(E)->getChosenSubExpr()); + return ClearTBAA(EmitLValue(cast(E)->getChosenSubExpr()), R); case Expr::OpaqueValueExprClass: - return EmitOpaqueValueLValue(cast(E)); - case Expr::SubstNonTypeTemplateParmExprClass: - return EmitLValue(cast(E)->getReplacement()); + return ClearTBAA(EmitOpaqueValueLValue(cast(E)), R); + case Expr::SubstNonTypeTemplateParmExprClass: { + const auto *STP = cast(E); + return ClearTBAA(EmitLValue(STP->getReplacement()), R); + } case Expr::ImplicitCastExprClass: case Expr::CStyleCastExprClass: case Expr::CXXFunctionalCastExprClass: @@ -1130,10 +1171,12 @@ case Expr::CXXReinterpretCastExprClass: case Expr::CXXConstCastExprClass: case Expr::ObjCBridgedCastExprClass: - return EmitCastLValue(cast(E)); + return ClearTBAA(EmitCastLValue(cast(E)), R); - case Expr::MaterializeTemporaryExprClass: - return EmitMaterializeTemporaryExpr(cast(E)); + case Expr::MaterializeTemporaryExprClass: { + const auto *MT = cast(E); + return ClearTBAA(EmitMaterializeTemporaryExpr(MT), R); + } } }