summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-12-03 01:14:32 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-12-03 01:14:32 +0000
commit4baaa5ab52870c3d2e1961aaa7758908ea69579e (patch)
treed0b7a59ca83d21a73fbd5a907b01941e9199da31 /clang/lib/Sema
parent05049bed027cb37ef4afcbc6b280603e767f7971 (diff)
downloadbcm5719-llvm-4baaa5ab52870c3d2e1961aaa7758908ea69579e.tar.gz
bcm5719-llvm-4baaa5ab52870c3d2e1961aaa7758908ea69579e.zip
DR616, and part of P0135R1: member access (or pointer-to-member access) on a
temporary produces an xvalue, not a prvalue. Support this by materializing the temporary prior to performing the member access. llvm-svn: 288563
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp6
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp11
-rw-r--r--clang/lib/Sema/SemaExprMember.cpp9
-rw-r--r--clang/lib/Sema/SemaInit.cpp30
4 files changed, 40 insertions, 16 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 667ea6cb4e3..4415100ab45 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -9810,8 +9810,8 @@ static bool IsReadonlyMessage(Expr *E, Sema &S) {
const MemberExpr *ME = dyn_cast<MemberExpr>(E);
if (!ME) return false;
if (!isa<FieldDecl>(ME->getMemberDecl())) return false;
- ObjCMessageExpr *Base =
- dyn_cast<ObjCMessageExpr>(ME->getBase()->IgnoreParenImpCasts());
+ ObjCMessageExpr *Base = dyn_cast<ObjCMessageExpr>(
+ ME->getBase()->IgnoreImplicit()->IgnoreParenImpCasts());
if (!Base) return false;
return Base->getMethodDecl() != nullptr;
}
@@ -9894,7 +9894,7 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
while (true) {
IsDereference = NextIsDereference;
- E = E->IgnoreParenImpCasts();
+ E = E->IgnoreImplicit()->IgnoreParenImpCasts();
if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
NextIsDereference = ME->isArrow();
const ValueDecl *VD = ME->getMemberDecl();
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 79b5356d79d..28ccd607507 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4984,11 +4984,14 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
!RHS.get()->getType()->isPlaceholderType() &&
"placeholders should have been weeded out by now");
- // The LHS undergoes lvalue conversions if this is ->*.
- if (isIndirect) {
+ // The LHS undergoes lvalue conversions if this is ->*, and undergoes the
+ // temporary materialization conversion otherwise.
+ if (isIndirect)
LHS = DefaultLvalueConversion(LHS.get());
- if (LHS.isInvalid()) return QualType();
- }
+ else if (LHS.get()->isRValue())
+ LHS = TemporaryMaterializationConversion(LHS.get());
+ if (LHS.isInvalid())
+ return QualType();
// The RHS always undergoes lvalue conversions.
RHS = DefaultLvalueConversion(RHS.get());
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index eddf0d69a22..806a3d813ee 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -969,6 +969,15 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
BaseType = BaseType->castAs<PointerType>()->getPointeeType();
}
R.setBaseObjectType(BaseType);
+
+ // C++1z [expr.ref]p2:
+ // For the first option (dot) the first expression shall be a glvalue [...]
+ if (!IsArrow && BaseExpr->isRValue()) {
+ ExprResult Converted = TemporaryMaterializationConversion(BaseExpr);
+ if (Converted.isInvalid())
+ return ExprError();
+ BaseExpr = Converted.get();
+ }
LambdaScopeInfo *const CurLSI = getCurLambda();
// If this is an implicit member reference and the overloaded
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index f5e38b4fbdf..3937aad012d 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5963,10 +5963,7 @@ performReferenceExtension(Expr *Init,
// Step over any subobject adjustments; we may have a materialized
// temporary inside them.
- SmallVector<const Expr *, 2> CommaLHSs;
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- Init = const_cast<Expr *>(
- Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
+ Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
// Per current approach for DR1376, look through casts to reference type
// when performing lifetime extension.
@@ -5996,10 +5993,7 @@ performReferenceExtension(Expr *Init,
static void performLifetimeExtension(Expr *Init,
const InitializedEntity *ExtendingEntity) {
// Dig out the expression which constructs the extended temporary.
- SmallVector<const Expr *, 2> CommaLHSs;
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- Init = const_cast<Expr *>(
- Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
+ Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
Init = BTE->getSubExpr();
@@ -6218,6 +6212,22 @@ Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
return MTE;
}
+ExprResult Sema::TemporaryMaterializationConversion(Expr *E) {
+ // In C++98, we don't want to implicitly create an xvalue.
+ // FIXME: This means that AST consumers need to deal with "prvalues" that
+ // denote materialized temporaries. Maybe we should add another ValueKind
+ // for "xvalue pretending to be a prvalue" for C++98 support.
+ if (!E->isRValue() || !getLangOpts().CPlusPlus11)
+ return E;
+
+ // C++1z [conv.rval]/1: T shall be a complete type.
+ QualType T = E->getType();
+ if (RequireCompleteType(E->getExprLoc(), T, diag::err_incomplete_type))
+ return ExprError();
+
+ return CreateMaterializeTemporaryExpr(E->getType(), E, false);
+}
+
ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
@@ -6316,7 +6326,9 @@ InitializationSequence::Perform(Sema &S,
if (Args.size() == 1 && Args[0]->getType()->isArrayType() &&
Entity.getType()->isPointerType() &&
InitializedEntityOutlivesFullExpression(Entity)) {
- Expr *Init = Args[0];
+ const Expr *Init = Args[0]->skipRValueSubobjectAdjustments();
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init))
+ Init = MTE->GetTemporaryExpr();
Expr::LValueClassification Kind = Init->ClassifyLValue(S.Context);
if (Kind == Expr::LV_ClassTemporary || Kind == Expr::LV_ArrayTemporary)
S.Diag(Init->getLocStart(), diag::warn_temporary_array_to_pointer_decay)
OpenPOWER on IntegriCloud