@@ -1015,15 +1015,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
10151015 : !isDependentScopeSpecifier (SS) || computeDeclContext (SS)) &&
10161016 " dependent lookup context that isn't the current instantiation?" );
10171017
1018- // C++1z [expr.ref]p2:
1019- // For the first option (dot) the first expression shall be a glvalue [...]
1020- if (!IsArrow && BaseExpr && BaseExpr->isPRValue ()) {
1021- ExprResult Converted = TemporaryMaterializationConversion (BaseExpr);
1022- if (Converted.isInvalid ())
1023- return ExprError ();
1024- BaseExpr = Converted.get ();
1025- }
1026-
10271018 const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo ();
10281019 DeclarationName MemberName = MemberNameInfo.getName ();
10291020 SourceLocation MemberLoc = MemberNameInfo.getLoc ();
@@ -1140,26 +1131,68 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
11401131 BaseExpr = BuildCXXThisExpr (Loc, BaseExprType, /* IsImplicit=*/ true );
11411132 }
11421133
1134+ // C++17 [expr.ref]p2, per CWG2813:
1135+ // For the first option (dot), if the id-expression names a static member or
1136+ // an enumerator, the first expression is a discarded-value expression; if
1137+ // the id-expression names a non-static data member, the first expression
1138+ // shall be a glvalue.
1139+ auto MakeDiscardedValue = [&BaseExpr, IsArrow, this ] {
1140+ assert (getLangOpts ().CPlusPlus &&
1141+ " Static member / member enumerator outside of C++" );
1142+ if (IsArrow)
1143+ return false ;
1144+ ExprResult Converted = IgnoredValueConversions (BaseExpr);
1145+ if (Converted.isInvalid ())
1146+ return true ;
1147+ BaseExpr = Converted.get ();
1148+ DiagnoseUnusedExprResult (BaseExpr,
1149+ diag::warn_discarded_class_member_access);
1150+ return false ;
1151+ };
1152+ auto MakeGLValue = [&BaseExpr, IsArrow, this ] {
1153+ if (IsArrow || !BaseExpr->isPRValue ())
1154+ return false ;
1155+ ExprResult Converted = TemporaryMaterializationConversion (BaseExpr);
1156+ if (Converted.isInvalid ())
1157+ return true ;
1158+ BaseExpr = Converted.get ();
1159+ return false ;
1160+ };
1161+
11431162 // Check the use of this member.
11441163 if (DiagnoseUseOfDecl (MemberDecl, MemberLoc))
11451164 return ExprError ();
11461165
1147- if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
1166+ if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
1167+ if (MakeGLValue ())
1168+ return ExprError ();
11481169 return BuildFieldReferenceExpr (BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl,
11491170 MemberNameInfo);
1171+ }
11501172
1151- if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))
1173+ if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl)) {
1174+ // Properties treated as non-static data members for the purpose of
1175+ // temporary materialization
1176+ if (MakeGLValue ())
1177+ return ExprError ();
11521178 return BuildMSPropertyRefExpr (*this , BaseExpr, IsArrow, SS, PD,
11531179 MemberNameInfo);
1180+ }
11541181
1155- if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
1182+ if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) {
1183+ if (MakeGLValue ())
1184+ return ExprError ();
11561185 // We may have found a field within an anonymous union or struct
11571186 // (C++ [class.union]).
11581187 return BuildAnonymousStructUnionMemberReference (SS, MemberLoc, FD,
11591188 FoundDecl, BaseExpr,
11601189 OpLoc);
1190+ }
11611191
1192+ // Static data member
11621193 if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
1194+ if (MakeDiscardedValue ())
1195+ return ExprError ();
11631196 return BuildMemberExpr (BaseExpr, IsArrow, OpLoc,
11641197 SS.getWithLocInContext (Context), TemplateKWLoc, Var,
11651198 FoundDecl, /* HadMultipleCandidates=*/ false ,
@@ -1174,6 +1207,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
11741207 valueKind = VK_PRValue;
11751208 type = Context.BoundMemberTy ;
11761209 } else {
1210+ // Static member function
1211+ if (MakeDiscardedValue ())
1212+ return ExprError ();
11771213 valueKind = VK_LValue;
11781214 type = MemberFn->getType ();
11791215 }
@@ -1186,13 +1222,17 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
11861222 assert (!isa<FunctionDecl>(MemberDecl) && " member function not C++ method?" );
11871223
11881224 if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
1225+ if (MakeDiscardedValue ())
1226+ return ExprError ();
11891227 return BuildMemberExpr (
11901228 BaseExpr, IsArrow, OpLoc, SS.getWithLocInContext (Context),
11911229 TemplateKWLoc, Enum, FoundDecl, /* HadMultipleCandidates=*/ false ,
11921230 MemberNameInfo, Enum->getType (), VK_PRValue, OK_Ordinary);
11931231 }
11941232
11951233 if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
1234+ if (MakeDiscardedValue ())
1235+ return ExprError ();
11961236 if (!TemplateArgs) {
11971237 diagnoseMissingTemplateArguments (
11981238 SS, /* TemplateKeyword=*/ TemplateKWLoc.isValid (), VarTempl, MemberLoc);
0 commit comments