Calculate the value kind of an expression when it's created and
store it on the expression node.  Also store an "object kind",
which distinguishes ordinary "addressed" l-values (like
variable references and pointer dereferences) and bitfield,
@property, and vector-component l-values.

Currently we're not using these for much, but I aim to switch
pretty much everything calculating l-valueness over to them.
For now they shouldn't necessarily be trusted.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119685 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index e57e89e..06c2758 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -44,17 +44,21 @@
 
 
 static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                           ExprValueKind &VK,
                            const SourceRange &OpRange,
                            const SourceRange &DestRange);
 static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                                 ExprValueKind &VK,
                                  const SourceRange &OpRange,
                                  const SourceRange &DestRange,
                                  CastKind &Kind);
 static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                            ExprValueKind &VK,
                             const SourceRange &OpRange,
                             CastKind &Kind,
                             CXXCastPath &BasePath);
 static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+                             ExprValueKind &VK,
                              const SourceRange &OpRange,
                              const SourceRange &DestRange,
                              CastKind &Kind,
@@ -156,44 +160,46 @@
     Diag(Ex->getLocStart(), diag::err_invalid_use_of_bound_member_func)
       << Ex->getSourceRange();
 
+  ExprValueKind VK = VK_RValue;
   switch (Kind) {
   default: llvm_unreachable("Unknown C++ cast!");
 
   case tok::kw_const_cast:
     if (!TypeDependent)
-      CheckConstCast(*this, Ex, DestType, OpRange, DestRange);
+      CheckConstCast(*this, Ex, DestType, VK, OpRange, DestRange);
     return Owned(CXXConstCastExpr::Create(Context,
                                         DestType.getNonLValueExprType(Context),
-                                          Ex, DestTInfo, OpLoc));
+                                          VK, Ex, DestTInfo, OpLoc));
 
   case tok::kw_dynamic_cast: {
     CastKind Kind = CK_Dependent;
     CXXCastPath BasePath;
     if (!TypeDependent)
-      CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind, BasePath);
+      CheckDynamicCast(*this, Ex, DestType, VK, OpRange, DestRange,
+                       Kind, BasePath);
     return Owned(CXXDynamicCastExpr::Create(Context,
                                           DestType.getNonLValueExprType(Context),
-                                            Kind, Ex, &BasePath, DestTInfo,
+                                            VK, Kind, Ex, &BasePath, DestTInfo,
                                             OpLoc));
   }
   case tok::kw_reinterpret_cast: {
     CastKind Kind = CK_Dependent;
     if (!TypeDependent)
-      CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind);
+      CheckReinterpretCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind);
     return Owned(CXXReinterpretCastExpr::Create(Context,
                                   DestType.getNonLValueExprType(Context),
-                                  Kind, Ex, 0,
+                                  VK, Kind, Ex, 0,
                                   DestTInfo, OpLoc));
   }
   case tok::kw_static_cast: {
     CastKind Kind = CK_Dependent;
     CXXCastPath BasePath;
     if (!TypeDependent)
-      CheckStaticCast(*this, Ex, DestType, OpRange, Kind, BasePath);
+      CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath);
     
     return Owned(CXXStaticCastExpr::Create(Context,
                                          DestType.getNonLValueExprType(Context),
-                                           Kind, Ex, &BasePath,
+                                           VK, Kind, Ex, &BasePath,
                                            DestTInfo, OpLoc));
   }
   }
@@ -315,7 +321,7 @@
 /// checked downcasts in class hierarchies.
 static void
 CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
-                 const SourceRange &OpRange,
+                 ExprValueKind &VK, const SourceRange &OpRange,
                  const SourceRange &DestRange, CastKind &Kind,
                  CXXCastPath &BasePath) {
   QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType();
@@ -326,11 +332,12 @@
 
   QualType DestPointee;
   const PointerType *DestPointer = DestType->getAs<PointerType>();
-  const ReferenceType *DestReference = DestType->getAs<ReferenceType>();
+  const ReferenceType *DestReference = 0;
   if (DestPointer) {
     DestPointee = DestPointer->getPointeeType();
-  } else if (DestReference) {
+  } else if ((DestReference = DestType->getAs<ReferenceType>())) {
     DestPointee = DestReference->getPointeeType();
+    VK = isa<LValueReferenceType>(DestReference) ? VK_LValue : VK_RValue;
   } else {
     Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
       << OrigDestType << DestRange;
@@ -447,9 +454,10 @@
 /// const char *str = "literal";
 /// legacy_function(const_cast\<char*\>(str));
 void
-CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, ExprValueKind &VK,
                const SourceRange &OpRange, const SourceRange &DestRange) {
-  if (!DestType->isLValueReferenceType())
+  VK = Expr::getValueKindForType(DestType);
+  if (VK == VK_RValue)
     Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
@@ -466,9 +474,10 @@
 /// char *bytes = reinterpret_cast\<char*\>(int_ptr);
 void
 CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
-                     const SourceRange &OpRange, const SourceRange &DestRange,
-                     CastKind &Kind) {
-  if (!DestType->isLValueReferenceType())
+                     ExprValueKind &VK, const SourceRange &OpRange,
+                     const SourceRange &DestRange, CastKind &Kind) {
+  VK = Expr::getValueKindForType(DestType);
+  if (VK == VK_RValue)
     Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
@@ -498,8 +507,8 @@
 /// implicit conversions explicit and getting rid of data loss warnings.
 void
 CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
-                const SourceRange &OpRange, CastKind &Kind,
-                CXXCastPath &BasePath) {
+                ExprValueKind &VK, const SourceRange &OpRange,
+                CastKind &Kind, CXXCastPath &BasePath) {
   // This test is outside everything else because it's the only case where
   // a non-lvalue-reference target type does not lead to decay.
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
@@ -508,7 +517,8 @@
     return;
   }
 
-  if (!DestType->isLValueReferenceType() && !DestType->isRecordType())
+  VK = Expr::getValueKindForType(DestType);
+  if (VK == VK_RValue && !DestType->isRecordType())
     Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
@@ -1345,8 +1355,8 @@
 }
 
 bool 
-Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
-                         CastKind &Kind, 
+Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
+                         Expr *&CastExpr, CastKind &Kind, 
                          CXXCastPath &BasePath,
                          bool FunctionalStyle) {
   if (CastExpr->isBoundMemberFunction(Context))
@@ -1368,7 +1378,8 @@
     return false;
   }
 
-  if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
+  VK = Expr::getValueKindForType(CastTy);
+  if (VK == VK_RValue && !CastTy->isRecordType())
     DefaultFunctionArrayLvalueConversion(CastExpr);
 
   // C++ [expr.cast]p5: The conversions performed by
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index d04addd..ed45de5 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -487,8 +487,9 @@
     // GCC does an implicit conversion to the pointer or integer ValType.  This
     // can fail in some cases (1i -> int**), check for this error case now.
     CastKind Kind = CK_Invalid;
+    ExprValueKind VK = VK_RValue;
     CXXCastPath BasePath;
-    if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, BasePath))
+    if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, VK, BasePath))
       return ExprError();
 
     // Okay, we have something that *can* be converted to the right type.  Check
@@ -497,7 +498,7 @@
     // pass in 42.  The 42 gets converted to char.  This is even more strange
     // for things like 45.123 -> char, etc.
     // FIXME: Do this check.
-    ImpCastExprToType(Arg, ValType, Kind, VK_RValue, &BasePath);
+    ImpCastExprToType(Arg, ValType, Kind, VK, &BasePath);
     TheCall->setArg(i+1, Arg);
   }
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index f7638f8..77f604a 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1515,7 +1515,8 @@
     
     Expr *CopyCtorArg = 
       DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param, 
-                          Constructor->getLocation(), ParamType, 0);
+                          Constructor->getLocation(), ParamType,
+                          VK_LValue, 0);
     
     // Cast to the base class to avoid ambiguities.
     QualType ArgTy = 
