diff options
author | Nico Weber <nicolasweber@gmx.de> | 2019-06-14 04:05:17 +0000 |
---|---|---|
committer | Nico Weber <nicolasweber@gmx.de> | 2019-06-14 04:05:17 +0000 |
commit | 3d02b895eda08dda749a16c9499f3a11fd68793b (patch) | |
tree | da36d6a87461e67af138453afafe5ffafd45d02b /clang/lib/Sema | |
parent | 5b4285d82ded14b5f486df39fbef6aacdfbd8659 (diff) | |
download | bcm5719-llvm-3d02b895eda08dda749a16c9499f3a11fd68793b.tar.gz bcm5719-llvm-3d02b895eda08dda749a16c9499f3a11fd68793b.zip |
Revert 363295, it caused PR42276. Also revert follow-ups 363337, 363340.
Revert 363340 "Remove unused SK_LValueToRValue initialization step."
Revert 363337 "PR23833, DR2140: an lvalue-to-rvalue conversion on a glvalue of type"
Revert 363295 "C++ DR712 and others: handle non-odr-use resulting from an lvalue-to-rvalue conversion applied to a member access or similar not-quite-trivial lvalue expression."
llvm-svn: 363352
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 159 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 23 |
2 files changed, 51 insertions, 131 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index a561b045f9a..d444a35be86 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -635,10 +635,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) Cleanup.setExprNeedsCleanups(true); - // C++ [conv.lval]p3: - // If T is cv std::nullptr_t, the result is a null pointer constant. - CastKind CK = T->isNullPtrType() ? CK_NullToPointer : CK_LValueToRValue; - Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue); + Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, nullptr, + VK_RValue); // C11 6.3.2.1p2: // ... if the lvalue has atomic type, the value has the non-atomic version @@ -15808,32 +15806,6 @@ QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { return DeclRefType; } -namespace { -// Helper to copy the template arguments from a DeclRefExpr or MemberExpr. -// The produced TemplateArgumentListInfo* points to data stored within this -// object, so should only be used in contexts where the pointer will not be -// used after the CopiedTemplateArgs object is destroyed. -class CopiedTemplateArgs { - bool HasArgs; - TemplateArgumentListInfo TemplateArgStorage; -public: - template<typename RefExpr> - CopiedTemplateArgs(RefExpr *E) : HasArgs(E->hasExplicitTemplateArgs()) { - if (HasArgs) - E->copyTemplateArgumentsInto(TemplateArgStorage); - } - operator TemplateArgumentListInfo*() -#ifdef __has_cpp_attribute -#if __has_cpp_attribute(clang::lifetimebound) - [[clang::lifetimebound]] -#endif -#endif - { - return HasArgs ? &TemplateArgStorage : nullptr; - } -}; -} - /// Walk the set of potential results of an expression and mark them all as /// non-odr-uses if they satisfy the side-conditions of the NonOdrUseReason. /// @@ -15925,11 +15897,16 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, // Rebuild as a non-odr-use DeclRefExpr. MarkNotOdrUsed(); + TemplateArgumentListInfo TemplateArgStorage, *TemplateArgs = nullptr; + if (DRE->hasExplicitTemplateArgs()) { + DRE->copyTemplateArgumentsInto(TemplateArgStorage); + TemplateArgs = &TemplateArgStorage; + } return DeclRefExpr::Create( S.Context, DRE->getQualifierLoc(), DRE->getTemplateKeywordLoc(), DRE->getDecl(), DRE->refersToEnclosingVariableOrCapture(), DRE->getNameInfo(), DRE->getType(), DRE->getValueKind(), - DRE->getFoundDecl(), CopiedTemplateArgs(DRE), NOUR); + DRE->getFoundDecl(), TemplateArgs, NOUR); } case Expr::FunctionParmPackExprClass: { @@ -15947,107 +15924,52 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, break; } + // FIXME: Implement these. // -- If e is a subscripting operation with an array operand... - case Expr::ArraySubscriptExprClass: { - auto *ASE = cast<ArraySubscriptExpr>(E); - Expr *OldBase = ASE->getBase()->IgnoreImplicit(); - if (!OldBase->getType()->isArrayType()) - break; - ExprResult Base = Rebuild(OldBase); - if (!Base.isUsable()) - return Base; - Expr *LHS = ASE->getBase() == ASE->getLHS() ? Base.get() : ASE->getLHS(); - Expr *RHS = ASE->getBase() == ASE->getRHS() ? Base.get() : ASE->getRHS(); - SourceLocation LBracketLoc = ASE->getBeginLoc(); // FIXME: Not stored. - return S.ActOnArraySubscriptExpr(nullptr, LHS, LBracketLoc, RHS, - ASE->getRBracketLoc()); - } + // -- If e is a class member access expression [...] naming a non-static + // data member... + // -- If e is a class member access expression naming a static data member, + // ... case Expr::MemberExprClass: { auto *ME = cast<MemberExpr>(E); - // -- If e is a class member access expression [...] naming a non-static - // data member... - if (isa<FieldDecl>(ME->getMemberDecl())) { - ExprResult Base = Rebuild(ME->getBase()); - if (!Base.isUsable()) - return Base; - return MemberExpr::Create( - S.Context, Base.get(), ME->isArrow(), ME->getOperatorLoc(), - ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), - ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(), - CopiedTemplateArgs(ME), ME->getType(), ME->getValueKind(), - ME->getObjectKind(), ME->isNonOdrUse()); - } - if (ME->getMemberDecl()->isCXXInstanceMember()) + // FIXME: Recurse to the left-hand side. break; - // -- If e is a class member access expression naming a static data member, - // ... if (ME->isNonOdrUse() || IsPotentialResultOdrUsed(ME->getMemberDecl())) break; // Rebuild as a non-odr-use MemberExpr. MarkNotOdrUsed(); + TemplateArgumentListInfo TemplateArgStorage, *TemplateArgs = nullptr; + if (ME->hasExplicitTemplateArgs()) { + ME->copyTemplateArgumentsInto(TemplateArgStorage); + TemplateArgs = &TemplateArgStorage; + } return MemberExpr::Create( S.Context, ME->getBase(), ME->isArrow(), ME->getOperatorLoc(), ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), ME->getMemberDecl(), - ME->getFoundDecl(), ME->getMemberNameInfo(), CopiedTemplateArgs(ME), + ME->getFoundDecl(), ME->getMemberNameInfo(), TemplateArgs, ME->getType(), ME->getValueKind(), ME->getObjectKind(), NOUR); return ExprEmpty(); } - case Expr::BinaryOperatorClass: { - auto *BO = cast<BinaryOperator>(E); - Expr *LHS = BO->getLHS(); - Expr *RHS = BO->getRHS(); - // -- If e is a pointer-to-member expression of the form e1 .* e2 ... - if (BO->getOpcode() == BO_PtrMemD) { - ExprResult Sub = Rebuild(LHS); - if (!Sub.isUsable()) - return Sub; - LHS = Sub.get(); - // -- If e is a comma expression, ... - } else if (BO->getOpcode() == BO_Comma) { - ExprResult Sub = Rebuild(RHS); - if (!Sub.isUsable()) - return Sub; - RHS = Sub.get(); - } else { - break; - } - return S.BuildBinOp(nullptr, BO->getOperatorLoc(), BO->getOpcode(), - LHS, RHS); - } + // FIXME: Implement this. + // -- If e is a pointer-to-member expression of the form e1 .* e2 ... // -- If e has the form (e1)... case Expr::ParenExprClass: { - auto *PE = cast<ParenExpr>(E); + auto *PE = dyn_cast<ParenExpr>(E); ExprResult Sub = Rebuild(PE->getSubExpr()); if (!Sub.isUsable()) return Sub; return S.ActOnParenExpr(PE->getLParen(), PE->getRParen(), Sub.get()); } + // FIXME: Implement these. // -- If e is a glvalue conditional expression, ... - // We don't apply this to a binary conditional operator. FIXME: Should we? - case Expr::ConditionalOperatorClass: { - auto *CO = cast<ConditionalOperator>(E); - ExprResult LHS = Rebuild(CO->getLHS()); - if (LHS.isInvalid()) - return ExprError(); - ExprResult RHS = Rebuild(CO->getRHS()); - if (RHS.isInvalid()) - return ExprError(); - if (!LHS.isUsable() && !RHS.isUsable()) - return ExprEmpty(); - if (!LHS.isUsable()) - LHS = CO->getLHS(); - if (!RHS.isUsable()) - RHS = CO->getRHS(); - return S.ActOnConditionalOp(CO->getQuestionLoc(), CO->getColonLoc(), - CO->getCond(), LHS.get(), RHS.get()); - } + // -- If e is a comma expression, ... // [Clang extension] // -- If e has the form __extension__ e1... @@ -16066,7 +15988,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, // -- If e has the form _Generic(...), the set of potential results is the // union of the sets of potential results of the associated expressions. case Expr::GenericSelectionExprClass: { - auto *GSE = cast<GenericSelectionExpr>(E); + auto *GSE = dyn_cast<GenericSelectionExpr>(E); SmallVector<Expr *, 4> AssocExprs; bool AnyChanged = false; @@ -16094,7 +16016,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, // results is the union of the sets of potential results of the // second and third subexpressions. case Expr::ChooseExprClass: { - auto *CE = cast<ChooseExpr>(E); + auto *CE = dyn_cast<ChooseExpr>(E); ExprResult LHS = Rebuild(CE->getLHS()); if (LHS.isInvalid()) @@ -16117,38 +16039,13 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, // Step through non-syntactic nodes. case Expr::ConstantExprClass: { - auto *CE = cast<ConstantExpr>(E); + auto *CE = dyn_cast<ConstantExpr>(E); ExprResult Sub = Rebuild(CE->getSubExpr()); if (!Sub.isUsable()) return Sub; return ConstantExpr::Create(S.Context, Sub.get()); } - // We could mostly rely on the recursive rebuilding to rebuild implicit - // casts, but not at the top level, so rebuild them here. - case Expr::ImplicitCastExprClass: { - auto *ICE = cast<ImplicitCastExpr>(E); - // Only step through the narrow set of cast kinds we expect to encounter. - // Anything else suggests we've left the region in which potential results - // can be found. - switch (ICE->getCastKind()) { - case CK_NoOp: - case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: { - ExprResult Sub = Rebuild(ICE->getSubExpr()); - if (!Sub.isUsable()) - return Sub; - CXXCastPath Path(ICE->path()); - return S.ImpCastExprToType(Sub.get(), ICE->getType(), ICE->getCastKind(), - ICE->getValueKind(), &Path); - } - - default: - break; - } - break; - } - default: break; } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index d5ef5eddf3e..1a1d9347985 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3282,6 +3282,7 @@ void InitializationSequence::Step::Destroy() { case SK_QualificationConversionXValue: case SK_QualificationConversionLValue: case SK_AtomicConversion: + case SK_LValueToRValue: case SK_ListInitialization: case SK_UnwrapInitList: case SK_RewrapInitList: @@ -3465,6 +3466,15 @@ void InitializationSequence::AddAtomicConversionStep(QualType Ty) { Steps.push_back(S); } +void InitializationSequence::AddLValueToRValueStep(QualType Ty) { + assert(!Ty.hasQualifiers() && "rvalues may not have qualifiers"); + + Step S; + S.Kind = SK_LValueToRValue; + S.Type = Ty; + Steps.push_back(S); +} + void InitializationSequence::AddConversionSequenceStep( const ImplicitConversionSequence &ICS, QualType T, bool TopLevelOfInitList) { @@ -7495,6 +7505,7 @@ ExprResult InitializationSequence::Perform(Sema &S, case SK_QualificationConversionXValue: case SK_QualificationConversionRValue: case SK_AtomicConversion: + case SK_LValueToRValue: case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: case SK_ListInitialization: @@ -7766,6 +7777,14 @@ ExprResult InitializationSequence::Perform(Sema &S, break; } + case SK_LValueToRValue: { + assert(CurInit.get()->isGLValue() && "cannot load from a prvalue"); + CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, + CK_LValueToRValue, CurInit.get(), + /*BasePath=*/nullptr, VK_RValue); + break; + } + case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: { if (const auto *FromPtrType = @@ -8987,6 +9006,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "non-atomic-to-atomic conversion"; break; + case SK_LValueToRValue: + OS << "load (lvalue to rvalue)"; + break; + case SK_ConversionSequence: OS << "implicit conversion sequence ("; S->ICS->dump(); // FIXME: use OS |