@@ -1577,7 +1578,7 @@
     
     Expr *MemberExprBase = 
       DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param, 
-                          Loc, ParamType, 0);
+                          Loc, ParamType, VK_LValue, 0);
 
     // Build a reference to this field within the parameter.
     CXXScopeSpec SS;
@@ -1622,7 +1623,7 @@
       
       // Create a reference to the iteration variable.
       ExprResult IterationVarRef
-        = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, Loc);
+        = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc);
       assert(!IterationVarRef.isInvalid() &&
              "Reference to invented variable cannot fail!");
       
@@ -4635,7 +4636,7 @@
   // Create a reference to the iteration variable; we'll use this several
   // times throughout.
   Expr *IterationVarRef
-    = S.BuildDeclRefExpr(IterationVar, SizeType, Loc).takeAs<Expr>();
+    = S.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc).take();
   assert(IterationVarRef && "Reference to invented variable cannot fail!");
   
   // Create the DeclStmt that holds the iteration variable.
@@ -4646,15 +4647,14 @@
   Upper.zextOrTrunc(S.Context.getTypeSize(SizeType));
   Expr *Comparison
     = new (S.Context) BinaryOperator(IterationVarRef,
-                           IntegerLiteral::Create(S.Context,
-                                                  Upper, SizeType, Loc),
-                                                  BO_NE, S.Context.BoolTy, Loc);
+                     IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
+                                     BO_NE, S.Context.BoolTy,
+                                     VK_RValue, OK_Ordinary, Loc);
   
   // Create the pre-increment of the iteration variable.
   Expr *Increment
-    = new (S.Context) UnaryOperator(IterationVarRef,
-                                    UO_PreInc,
-                                    SizeType, Loc);
+    = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType,
+                                    VK_LValue, OK_Ordinary, Loc);
   
   // Subscript the "from" and "to" expressions with the iteration variable.
   From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc,
@@ -4663,10 +4663,9 @@
                                                        IterationVarRef, Loc));
   
   // Build the copy for an individual element of the array.
-  StmtResult Copy = BuildSingleCopyAssign(S, Loc, 
-                                                ArrayTy->getElementType(),
-                                                To, From, 
-                                                CopyingBaseSubobject, Depth+1);
+  StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(),
+                                          To, From, CopyingBaseSubobject,
+                                          Depth + 1);
   if (Copy.isInvalid())
     return StmtError();
   
@@ -4907,7 +4906,7 @@
   
   // Construct a reference to the "other" object. We'll be using this 
   // throughout the generated ASTs.
-  Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, Loc).takeAs<Expr>();
+  Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_RValue, Loc).take();
   assert(OtherRef && "Reference to parameter cannot fail!");
   
   // Construct the "this" pointer. We'll be using this throughout the generated
@@ -5068,7 +5067,7 @@
         
           CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, 
                                                   CollectableMemCpy->getType(),
-                                                  Loc, 0).takeAs<Expr>();
+                                                  VK_LValue, Loc, 0).take();
           assert(CollectableMemCpyRef && "Builtin reference cannot fail");
         }
       }
@@ -5088,7 +5087,7 @@
 
         BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, 
                                             BuiltinMemCpy->getType(),
-                                            Loc, 0).takeAs<Expr>();
+                                            VK_LValue, Loc, 0).take();
         assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
       }
           
@@ -6105,7 +6104,7 @@
       // it can be destroyed later.
       InitializedEntity Entity = InitializedEntity::InitializeVariable(ExDecl);
       Expr *ExDeclRef = DeclRefExpr::Create(Context, 0, SourceRange(), ExDecl, 
-                                            Loc, ExDeclType, 0);
+                                            Loc, ExDeclType, VK_LValue, 0);
       InitializationKind Kind = InitializationKind::CreateCopy(Loc, 
                                                                SourceLocation());
       InitializationSequence InitSeq(*this, Entity, Kind, &ExDeclRef, 1);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 2cb92b6..25c27fe 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -743,15 +743,16 @@
 
 
 ExprResult
-Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
-                       const CXXScopeSpec *SS) {
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+                       SourceLocation Loc, const CXXScopeSpec *SS) {
   DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
-  return BuildDeclRefExpr(D, Ty, NameInfo, SS);
+  return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS);
 }
 
 /// BuildDeclRefExpr - Build a DeclRefExpr.
 ExprResult
 Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+                       ExprValueKind VK,
                        const DeclarationNameInfo &NameInfo,
                        const CXXScopeSpec *SS) {
   if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) {
@@ -785,7 +786,7 @@
   return Owned(DeclRefExpr::Create(Context,
                               SS? (NestedNameSpecifier *)SS->getScopeRep() : 0,
                                    SS? SS->getRange() : SourceRange(),
-                                   D, NameInfo, Ty));
+                                   D, NameInfo, Ty, VK));
 }
 
 /// \brief Given a field that represents a member of an anonymous
@@ -845,8 +846,9 @@
     // BaseObject is an anonymous struct/union variable (and is,
     // therefore, not part of another non-anonymous record).
     MarkDeclarationReferenced(Loc, BaseObject);
-    BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(),
-                                               Loc);
+    BaseObjectExpr =
+      new (Context) DeclRefExpr(BaseObject, BaseObject->getType(),
+                                VK_LValue, Loc);
     BaseQuals
       = Context.getCanonicalType(BaseObject->getType()).getQualifiers();
   } else if (BaseObjectExpr) {
@@ -899,13 +901,14 @@
   for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
          FI = AnonFields.rbegin(), FIEnd = AnonFields.rend();
        FI != FIEnd; ++FI) {
-    QualType MemberType = (*FI)->getType();
+    FieldDecl *Field = *FI;
+    QualType MemberType = Field->getType();
     Qualifiers MemberTypeQuals =
       Context.getCanonicalType(MemberType).getQualifiers();
 
     // CVR attributes from the base are picked up by members,
     // except that 'mutable' members don't pick up 'const'.
-    if ((*FI)->isMutable())
+    if (Field->isMutable())
       ResultQuals.removeConst();
 
     // GC attributes are never picked up by members.
@@ -922,7 +925,9 @@
     PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI, *FI);
     // FIXME: Might this end up being a qualified name?
     Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
-                                      OpLoc, MemberType);
+                                      OpLoc, MemberType, VK_LValue,
+                                      Field->isBitField() ?
+                                        OK_BitField : OK_Ordinary);
     BaseObjectIsPointer = false;
     ResultQuals = NewQuals;
   }
@@ -1526,7 +1531,8 @@
       if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>())
         NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType(),
                                                      Proto->getExtInfo());
-      return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS);
+      // Note that functions are r-values in C.
+      return BuildDeclRefExpr(Func, NoProtoType, VK_RValue, NameLoc, &SS);
     }
   }
 
@@ -1916,6 +1922,7 @@
                                    DeclAccessPair FoundDecl,
                                    const DeclarationNameInfo &MemberNameInfo,
                                    QualType Ty,
+                                   ExprValueKind VK, ExprObjectKind OK,
                           const TemplateArgumentListInfo *TemplateArgs = 0) {
   NestedNameSpecifier *Qualifier = 0;
   SourceRange QualifierRange;
@@ -1926,7 +1933,7 @@
 
   return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
                             Member, FoundDecl, MemberNameInfo,
-                            TemplateArgs, Ty);
+                            TemplateArgs, Ty, VK, OK);
 }
 
 /// Builds an implicit member access expression.  The current context
@@ -2083,6 +2090,18 @@
   return Owned(ULE);
 }
 
+static ExprValueKind getValueKindForDecl(ASTContext &Context,
+                                         const ValueDecl *D) {
+  if (isa<VarDecl>(D) || isa<FieldDecl>(D)) return VK_LValue;
+  if (!Context.getLangOptions().CPlusPlus) return VK_RValue;
+  if (isa<FunctionDecl>(D)) {
+    if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
+      return VK_RValue;
+    return VK_LValue;
+  }
+  return Expr::getValueKindForType(D->getType());
+}
+
 
 /// \brief Complete semantic analysis for a reference to the given declaration.
 ExprResult
@@ -2126,6 +2145,8 @@
   if (VD->isInvalidDecl())
     return ExprError();
 
+  ExprValueKind VK = getValueKindForDecl(Context, VD);
+
   // If the identifier reference is inside a block, and it refers to a value
   // that is outside the block, create a BlockDeclRefExpr instead of a
   // DeclRefExpr.  This ensures the value is treated as a copy-in snapshot when
@@ -2150,6 +2171,7 @@
 
     MarkDeclarationReferenced(Loc, VD);
     QualType ExprTy = VD->getType().getNonReferenceType();
+
     // The BlocksAttr indicates the variable is bound by-reference.
     bool byrefVar = (VD->getAttr<BlocksAttr>() != 0);
     QualType T = VD->getType();
@@ -2160,17 +2182,17 @@
       bool constAdded = !ExprTy.isConstQualified();
       // Variable will be bound by-copy, make it const within the closure.
       ExprTy.addConst();
-      BDRE = new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false,
-                                            constAdded);
+      BDRE = new (Context) BlockDeclRefExpr(VD, ExprTy, VK,
+                                            Loc, false, constAdded);
     }
     else
-      BDRE = new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, true);
+      BDRE = new (Context) BlockDeclRefExpr(VD, ExprTy, VK, Loc, true);
     
     if (getLangOptions().CPlusPlus) {
       if (!T->isDependentType() && !T->isReferenceType()) {
         Expr *E = new (Context) 
                     DeclRefExpr(const_cast<ValueDecl*>(BDRE->getDecl()), T,
-                                          SourceLocation());
+                                VK, SourceLocation());
         if (T->getAs<RecordType>())
           if (!T->isUnionType()) {
             ExprResult Res = PerformCopyInitialization(
@@ -2191,7 +2213,7 @@
   // If this reference is not in a block or if the referenced variable is
   // within the block, create a normal DeclRefExpr.
 
-  return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
+  return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), VK,
                           NameInfo, &SS);
 }
 
@@ -2624,7 +2646,9 @@
   if (getLangOptions().CPlusPlus &&
       (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {
     return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
-                                                  Context.DependentTy, RLoc));
+                                                  Context.DependentTy,
+                                                  VK_LValue, OK_Ordinary,
+                                                  RLoc));
   }
 
   if (getLangOptions().CPlusPlus &&
@@ -2651,6 +2675,8 @@
   DefaultFunctionArrayLvalueConversion(RHSExp);
 
   QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
+  ExprValueKind VK = VK_LValue;
+  ExprObjectKind OK = OK_Ordinary;
 
   // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
   // to the expression *((e1)+(e2)). This means the array "Base" may actually be
@@ -2685,6 +2711,9 @@
   } else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) {
     BaseExpr = LHSExp;    // vectors: V[123]
     IndexExpr = RHSExp;
+    VK = LHSExp->getValueKind();
+    if (VK != VK_RValue)
+      OK = OK_VectorComponent;
 
     // FIXME: need to deal with const...
     ResultType = VTy->getElementType();
@@ -2756,7 +2785,7 @@
   }
 
   return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
-                                                ResultType, RLoc));
+                                                ResultType, VK, OK, RLoc));
 }
 
 QualType Sema::
@@ -3240,11 +3269,17 @@
       return BuildAnonymousStructUnionMemberReference(MemberLoc, FD,
                                                       BaseExpr, OpLoc);
 
+    // x.a is an l-value if 'a' has a reference type. Otherwise:
+    // x.a is an l-value/x-value/pr-value if the base is (and note
+    //   that *x is always an l-value).
+    ExprValueKind VK = IsArrow ? VK_LValue : BaseExpr->getValueKind();
+
     // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
     QualType MemberType = FD->getType();
-    if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
+    if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
       MemberType = Ref->getPointeeType();
-    else {
+      VK = VK_LValue;
+    } else {
       Qualifiers BaseQuals = BaseType.getQualifiers();
       BaseQuals.removeObjCGCAttr();
       if (FD->isMutable()) BaseQuals.removeConst();
@@ -3262,28 +3297,34 @@
       return ExprError();
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
                                  FD, FoundDecl, MemberNameInfo,
-                                 MemberType));
+                                 MemberType, VK,
+                                 FD->isBitField() ? OK_BitField : OK_Ordinary));
   }
 
   if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
     MarkDeclarationReferenced(MemberLoc, Var);
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
                                  Var, FoundDecl, MemberNameInfo,
-                                 Var->getType().getNonReferenceType()));
+                                 Var->getType().getNonReferenceType(),
+                                 Expr::getValueKindForType(Var->getType()),
+                                 OK_Ordinary));
   }
 
-  if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
+  if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
     MarkDeclarationReferenced(MemberLoc, MemberDecl);
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
                                  MemberFn, FoundDecl, MemberNameInfo,
-                                 MemberFn->getType()));
+                                 MemberFn->getType(),
+                                 MemberFn->isInstance() ? VK_RValue : VK_LValue,
+                                 OK_Ordinary));
   }
+  assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
 
   if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
     MarkDeclarationReferenced(MemberLoc, MemberDecl);
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
                                  Enum, FoundDecl, MemberNameInfo,
-                                 Enum->getType()));
+                                 Enum->getType(), VK_RValue, OK_Ordinary));
   }
 
   Owned(BaseExpr);
@@ -3435,7 +3476,8 @@
           PType = (*(Setter->param_end() -1))->getType();
         // FIXME: we must check that the setter has property type.
         return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter,
-                                                  PType,
+                                                  PType, VK_LValue,
+                                                  OK_ObjCProperty,
                                                   Setter, MemberLoc, BaseExpr));
       }
       return ExprError(Diag(MemberLoc, diag::err_property_not_found)
@@ -3599,6 +3641,7 @@
           return ExprError();
 
         return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+                                                       VK_LValue, OK_ObjCProperty,
                                                        MemberLoc, 
                                                        BaseExpr));
       }
@@ -3615,6 +3658,8 @@
           SMD = dyn_cast<ObjCMethodDecl>(SDecl);
         QualType PType = OMD->getSendResultType();
         return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(OMD, PType,
+                                                                   VK_LValue,
+                                                              OK_ObjCProperty,
                                                                    SMD, 
                                                                    MemberLoc, 
                                                                    BaseExpr));
@@ -3647,7 +3692,9 @@
     QualType ret = CheckExtVectorComponent(BaseType, OpLoc, Member, MemberLoc);
     if (ret.isNull())
       return ExprError();
-    return Owned(new (Context) ExtVectorElementExpr(ret, BaseExpr, *Member,
+    return Owned(new (Context) ExtVectorElementExpr(ret,
+                                                    BaseExpr->getValueKind(),
+                                                    BaseExpr, *Member,
                                                     MemberLoc));
   }
 
@@ -3959,7 +4006,7 @@
       }
 
       return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy,
-                                          RParenLoc));
+                                          VK_RValue, RParenLoc));
     }
 
     // Determine whether this is a dependent call inside a C++ template,
@@ -3974,7 +4021,8 @@
 
     if (Dependent)
       return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs,
-                                          Context.DependentTy, RParenLoc));
+                                          Context.DependentTy, VK_RValue,
+                                          RParenLoc));
 
     // Determine whether this is a call to an object (C++ [over.call.object]).
     if (Fn->getType()->isRecordType())
@@ -4014,10 +4062,11 @@
         if (const FunctionProtoType *FPT
                                 = BO->getType()->getAs<FunctionProtoType>()) {
           QualType ResultTy = FPT->getCallResultType(Context);
+          ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType());
 
           CXXMemberCallExpr *TheCall
             = new (Context) CXXMemberCallExpr(Context, BO, Args,
-                                              NumArgs, ResultTy,
+                                              NumArgs, ResultTy, VK,
                                               RParenLoc);
 
           if (CheckCallReturnType(FPT->getResultType(),
@@ -4081,6 +4130,7 @@
   CallExpr *TheCall = new (Context) CallExpr(Context, Fn,
                                              Args, NumArgs,
                                              Context.BoolTy,
+                                             VK_RValue,
                                              RParenLoc);
 
   const FunctionType *FuncT;
@@ -4108,6 +4158,7 @@
 
   // We know the result type of the call, set it.
   TheCall->setType(FuncT->getCallResultType(Context));
+  TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType()));
 
   if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) {
     if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs,
@@ -4243,8 +4294,11 @@
       return ExprError();
   }
 
+  // In C, compound literals are l-values for some reason.
+  ExprValueKind VK = getLangOptions().CPlusPlus ? VK_RValue : VK_LValue;
+
   return Owned(new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
-                                                 literalExpr, isFileScope));
+                                                 VK, literalExpr, isFileScope));
 }
 
 ExprResult
@@ -4388,16 +4442,18 @@
 }
 
 /// CheckCastTypes - Check type constraints for casting between types.
-bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
-                          CastKind& Kind,
-                          CXXCastPath &BasePath,
-                          bool FunctionalStyle) {
+bool Sema::CheckCastTypes(SourceRange TyR, QualType castType,
+                          Expr *&castExpr, CastKind& Kind, ExprValueKind &VK,
+                          CXXCastPath &BasePath, bool FunctionalStyle) {
   if (getLangOptions().CPlusPlus)
     return CXXCheckCStyleCast(SourceRange(TyR.getBegin(),
                                           castExpr->getLocEnd()), 
-                              castType, castExpr, Kind, BasePath,
+                              castType, VK, castExpr, Kind, BasePath,
                               FunctionalStyle);
 
+  // We only support r-value casts in C.
+  VK = VK_RValue;
+
   DefaultFunctionArrayLvalueConversion(castExpr);
 
   // C99 6.5.4p2: the cast type needs to be void or scalar and the expression
@@ -4574,14 +4630,15 @@
 Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
                           SourceLocation RParenLoc, Expr *castExpr) {
   CastKind Kind = CK_Invalid;
+  ExprValueKind VK = VK_RValue;
   CXXCastPath BasePath;
   if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
-                     Kind, BasePath))
+                     Kind, VK, BasePath))
     return ExprError();
 
   return Owned(CStyleCastExpr::Create(Context,
                                     Ty->getType().getNonLValueExprType(Context),
-                                      Kind, castExpr, &BasePath, Ty,
+                                      VK, Kind, castExpr, &BasePath, Ty,
                                       LParenLoc, RParenLoc));
 }
 
@@ -4669,7 +4726,7 @@
 /// In that case, lhs = cond.
 /// C99 6.5.15
 QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
-                                        Expr *&SAVE,
+                                        Expr *&SAVE, ExprValueKind &VK,
                                         SourceLocation QuestionLoc) {
   // If both LHS and RHS are overloaded functions, try to resolve them.
   if (Context.hasSameType(LHS->getType(), RHS->getType()) && 
@@ -4688,7 +4745,9 @@
 
   // C++ is sufficiently different to merit its own checker.
   if (getLangOptions().CPlusPlus)
-    return CXXCheckConditionalOperands(Cond, LHS, RHS, SAVE, QuestionLoc);
+    return CXXCheckConditionalOperands(Cond, LHS, RHS, SAVE, VK, QuestionLoc);
+
+  VK = VK_RValue;
 
   UsualUnaryConversions(Cond);
   if (SAVE) {
@@ -5053,15 +5112,16 @@
     LHSExpr = SAVEExpr = CondExpr;
   }
 
+  ExprValueKind VK = VK_RValue;
   QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr, 
-                                             SAVEExpr, QuestionLoc);
+                                             SAVEExpr, VK, QuestionLoc);
   if (result.isNull())
     return ExprError();
 
   return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc,
                                                  LHSExpr, ColonLoc, 
                                                  RHSExpr, SAVEExpr,
-                                                 result));
+                                                 result, VK));
 }
 
 // CheckPointerTypesForAssignment - This is a very tricky routine (despite
@@ -5499,7 +5559,7 @@
   // union type from this initializer list.
   TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
   E = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
-                                  Initializer, false);
+                                  VK_RValue, Initializer, false);
 }
 
 Sema::AssignConvertType
@@ -6649,6 +6709,12 @@
           LHSType->isObjCObjectPointerType())))
       ConvTy = Compatible;
 
+    if (ConvTy == Compatible &&
+        getLangOptions().ObjCNonFragileABI &&
+        LHSType->isObjCObjectType())
+      Diag(Loc, diag::err_assignment_requires_nonfragile_object)
+        << LHSType;
+
     // If the RHS is a unary plus or minus, check to see if they = and + are
     // right next to each other.  If so, the user may have typo'd "x =+ 4"
     // instead of "x += 4".
@@ -7148,14 +7214,20 @@
   // The following two variables are used for compound assignment operators
   QualType CompLHSTy;    // Type of LHS after promotions for computation
   QualType CompResultTy; // Type of computation result
+  ExprValueKind VK = VK_RValue;
+  ExprObjectKind OK = OK_Ordinary;
 
   switch (Opc) {
   case BO_Assign:
     ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType());
+    if (getLangOptions().CPlusPlus) {
+      VK = rhs->getValueKind();
+      OK = rhs->getObjectKind();
+    }
     break;
   case BO_PtrMemD:
   case BO_PtrMemI:
-    ResultTy = CheckPointerToMemberOperands(lhs, rhs, OpLoc,
+    ResultTy = CheckPointerToMemberOperands(lhs, rhs, VK, OpLoc,
                                             Opc == BO_PtrMemI);
     break;
   case BO_Mul:
@@ -7198,7 +7270,7 @@
   case BO_MulAssign:
   case BO_DivAssign:
     CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true,
-                                              Opc == BO_DivAssign);
+                                               Opc == BO_DivAssign);
     CompLHSTy = CompResultTy;
     if (!CompResultTy.isNull())
       ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
@@ -7236,21 +7308,25 @@
     break;
   case BO_Comma:
     ResultTy = CheckCommaOperands(lhs, rhs, OpLoc);
+    if (getLangOptions().CPlusPlus) {
+      VK = rhs->getValueKind();
+      OK = rhs->getObjectKind();
+    }
     break;
   }
   if (ResultTy.isNull())
     return ExprError();
-  if (ResultTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
-    if (Opc >= BO_Assign && Opc <= BO_OrAssign) 
-          Diag(OpLoc, diag::err_assignment_requires_nonfragile_object)
-                << ResultTy;
-  }
   if (CompResultTy.isNull())
-    return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy, OpLoc));
-  else
-    return Owned(new (Context) CompoundAssignOperator(lhs, rhs, Opc, ResultTy,
-                                                      CompLHSTy, CompResultTy,
-                                                      OpLoc));
+    return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy,
+                                              VK, OK, OpLoc));
+
+  if (getLangOptions().CPlusPlus) {
+    VK = VK_LValue;
+    OK = lhs->getObjectKind();
+  }
+  return Owned(new (Context) CompoundAssignOperator(lhs, rhs, Opc, ResultTy,
+                                                    VK, OK, CompLHSTy,
+                                                    CompResultTy, OpLoc));
 }
 
 /// SuggestParentheses - Emit a diagnostic together with a fixit hint that wraps
@@ -7470,10 +7546,15 @@
                                       Expr *Input) {
   UnaryOperatorKind Opc = static_cast<UnaryOperatorKind>(OpcIn);
 
+  ExprValueKind VK = VK_RValue;
+  ExprObjectKind OK = OK_Ordinary;
   QualType resultType;
   switch (Opc) {
   case UO_PreInc:
   case UO_PreDec:
+    VK = VK_LValue;
+    OK = Input->getObjectKind();
+    // fallthrough
   case UO_PostInc:
   case UO_PostDec:
     resultType = CheckIncrementDecrementOperand(Input, OpLoc,
@@ -7488,6 +7569,7 @@
   case UO_Deref:
     DefaultFunctionArrayLvalueConversion(Input);
     resultType = CheckIndirectionOperand(Input, OpLoc);
+    VK = VK_LValue;
     break;
   case UO_Plus:
   case UO_Minus:
@@ -7558,15 +7640,22 @@
   case UO_Real:
   case UO_Imag:
     resultType = CheckRealImagOperand(Input, OpLoc, Opc == UO_Real);
+    // _Real and _Imag map ordinary l-values into ordinary l-values.
+    if (Input->getValueKind() != VK_RValue &&
+        Input->getObjectKind() == OK_Ordinary)
+      VK = Input->getValueKind();
     break;
   case UO_Extension:
     resultType = Input->getType();
+    VK = Input->getValueKind();
+    OK = Input->getObjectKind();
     break;
   }
   if (resultType.isNull())
     return ExprError();
 
-  return Owned(new (Context) UnaryOperator(Input, Opc, resultType, OpLoc));
+  return Owned(new (Context) UnaryOperator(Input, Opc, resultType,
+                                           VK, OK, OpLoc));
 }
 
 ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
@@ -7884,6 +7973,8 @@
                                  SourceLocation RPLoc) {
   assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
 
+  ExprValueKind VK = VK_RValue;
+  ExprObjectKind OK = OK_Ordinary;
   QualType resType;
   bool ValueDependent = false;
   if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) {
@@ -7899,13 +7990,16 @@
         << CondExpr->getSourceRange());
 
     // If the condition is > zero, then the AST type is the same as the LSHExpr.
-    resType = condEval.getZExtValue() ? LHSExpr->getType() : RHSExpr->getType();
-    ValueDependent = condEval.getZExtValue() ? LHSExpr->isValueDependent()
-                                             : RHSExpr->isValueDependent();
+    Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr;
+
+    resType = ActiveExpr->getType();
+    ValueDependent = ActiveExpr->isValueDependent();
+    VK = ActiveExpr->getValueKind();
+    OK = ActiveExpr->getObjectKind();
   }
 
   return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
-                                        resType, RPLoc,
+                                        resType, VK, OK, RPLoc,
                                         resType->isDependentType(),
                                         ValueDependent));
 }
@@ -8154,8 +8248,8 @@
 }
 
 ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
-                                            Expr *E, TypeSourceInfo *TInfo,
-                                            SourceLocation RPLoc) {
+                                Expr *E, TypeSourceInfo *TInfo,
+                                SourceLocation RPLoc) {
   Expr *OrigExpr = E;
 
   // Get the va_list type
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 70e9a97..fbd36fd 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -605,9 +605,10 @@
   //
   if (NumExprs == 1) {
     CastKind Kind = CK_Invalid;
+    ExprValueKind VK = VK_RValue;
     CXXCastPath BasePath;
     if (CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0], 
-                       Kind, BasePath,
+                       Kind, VK, BasePath,
                        /*FunctionalStyle=*/true))
       return ExprError();
 
@@ -615,7 +616,7 @@
 
     return Owned(CXXFunctionalCastExpr::Create(Context,
                                                Ty.getNonLValueExprType(Context),
-                                               TInfo, TyBeginLoc, Kind,
+                                               VK, TInfo, TyBeginLoc, Kind,
                                                Exprs[0], &BasePath,
                                                RParenLoc));
   }
@@ -1582,8 +1583,8 @@
 /// \brief Check the use of the given variable as a C++ condition in an if,
 /// while, do-while, or switch statement.
 ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
-                                                      SourceLocation StmtLoc,
-                                                      bool ConvertToBoolean) {
+                                        SourceLocation StmtLoc,
+                                        bool ConvertToBoolean) {
   QualType T = ConditionVar->getType();
   
   // C++ [stmt.select]p2:
@@ -1599,7 +1600,8 @@
 
   Expr *Condition = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
                                         ConditionVar->getLocation(), 
-                                 ConditionVar->getType().getNonReferenceType());
+                            ConditionVar->getType().getNonReferenceType(),
+                            Expr::getValueKindForType(ConditionVar->getType()));
   if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc))
     return ExprError();
   
@@ -2331,8 +2333,10 @@
                                                 RParen, Context.BoolTy));
 }
 
-QualType Sema::CheckPointerToMemberOperands(
-  Expr *&lex, Expr *&rex, SourceLocation Loc, bool isIndirect) {
+QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
+                                            ExprValueKind &VK,
+                                            SourceLocation Loc,
+                                            bool isIndirect) {
   const char *OpSpelling = isIndirect ? "->*" : ".*";
   // C++ 5.5p2
   //   The binary operator .* [p3: ->*] binds its second operand, which shall
@@ -2361,7 +2365,7 @@
   QualType LType = lex->getType();
   if (isIndirect) {
     if (const PointerType *Ptr = LType->getAs<PointerType>())
-      LType = Ptr->getPointeeType().getNonReferenceType();
+      LType = Ptr->getPointeeType();
     else {
       Diag(Loc, diag::err_bad_memptr_lhs)
         << OpSpelling << 1 << LType
@@ -2402,6 +2406,7 @@
     Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;
      return QualType();
   }
+
   // C++ 5.5p2
   //   The result is an object or a function of the type specified by the
   //   second operand.
@@ -2416,6 +2421,21 @@
   // We probably need a "MemberFunctionClosureType" or something like that.
   QualType Result = MemPtr->getPointeeType();
   Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
+
+  // C++ [expr.mptr.oper]p6:
+  //   The result of a .* expression whose second operand is a pointer
+  //   to a data member is of the same value category as its
+  //   first operand. The result of a .* expression whose second
+  //   operand is a pointer to a member function is a prvalue. The
+  //   result of an ->* expression is an lvalue if its second operand
+  //   is a pointer to data member and a prvalue otherwise.
+  if (Result->isFunctionType())
+    VK = VK_RValue;
+  else if (isIndirect)
+    VK = VK_LValue;
+  else
+    VK = lex->getValueKind();
+
   return Result;
 }
 
@@ -2573,7 +2593,7 @@
 /// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
 /// extension. In this case, LHS == Cond. (But they're not aliases.)
 QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
-                                           Expr *&SAVE,
+                                           Expr *&SAVE, ExprValueKind &VK,
                                            SourceLocation QuestionLoc) {
   // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
   // interface pointers.
@@ -2591,6 +2611,9 @@
       return QualType();
   }
 
+  // Assume r-value.
+  VK = VK_RValue;
+
   // Either of the arguments dependent?
   if (LHS->isTypeDependent() || RHS->isTypeDependent())
     return Context.DependentTy;
@@ -2670,19 +2693,20 @@
   }
 
   // C++0x 5.16p4
-  //   If the second and third operands are lvalues and have the same type,
-  //   the result is of that type [...]
+  //   If the second and third operands are glvalues of the same value
+  //   category and have the same type, the result is of that type and
+  //   value category and it is a bit-field if the second or the third
+  //   operand is a bit-field, or if both are bit-fields.
+  // We can't support the bitfield parts of that correctly right now,
+  // though, so we just require both sides to be ordinary values.
   bool Same = Context.hasSameType(LTy, RTy);
-  if (Same && LHS->isLvalue(Context) == Expr::LV_Valid &&
-      RHS->isLvalue(Context) == Expr::LV_Valid) {
-    // In this context, property reference is really a message call and
-    // is not considered an l-value.
-    bool lhsProperty = (isa<ObjCPropertyRefExpr>(LHS) || 
-                        isa<ObjCImplicitSetterGetterRefExpr>(LHS));
-    bool rhsProperty = (isa<ObjCPropertyRefExpr>(RHS) || 
-                        isa<ObjCImplicitSetterGetterRefExpr>(RHS));
-    if (!lhsProperty && !rhsProperty)
-      return LTy;
+  if (Same &&
+      LHS->getValueKind() != VK_RValue &&
+      LHS->getValueKind() == RHS->getValueKind() &&
+      LHS->getObjectKind() == OK_Ordinary &&
+      RHS->getObjectKind() == OK_Ordinary) {
+    VK = LHS->getValueKind();
+    return LTy;
   }
 
   // C++0x 5.16p5
@@ -3456,11 +3480,15 @@
 
   MemberExpr *ME = 
       new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method,
-                               SourceLocation(), Method->getType());
-  QualType ResultType = Method->getCallResultType();
+                               SourceLocation(), Method->getType(),
+                               VK_RValue, OK_Ordinary);
+  QualType ResultType = Method->getResultType();
+  ExprValueKind VK = Expr::getValueKindForType(ResultType);
+  ResultType = ResultType.getNonLValueExprType(Context);
+
   MarkDeclarationReferenced(Exp->getLocStart(), Method);
   CXXMemberCallExpr *CE =
-    new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType,
+    new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK,
                                     Exp->getLocEnd());
   return CE;
 }
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index be87a42..a99a72f 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -199,7 +199,7 @@
                                      Selector Sel, ObjCMethodDecl *Method,
                                      bool isClassMessage,
                                      SourceLocation lbrac, SourceLocation rbrac,
-                                     QualType &ReturnType) {
+                                     QualType &ReturnType, ExprValueKind &VK) {
   if (!Method) {
     // Apply default argument promotion as for (C99 6.5.2.2p6).
     for (unsigned i = 0; i != NumArgs; i++) {
@@ -214,10 +214,12 @@
     Diag(lbrac, DiagID)
       << Sel << isClassMessage << SourceRange(lbrac, rbrac);
     ReturnType = Context.getObjCIdType();
+    VK = VK_RValue;
     return false;
   }
 
   ReturnType = Method->getSendResultType();
+  VK = Expr::getValueKindForType(Method->getResultType());
 
   unsigned NumNamedArgs = Sel.getNumArgs();
   // Method might have more arguments than selector indicates. This is due
@@ -226,8 +228,8 @@
     NumNamedArgs = Method->param_size();
   // FIXME. This need be cleaned up.
   if (NumArgs < NumNamedArgs) {
-    Diag(lbrac, diag::err_typecheck_call_too_few_args) << 2
-    << NumNamedArgs << NumArgs;
+    Diag(lbrac, diag::err_typecheck_call_too_few_args)
+      << 2 << NumNamedArgs << NumArgs;
     return false;
   }
 
@@ -357,13 +359,16 @@
     Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
     ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
     if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))
-      ResTy = Getter->getSendResultType();
+      ResTy = Getter->getResultType();
+
     if (Super)
       return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
+                                                     VK_LValue, OK_ObjCProperty,
                                                      MemberLoc, 
                                                      SuperLoc, SuperType));
     else
       return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
+                                                     VK_LValue, OK_ObjCProperty,
                                                      MemberLoc, BaseExpr));
   }
   // Check protocols on qualified interfaces.
@@ -374,11 +379,15 @@
       if (DiagnoseUseOfDecl(PD, MemberLoc))
         return ExprError();
       if (Super)
-      return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
-                                                     MemberLoc, 
-                                                     SuperLoc, SuperType));
+        return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+                                                       VK_LValue,
+                                                       OK_ObjCProperty,
+                                                       MemberLoc, 
+                                                       SuperLoc, SuperType));
       else
         return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+                                                       VK_LValue,
+                                                       OK_ObjCProperty,
                                                        MemberLoc,
                                                        BaseExpr));
     }
@@ -426,12 +435,12 @@
     PType = Getter->getSendResultType();
     if (Super)
       return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
-                                    Setter, MemberLoc,
-                                    SuperLoc, SuperType));
+                                    VK_LValue, OK_ObjCProperty,
+                                    Setter, MemberLoc, SuperLoc, SuperType));
     else
       return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
-                                                                 Setter, MemberLoc, 
-                                                                 BaseExpr));
+                                    VK_LValue, OK_ObjCProperty,
+                                    Setter, MemberLoc, BaseExpr));
 
   }
 
@@ -546,7 +555,8 @@
         PType = (*PI)->getType();
     }
     return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(
-                                  Getter, PType, Setter,
+                                  Getter, PType, VK_LValue, OK_ObjCProperty,
+                                  Setter,
                                   propertyNameLoc, IFace, receiverNameLoc));
   }
   return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
@@ -751,8 +761,9 @@
     unsigned NumArgs = ArgsIn.size();
     Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
     assert(SuperLoc.isInvalid() && "Message to super with dependent type");
-    return Owned(ObjCMessageExpr::Create(Context, ReceiverType, LBracLoc,
-                                         ReceiverTypeInfo, Sel, /*Method=*/0, 
+    return Owned(ObjCMessageExpr::Create(Context, ReceiverType,
+                                         VK_RValue, LBracLoc, ReceiverTypeInfo,
+                                         Sel, /*Method=*/0,
                                          Args, NumArgs, RBracLoc));
   }
   
@@ -790,21 +801,23 @@
 
   // Check the argument types and determine the result type.
   QualType ReturnType;
+  ExprValueKind VK = VK_RValue;
+
   unsigned NumArgs = ArgsIn.size();
   Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
   if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true,
-                                LBracLoc, RBracLoc, ReturnType))
+                                LBracLoc, RBracLoc, ReturnType, VK))
     return ExprError();
 
   // Construct the appropriate ObjCMessageExpr.
   Expr *Result;
   if (SuperLoc.isValid())
-    Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, 
+    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, 
                                      SuperLoc, /*IsInstanceSuper=*/false, 
                                      ReceiverType, Sel, Method, Args, 
                                      NumArgs, RBracLoc);
   else
-    Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, 
+    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, 
                                      ReceiverTypeInfo, Sel, Method, Args, 
                                      NumArgs, RBracLoc);
   return MaybeBindToTemporary(Result);
@@ -889,7 +902,7 @@
       Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
       assert(SuperLoc.isInvalid() && "Message to super with dependent type");
       return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy,
-                                           LBracLoc, Receiver, Sel, 
+                                           VK_RValue, LBracLoc, Receiver, Sel, 
                                            /*Method=*/0, Args, NumArgs, 
                                            RBracLoc));
     }
@@ -1050,8 +1063,9 @@
   unsigned NumArgs = ArgsIn.size();
   Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
   QualType ReturnType;
+  ExprValueKind VK = VK_RValue;
   if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, false,
-                                LBracLoc, RBracLoc, ReturnType))
+                                LBracLoc, RBracLoc, ReturnType, VK))
     return ExprError();
   
   if (!ReturnType->isVoidType()) {
@@ -1063,12 +1077,13 @@
   // Construct the appropriate ObjCMessageExpr instance.
   Expr *Result;
   if (SuperLoc.isValid())
-    Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc,
+    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
                                      SuperLoc,  /*IsInstanceSuper=*/true,
                                      ReceiverType, Sel, Method, 
                                      Args, NumArgs, RBracLoc);
   else
-    Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, Receiver, 
+    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
+                                     Receiver, 
                                      Sel, Method, Args, NumArgs, RBracLoc);
   return MaybeBindToTemporary(Result);
 }
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 65002f3..607b7b1 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -485,8 +485,8 @@
       // FIXME. Eventually we want to do this for Objective-C as well.
       ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
       DeclRefExpr *SelfExpr = 
-        new (Context) DeclRefExpr(SelfDecl,SelfDecl->getType(),
-                                  SourceLocation());
+        new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(),
+                                  VK_RValue, SourceLocation());
       Expr *IvarRefExpr =
         new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
                                       SelfExpr, true, true);
@@ -512,15 +512,15 @@
       // FIXME. Eventually we want to do this for Objective-C as well.
       ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
       DeclRefExpr *SelfExpr = 
-        new (Context) DeclRefExpr(SelfDecl,SelfDecl->getType(),
-                                  SourceLocation());
+        new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(),
+                                  VK_RValue, SourceLocation());
       Expr *lhs =
         new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
                                       SelfExpr, true, true);
       ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
       ParmVarDecl *Param = (*P);
-      Expr *rhs = new (Context) DeclRefExpr(Param,Param->getType(),
-                                            SourceLocation());
+      Expr *rhs = new (Context) DeclRefExpr(Param, Param->getType(),
+                                            VK_LValue, SourceLocation());
       ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), 
                                   BO_Assign, lhs, rhs);
       PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 65d6bc8..a0e4816 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -33,6 +33,16 @@
 namespace clang {
 using namespace sema;
 
+/// A convenience routine for creating a decayed reference to a
+/// function.
+static Expr *
+CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn,
+                      SourceLocation Loc = SourceLocation()) {
+  Expr *E = new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc);
+  S.DefaultFunctionArrayConversion(E);
+  return E;
+}
+
 static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
                                  bool InOverloadResolution,
                                  StandardConversionSequence &SCS);
@@ -3895,7 +3905,7 @@
   // call on the stack and we don't need its arguments to be
   // well-formed.
   DeclRefExpr ConversionRef(Conversion, Conversion->getType(),
-                            From->getLocStart());
+                            VK_LValue, From->getLocStart());
   ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
                                 Context.getPointerType(Conversion->getType()),
                                 CK_FunctionToPointerDecay,
@@ -3909,10 +3919,12 @@
     return;
   }
 
+  ExprValueKind VK = Expr::getValueKindForType(Conversion->getConversionType());
+
   // Note that it is safe to allocate CallExpr on the stack here because
   // there are 0 arguments (i.e., nothing is allocated using ASTContext's
   // allocator).
-  CallExpr Call(Context, &ConversionFn, 0, 0, CallResultType, 
+  CallExpr Call(Context, &ConversionFn, 0, 0, CallResultType, VK,
                 From->getLocStart());
   ImplicitConversionSequence ICS =
     TryCopyInitialization(*this, &Call, ToType,
@@ -7086,6 +7098,7 @@
       return Owned(new (Context) UnaryOperator(Input,
                                                Opc, 
                                                Context.DependentTy,
+                                               VK_RValue, OK_Ordinary,
                                                OpLoc));
     
     CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
@@ -7097,6 +7110,7 @@
     return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
                                                    &Args[0], NumArgs,
                                                    Context.DependentTy,
+                                                   VK_RValue,
                                                    OpLoc));
   }
 
@@ -7151,18 +7165,18 @@
 
       DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
 
-      // Determine the result type
-      QualType ResultTy = FnDecl->getCallResultType();
+      // Determine the result type.
+      QualType ResultTy = FnDecl->getResultType();
+      ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+      ResultTy = ResultTy.getNonLValueExprType(Context);
 
       // Build the actual expression node.
-      Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
-                                               SourceLocation());
-      UsualUnaryConversions(FnExpr);
+      Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl);
 
       Args[0] = Input;
       CallExpr *TheCall =
         new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
-                                          Args, NumArgs, ResultTy, OpLoc);
+                                          Args, NumArgs, ResultTy, VK, OpLoc);
 
       if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, 
                               FnDecl))
@@ -7248,10 +7262,14 @@
       // BinaryOperator or CompoundAssignment.
       if (Opc <= BO_Assign || Opc > BO_OrAssign)
         return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
-                                                  Context.DependentTy, OpLoc));
+                                                  Context.DependentTy,
+                                                  VK_RValue, OK_Ordinary,
+                                                  OpLoc));
       
       return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
                                                         Context.DependentTy,
+                                                        VK_LValue,
+                                                        OK_Ordinary,
                                                         Context.DependentTy,
                                                         Context.DependentTy,
                                                         OpLoc));
@@ -7269,6 +7287,7 @@
     return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
                                                    Args, 2,
                                                    Context.DependentTy,
+                                                   VK_RValue,
                                                    OpLoc));
   }
 
@@ -7362,19 +7381,17 @@
 
         DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
 
-        // Determine the result type
-        QualType ResultTy
-          = FnDecl->getType()->getAs<FunctionType>()
-                                                ->getCallResultType(Context);
+        // Determine the result type.
+        QualType ResultTy = FnDecl->getResultType();
+        ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+        ResultTy = ResultTy.getNonLValueExprType(Context);
 
         // Build the actual expression node.
-        Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
-                                                 OpLoc);
-        UsualUnaryConversions(FnExpr);
+        Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc);
 
         CXXOperatorCallExpr *TheCall =
           new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
-                                            Args, 2, ResultTy, OpLoc);
+                                            Args, 2, ResultTy, VK, OpLoc);
         
         if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, 
                                 FnDecl))
@@ -7474,6 +7491,7 @@
     return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
                                                    Args, 2,
                                                    Context.DependentTy,
+                                                   VK_RValue,
                                                    RLoc));
   }
 
@@ -7521,19 +7539,17 @@
         Args[1] = InputInit.takeAs<Expr>();
 
         // Determine the result type
-        QualType ResultTy
-          = FnDecl->getType()->getAs<FunctionType>()
-                                                  ->getCallResultType(Context);
+        QualType ResultTy = FnDecl->getResultType();
+        ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+        ResultTy = ResultTy.getNonLValueExprType(Context);
 
         // Build the actual expression node.
-        Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
-                                                 LLoc);
-        UsualUnaryConversions(FnExpr);
+        Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc);
 
         CXXOperatorCallExpr *TheCall =
           new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
                                             FnExpr, Args, 2,
-                                            ResultTy, RLoc);
+                                            ResultTy, VK, RLoc);
 
         if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
                                 FnDecl))
@@ -7704,11 +7720,14 @@
     MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
   }
 
+  QualType ResultType = Method->getResultType();
+  ExprValueKind VK = Expr::getValueKindForType(ResultType);
+  ResultType = ResultType.getNonLValueExprType(Context);
+
   assert(Method && "Member call to something that isn't a method?");
   CXXMemberCallExpr *TheCall = 
     new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
-                                    Method->getCallResultType(),
-                                    RParenLoc);
+                                    ResultType, VK, RParenLoc);
 
   // Check for a valid return type.
   if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(), 
@@ -7909,17 +7928,18 @@
   for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
     MethodArgs[ArgIdx + 1] = Args[ArgIdx];
 
-  Expr *NewFn = new (Context) DeclRefExpr(Method, Method->getType(),
-                                          SourceLocation());
-  UsualUnaryConversions(NewFn);
+  Expr *NewFn = CreateFunctionRefExpr(*this, Method);
 
   // Once we've built TheCall, all of the expressions are properly
   // owned.
-  QualType ResultTy = Method->getCallResultType();
+  QualType ResultTy = Method->getResultType();
+  ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+  ResultTy = ResultTy.getNonLValueExprType(Context);
+
   CXXOperatorCallExpr *TheCall =
     new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn,
                                       MethodArgs, NumArgs + 1,
-                                      ResultTy, RParenLoc);
+                                      ResultTy, VK, RParenLoc);
   delete [] MethodArgs;
 
   if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall, 
@@ -8064,14 +8084,14 @@
     return ExprError();
 
   // Build the operator call.
-  Expr *FnExpr = new (Context) DeclRefExpr(Method, Method->getType(),
-                                           SourceLocation());
-  UsualUnaryConversions(FnExpr);
+  Expr *FnExpr = CreateFunctionRefExpr(*this, Method);
   
-  QualType ResultTy = Method->getCallResultType();
+  QualType ResultTy = Method->getResultType();
+  ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+  ResultTy = ResultTy.getNonLValueExprType(Context);
   CXXOperatorCallExpr *TheCall =
     new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, 
-                                      &Base, 1, ResultTy, OpLoc);
+                                      &Base, 1, ResultTy, VK, OpLoc);
 
   if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, 
                           Method))
@@ -8140,8 +8160,9 @@
         QualType MemPtrType
           = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
 
-        return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
-                                           MemPtrType, UnOp->getOperatorLoc());
+        return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
+                                           VK_RValue, OK_Ordinary,
+                                           UnOp->getOperatorLoc());
       }
     }
     Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -8151,6 +8172,7 @@
     
     return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
                                      Context.getPointerType(SubExpr->getType()),
+                                       VK_RValue, OK_Ordinary,
                                        UnOp->getOperatorLoc());
   } 
 
@@ -8168,6 +8190,7 @@
                                Fn,
                                ULE->getNameLoc(),
                                Fn->getType(),
+                               VK_LValue,
                                TemplateArgs);
   }
 
@@ -8181,7 +8204,8 @@
 
     Expr *Base;
 
-    // If we're filling in 
+    // If we're filling in a static method where we used to have an
+    // implicit member access, rewrite to a simple decl ref.
     if (MemExpr->isImplicitAccess()) {
       if (cast<CXXMethodDecl>(Fn)->isStatic()) {
         return DeclRefExpr::Create(Context,
@@ -8190,6 +8214,7 @@
                                    Fn,
                                    MemExpr->getMemberLoc(),
                                    Fn->getType(),
+                                   VK_LValue,
                                    TemplateArgs);
       } else {
         SourceLocation Loc = MemExpr->getMemberLoc();
@@ -8210,7 +8235,10 @@
                               Found,
                               MemExpr->getMemberNameInfo(),
                               TemplateArgs,
-                              Fn->getType());
+                              Fn->getType(),
+                              cast<CXXMethodDecl>(Fn)->isStatic()
+                                ? VK_LValue : VK_RValue,
+                              OK_Ordinary);
   }
   
   llvm_unreachable("Invalid reference to overloaded function");
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 3f4a1af..4c25bc3 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3361,9 +3361,10 @@
       CXXScopeSpec SS;
       SS.setScopeRep(Qualifier);
       ExprResult RefExpr = BuildDeclRefExpr(VD, 
-                                           VD->getType().getNonReferenceType(), 
-                                                  Loc,
-                                                  &SS);
+                                            VD->getType().getNonReferenceType(),
+                                            VK_LValue,
+                                            Loc,
+                                            &SS);
       if (RefExpr.isInvalid())
         return ExprError();
       
@@ -3390,7 +3391,7 @@
   if (ParamType->isPointerType()) {
     // When the non-type template parameter is a pointer, take the
     // address of the declaration.
-    ExprResult RefExpr = BuildDeclRefExpr(VD, T, Loc);
+    ExprResult RefExpr = BuildDeclRefExpr(VD, T, VK_LValue, Loc);
     if (RefExpr.isInvalid())
       return ExprError();
 
@@ -3410,13 +3411,18 @@
     return CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
   }
 
+  ExprValueKind VK = VK_RValue;
+
   // If the non-type template parameter has reference type, qualify the
   // resulting declaration reference with the extra qualifiers on the
   // type that the reference refers to.
-  if (const ReferenceType *TargetRef = ParamType->getAs<ReferenceType>())
-    T = Context.getQualifiedType(T, TargetRef->getPointeeType().getQualifiers());
+  if (const ReferenceType *TargetRef = ParamType->getAs<ReferenceType>()) {
+    VK = VK_LValue;
+    T = Context.getQualifiedType(T,
+                              TargetRef->getPointeeType().getQualifiers());
+  }
     
-  return BuildDeclRefExpr(VD, T, Loc);
+  return BuildDeclRefExpr(VD, T, VK, Loc);
 }
 
 /// \brief Construct a new expression that refers to the given
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index bae703d..807346c 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1142,26 +1142,32 @@
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
   ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc,
-                                     bool isArrow,
-                                     NestedNameSpecifier *Qualifier,
-                                     SourceRange QualifierRange,
-                                     const DeclarationNameInfo &MemberNameInfo,
-                                     ValueDecl *Member,
-                                     NamedDecl *FoundDecl,
+                               bool isArrow,
+                               NestedNameSpecifier *Qualifier,
+                               SourceRange QualifierRange,
+                               const DeclarationNameInfo &MemberNameInfo,
+                               ValueDecl *Member,
+                               NamedDecl *FoundDecl,
                         const TemplateArgumentListInfo *ExplicitTemplateArgs,
-                                     NamedDecl *FirstQualifierInScope) {
+                               NamedDecl *FirstQualifierInScope) {
     if (!Member->getDeclName()) {
-      // We have a reference to an unnamed field.
+      // We have a reference to an unnamed field.  This is always the
+      // base of an anonymous struct/union member access, i.e. the
+      // field is always of record type.
       assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
+      assert(Member->getType()->isRecordType() &&
+             "unnamed member not of record type?");
 
       if (getSema().PerformObjectMemberConversion(Base, Qualifier,
                                                   FoundDecl, Member))
         return ExprError();
 
+      ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind();
       MemberExpr *ME =
         new (getSema().Context) MemberExpr(Base, isArrow,
                                            Member, MemberNameInfo,
-                                           cast<FieldDecl>(Member)->getType());
+                                           cast<FieldDecl>(Member)->getType(),
+                                           VK, OK_Ordinary);
       return getSema().Owned(ME);
     }
 
@@ -1903,18 +1909,21 @@
     // perform semantic analysis again.
     if (Super)
       return Owned(
-                   new (getSema().Context) ObjCImplicitSetterGetterRefExpr(Getter, T,
-                                                                           Setter,
-                                                                           NameLoc,
-                                                                           SuperLoc,
-                                                                           SuperTy));
+        new (getSema().Context) ObjCImplicitSetterGetterRefExpr(Getter, T,
+                                                                VK_LValue,
+                                                                OK_Ordinary,
+                                                                Setter,
+                                                                NameLoc,
+                                                                SuperLoc,
+                                                                SuperTy));
     else
       return Owned(
-                   new (getSema().Context) ObjCImplicitSetterGetterRefExpr(
-                                                                     Getter, T,
-                                                                     Setter,
-                                                                     NameLoc,
-                                                                     Base));
+        new (getSema().Context) ObjCImplicitSetterGetterRefExpr(Getter, T,
+                                                                VK_LValue,
+                                                                OK_Ordinary,
+                                                                Setter,
+                                                                NameLoc,
+                                                                Base));
   }
 
   /// \brief Build a new Objective-C "isa" expression.
@@ -1948,8 +1957,8 @@
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
   ExprResult RebuildShuffleVectorExpr(SourceLocation BuiltinLoc,
-                                            MultiExprArg SubExprs,
-                                            SourceLocation RParenLoc) {
+                                      MultiExprArg SubExprs,
+                                      SourceLocation RParenLoc) {
     // Find the declaration for __builtin_shufflevector
     const IdentifierInfo &Name
       = SemaRef.Context.Idents.get("__builtin_shufflevector");
@@ -1961,7 +1970,7 @@
     FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first);
     Expr *Callee
       = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(),
-                                          BuiltinLoc);
+                                          VK_LValue, BuiltinLoc);
     SemaRef.UsualUnaryConversions(Callee);
 
     // Build the CallExpr
@@ -1970,6 +1979,7 @@
     CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee,
                                                        Subs, NumSubExprs,
                                                    Builtin->getCallResultType(),
+                            Expr::getValueKindForType(Builtin->getResultType()),
                                                        RParenLoc);
     ExprResult OwnedCall(SemaRef.Owned(TheCall));