Basic support for volatile loads and stores. Stores the volatile 
qualifier in the lvalue, and changes lvalue loads/stores to honor 
the volatile flag.  Places which need some further attention are marked 
with FIXMEs.

Patch by Cédric Venet.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52264 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 232f6d6..51d7ced 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -143,7 +143,6 @@
     
     Value *SrcPtr = CreateTempAlloca(SrcValue->getType(), "dst_ptr");
     
-    // FIXME: Volatile
     Builder.CreateStore(SrcValue, SrcPtr, false);
 
     const llvm::Type *Type = 
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index fe58ca0..2d30ed5 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -208,7 +208,7 @@
                                      AllocaInsertPt);
       
       // Store the initial value into the alloca.
-      Builder.CreateStore(Arg, DeclPtr);
+      Builder.CreateStore(Arg, DeclPtr,Ty.isVolatileQualified());
     } else {
       // Otherwise, if this is an aggregate, just use the input pointer.
       DeclPtr = Arg;
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index d960503..05a8972 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -97,7 +97,8 @@
     printf("Statement class: %d\n", E->getStmtClass());
     WarnUnsupported(E, "l-value expression");
     llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType()));
-    return LValue::MakeAddr(llvm::UndefValue::get(Ty));
+    return LValue::MakeAddr(llvm::UndefValue::get(Ty),
+                            E->getType().getCVRQualifiers());
   }
 
   case Expr::CallExprClass: return EmitCallExprLValue(cast<CallExpr>(E));
@@ -134,7 +135,7 @@
     
     // Simple scalar l-value.
     if (EltTy->isSingleValueType()) {
-      llvm::Value *V = Builder.CreateLoad(Ptr, "tmp");
+      llvm::Value *V = Builder.CreateLoad(Ptr, LV.isVolatileQualified(),"tmp");
       
       // Bool can have different representation in memory than in registers.
       if (ExprType->isBooleanType()) {
@@ -150,7 +151,8 @@
   }
   
   if (LV.isVectorElt()) {
-    llvm::Value *Vec = Builder.CreateLoad(LV.getVectorAddr(), "tmp");
+    llvm::Value *Vec = Builder.CreateLoad(LV.getVectorAddr(),
+                                          LV.isVolatileQualified(), "tmp");
     return RValue::get(Builder.CreateExtractElement(Vec, LV.getVectorIdx(),
                                                     "vecext"));
   }
@@ -178,7 +180,7 @@
   unsigned short BitfieldSize = LV.getBitfieldSize();
   unsigned short EndBit = LV.getBitfieldStartBit() + BitfieldSize;
 
-  llvm::Value *V = Builder.CreateLoad(Ptr, "tmp");
+  llvm::Value *V = Builder.CreateLoad(Ptr, LV.isVolatileQualified(), "tmp");
 
   llvm::Value *ShAmt = llvm::ConstantInt::get(EltTy, EltTySize - EndBit);
   V = Builder.CreateShl(V, ShAmt, "tmp");
@@ -199,7 +201,8 @@
 // shuffle the input or extract/insert them as appropriate.
 RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
                                                          QualType ExprType) {
-  llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(), "tmp");
+  llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(),
+                                        LV.isVolatileQualified(), "tmp");
   
   const llvm::Constant *Elts = LV.getExtVectorElts();
   
@@ -258,11 +261,11 @@
   if (!Dst.isSimple()) {
     if (Dst.isVectorElt()) {
       // Read/modify/write the vector, inserting the new element.
-      // FIXME: Volatility.
-      llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddr(), "tmp");
+      llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddr(),
+                                            Dst.isVolatileQualified(), "tmp");
       Vec = Builder.CreateInsertElement(Vec, Src.getScalarVal(),
                                         Dst.getVectorIdx(), "vecins");
-      Builder.CreateStore(Vec, Dst.getVectorAddr());
+      Builder.CreateStore(Vec, Dst.getVectorAddr(),Dst.isVolatileQualified());
       return;
     }
   
@@ -289,7 +292,7 @@
     DstAddr = Builder.CreateBitCast(DstAddr, 
                                     llvm::PointerType::get(SrcTy, AS),
                                     "storetmp");
-  Builder.CreateStore(Src.getScalarVal(), DstAddr);
+  Builder.CreateStore(Src.getScalarVal(), DstAddr, Dst.isVolatileQualified());
 }
 
 void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
@@ -299,7 +302,8 @@
   llvm::Value *Ptr = Dst.getBitfieldAddr();
 
   llvm::Value *NewVal = Src.getScalarVal();
-  llvm::Value *OldVal = Builder.CreateLoad(Ptr, "tmp");
+  llvm::Value *OldVal = Builder.CreateLoad(Ptr, Dst.isVolatileQualified(),
+                                           "tmp");
 
   // The bitfield type and the normal type differ when the storage sizes
   // differ (currently just _Bool).
@@ -326,7 +330,7 @@
   // Finally, merge the two together and store it.
   NewVal = Builder.CreateOr(OldVal, NewVal, "tmp");
 
-  Builder.CreateStore(NewVal, Ptr);
+  Builder.CreateStore(NewVal, Ptr, Dst.isVolatileQualified());
 }
 
 void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
@@ -334,8 +338,8 @@
                                                                QualType Ty) {
   // This access turns into a read/modify/write of the vector.  Load the input
   // value now.
-  llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddr(), "tmp");
-  // FIXME: Volatility.
+  llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddr(),
+                                        Dst.isVolatileQualified(), "tmp");
   const llvm::Constant *Elts = Dst.getExtVectorElts();
   
   llvm::Value *SrcVal = Src.getScalarVal();
@@ -359,7 +363,7 @@
     Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp");
   }
   
-  Builder.CreateStore(Vec, Dst.getExtVectorAddr());
+  Builder.CreateStore(Vec, Dst.getExtVectorAddr(), Dst.isVolatileQualified());
 }
 
 
@@ -368,16 +372,19 @@
   
   if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(VD))) {
     if (VD->getStorageClass() == VarDecl::Extern)
-      return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false));
+      return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false),
+                              E->getType().getCVRQualifiers());
     else {
       llvm::Value *V = LocalDeclMap[VD];
       assert(V && "BlockVarDecl not entered in LocalDeclMap?");
-      return LValue::MakeAddr(V);
+      return LValue::MakeAddr(V, E->getType().getCVRQualifiers());
     }
   } else if (VD && VD->isFileVarDecl()) {
-    return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false));
+    return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false),
+                            E->getType().getCVRQualifiers());
   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
-    return LValue::MakeAddr(CGM.GetAddrOfFunctionDecl(FD, false));
+    return LValue::MakeAddr(CGM.GetAddrOfFunctionDecl(FD, false),
+                            E->getType().getCVRQualifiers());
   }
   assert(0 && "Unimp declref");
   //an invalid LValue, but the assert will
@@ -393,13 +400,15 @@
   switch (E->getOpcode()) {
   default: assert(0 && "Unknown unary operator lvalue!");
   case UnaryOperator::Deref:
-    return LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()));
+    return LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()),
+      E->getSubExpr()->getType().getCanonicalType()->getAsPointerType()
+      ->getPointeeType().getCVRQualifiers());
   case UnaryOperator::Real:
   case UnaryOperator::Imag:
     LValue LV = EmitLValue(E->getSubExpr());
     unsigned Idx = E->getOpcode() == UnaryOperator::Imag;
     return LValue::MakeAddr(Builder.CreateStructGEP(LV.getAddress(),
-                                                    Idx, "idx"));
+      Idx, "idx"),E->getSubExpr()->getType().getCVRQualifiers());
   }
 }
 
@@ -415,7 +424,7 @@
   uint64_t RealLen = CAT->getSize().getZExtValue();
   StringLiteral.resize(RealLen, '\0');
 
-  return LValue::MakeAddr(CGM.GetAddrOfConstantString(StringLiteral));
+  return LValue::MakeAddr(CGM.GetAddrOfConstantString(StringLiteral),0);
 }
 
 LValue CodeGenFunction::EmitPreDefinedLValue(const PreDefinedExpr *E) {
@@ -452,7 +461,7 @@
   C = new llvm::GlobalVariable(C->getType(), true, 
                                llvm::GlobalValue::InternalLinkage,
                                C, GlobalVarName, CurFn->getParent());
-  return LValue::MakeAddr(C);
+  return LValue::MakeAddr(C,0);
 }
 
 LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
@@ -461,12 +470,13 @@
   
   // If the base is a vector type, then we are forming a vector element lvalue
   // with this subscript.
-  if (E->getLHS()->getType()->isVectorType()) {
+  if (E->getBase()->getType()->isVectorType()) {
     // Emit the vector as an lvalue to get its address.
-    LValue LHS = EmitLValue(E->getLHS());
+    LValue LHS = EmitLValue(E->getBase());
     assert(LHS.isSimple() && "Can only subscript lvalue vectors here!");
     // FIXME: This should properly sign/zero/extend or truncate Idx to i32.
-    return LValue::MakeVectorElt(LHS.getAddress(), Idx);
+    return LValue::MakeVectorElt(LHS.getAddress(), Idx,
+      E->getBase()->getType().getCVRQualifiers());
   }
   
   // The base must be a pointer, which is not an aggregate.  Emit it.
@@ -484,7 +494,9 @@
   // size is a VLA.
   if (!E->getType()->isConstantSizeType())
     assert(0 && "VLA idx not implemented");
-  return LValue::MakeAddr(Builder.CreateGEP(Base, Idx, "arrayidx"));
+  return LValue::MakeAddr(Builder.CreateGEP(Base, Idx, "arrayidx"),
+    E->getBase()->getType().getCanonicalType()->getAsPointerType()
+    ->getPointeeType().getCVRQualifiers());
 }
 
 static 
@@ -508,7 +520,8 @@
 
   if (Base.isSimple()) {
     llvm::Constant *CV = GenerateConstantVector(Indices);
-    return LValue::MakeExtVectorElt(Base.getAddress(), CV);
+    return LValue::MakeExtVectorElt(Base.getAddress(), CV,
+                                   E->getBase()->getType().getCVRQualifiers());
   }
   assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!");
 
@@ -522,14 +535,16 @@
       CElts.push_back(BaseElts->getOperand(Indices[i]));
   }
   llvm::Constant *CV = llvm::ConstantVector::get(&CElts[0], CElts.size());
-  return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV);
+  return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV,
+                                  E->getBase()->getType().getCVRQualifiers());
 }
 
 LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
   bool isUnion = false;
   Expr *BaseExpr = E->getBase();
   llvm::Value *BaseValue = NULL;
-  
+  unsigned CVRQualifiers=0;
+
   // If this is s.x, emit s as an lvalue.  If it is s->x, emit s as a scalar.
   if (E->isArrow()) {
     BaseValue = EmitScalarExpr(BaseExpr);
@@ -537,6 +552,7 @@
       cast<PointerType>(BaseExpr->getType().getCanonicalType());
     if (PTy->getPointeeType()->isUnionType())
       isUnion = true;
+    CVRQualifiers = PTy->getPointeeType().getCVRQualifiers();
   }
   else {
     LValue BaseLV = EmitLValue(BaseExpr);
@@ -544,15 +560,17 @@
     BaseValue = BaseLV.getAddress();
     if (BaseExpr->getType()->isUnionType())
       isUnion = true;
+    CVRQualifiers = BaseExpr->getType().getCVRQualifiers();
   }
 
   FieldDecl *Field = E->getMemberDecl();
-  return EmitLValueForField(BaseValue, Field, isUnion);
+  return EmitLValueForField(BaseValue, Field, isUnion, CVRQualifiers);
 }
 
 LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue,
                                            FieldDecl* Field,
-                                           bool isUnion)
+                                           bool isUnion,
+                                           unsigned CVRQualifiers)
 {
   llvm::Value *V;
   unsigned idx = CGM.getTypes().getLLVMFieldNo(Field);
@@ -574,14 +592,16 @@
     CodeGenTypes::BitFieldInfo bitFieldInfo =
       CGM.getTypes().getBitFieldInfo(Field);
     return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size,
-                                Field->getType()->isSignedIntegerType());
+                                Field->getType()->isSignedIntegerType(),
+                            Field->getType().getCVRQualifiers()|CVRQualifiers);
   }
 
   V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
 
   // Match union field type.
   if (isUnion) {
-    const llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(Field->getType());
+    const llvm::Type *FieldTy = 
+      CGM.getTypes().ConvertTypeForMem(Field->getType());
     const llvm::PointerType * BaseTy = 
       cast<llvm::PointerType>(BaseValue->getType());
     unsigned AS = BaseTy->getAddressSpace();
@@ -590,15 +610,17 @@
                               "tmp");
   }
 
-  return LValue::MakeAddr(V);
+  return LValue::MakeAddr(V, 
+                          Field->getType().getCVRQualifiers()|CVRQualifiers);
 }
 
-LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E) {
+LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E)
+{
   const llvm::Type *LTy = ConvertType(E->getType());
   llvm::Value *DeclPtr = CreateTempAlloca(LTy, ".compoundliteral");
 
   const Expr* InitExpr = E->getInitializer();
-  LValue Result = LValue::MakeAddr(DeclPtr);
+  LValue Result = LValue::MakeAddr(DeclPtr, E->getType().getCVRQualifiers());
 
   if (E->getType()->isComplexType()) {
     EmitComplexExprIntoAddr(InitExpr, DeclPtr, false);
@@ -640,7 +662,9 @@
 LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
   // Can only get l-value for call expression returning aggregate type
   RValue RV = EmitCallExpr(E);
-  return LValue::MakeAddr(RV.getAggregateAddr());
+  // FIXME: can this be volatile?
+  return LValue::MakeAddr(RV.getAggregateAddr(),
+                          E->getType().getCVRQualifiers());
 }
 
 LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
@@ -665,14 +689,16 @@
     
   // Get object pointer and coerce object pointer to correct type.
   llvm::Value *Object = EmitLValue(E->getBase()).getAddress();
+  // FIXME: Volatility
   Object = Builder.CreateLoad(Object, E->getDecl()->getName());
   if (Object->getType() != ObjectType)
     Object = Builder.CreateBitCast(Object, ObjectType);
 
   
   // Return a pointer to the right element.
+  // FIXME: volatile
   return LValue::MakeAddr(Builder.CreateStructGEP(Object, Index,
-                                                  Decl->getName()));
+                                                  Decl->getName()),0);
 }
 
 RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType FnType, 
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 80231cc..924a5cf 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -280,6 +280,7 @@
   llvm::Value *ArgValue = CGF.EmitLValue(VE->getSubExpr()).getAddress();
   llvm::Value *V = Builder.CreateVAArg(ArgValue, CGF.ConvertType(VE->getType()));
   if (DestPtr)
+    // FIXME: volatility
     Builder.CreateStore(V, DestPtr);
 }
 
@@ -299,6 +300,7 @@
       if (isa<InitListExpr>(Init))
         CGF.EmitAggExpr(Init, NextVal, VolatileDest);
       else
+        // FIXME: volatility
         Builder.CreateStore(CGF.EmitScalarExpr(Init), NextVal);
     }
 
@@ -309,6 +311,7 @@
     for (/*Do not initialize i*/; i < NumArrayElements; ++i) {
       llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
       if (EType->isSingleValueType())
+        // FIXME: volatility
         Builder.CreateStore(llvm::Constant::getNullValue(EType), NextVal);
       else
         EmitAggregateClear(NextVal, QType);
@@ -333,6 +336,7 @@
     // For non-aggregates, we can store zero
     const llvm::Type *T =
        cast<llvm::PointerType>(LV.getAddress()->getType())->getElementType();
+    // FIXME: volatility
     Builder.CreateStore(llvm::Constant::getNullValue(T), LV.getAddress());
   } else {
     // Otherwise, just memset the whole thing to zero.  This is legal
@@ -382,12 +386,16 @@
     uint64_t NumArrayElements = AType->getNumElements();
     QualType ElementType = E->getType()->getAsArrayType()->getElementType();
     
+    unsigned CVRqualifier = E->getType().getCanonicalType()->getAsArrayType()
+                            ->getElementType().getCVRQualifiers();
+
     for (uint64_t i = 0; i != NumArrayElements; ++i) {
       llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
       if (i < NumInitElements)
-        EmitInitializationToLValue(E->getInit(i), LValue::MakeAddr(NextVal));
+        EmitInitializationToLValue(E->getInit(i),
+                                   LValue::MakeAddr(NextVal, CVRqualifier));
       else
-        EmitNullInitializationToLValue(LValue::MakeAddr(NextVal),
+        EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, CVRqualifier),
                                        ElementType);
     }
     return;
@@ -418,7 +426,8 @@
       // Initializers can't initialize unnamed fields, e.g. "int : 20;"
       continue;
     }
-    LValue FieldLoc = CGF.EmitLValueForField(DestPtr, CurField, isUnion);
+    // FIXME: volatility
+    LValue FieldLoc = CGF.EmitLValueForField(DestPtr, CurField, isUnion,0);
     if (CurInitVal < NumInitElements) {
       // Store the initializer into the field
       // This will probably have to get a bit smarter when we support
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 78e02e4..e545fc1 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -222,6 +222,7 @@
     if (SelTypes == 0) {
       // If it's already cached, return it.
       if (UntypedSelectors[CName->getStringValue()]) {
+        // FIXME: Volatility
         return Builder.CreateLoad(UntypedSelectors[CName->getStringValue()]);
       }
       // If it isn't, cache it.
@@ -230,6 +231,7 @@
           llvm::GlobalValue::InternalLinkage, ".objc_untyped_selector_alias",
           NULL, &TheModule);
       UntypedSelectors[CName->getStringValue()] = Sel;
+      // FIXME: Volatility
       return Builder.CreateLoad(Sel);
     }
     // Typed selectors
@@ -238,6 +240,7 @@
           CTypes->getStringValue());
       // If it's already cached, return it.
       if (TypedSelectors[Selector]) {
+        // FIXME: Volatility
         return Builder.CreateLoad(TypedSelectors[Selector]);
       }
       // If it isn't, cache it.
@@ -246,6 +249,7 @@
           llvm::GlobalValue::InternalLinkage, ".objc_typed_selector_alias",
           NULL, &TheModule);
       TypedSelectors[Selector] = Sel;
+      // FIXME: Volatility
       return Builder.CreateLoad(Sel);
     }
   }
@@ -337,6 +341,7 @@
   llvm::StructType *ObjCSuperTy = llvm::StructType::get(Receiver->getType(),
       IdTy, NULL);
   llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy);
+  // FIXME: volatility
   Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
   Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
 
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 067d6eb..736fad0 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -808,6 +808,6 @@
     llvm::InlineAsm::get(FTy, AsmString, Constraints, 
                          S.isVolatile() || S.getNumOutputs() == 0);
   llvm::Value *Result = Builder.CreateCall(IA, Args.begin(), Args.end(), "");
-  if (ResultAddr)
+  if (ResultAddr) // FIXME: volatility
     Builder.CreateStore(Result, ResultAddr);
 }
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 1557738..c8ef8fc 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -114,6 +114,7 @@
                                    AllocaInsertPt);
 
   // Store the initial value into the alloca.
+  // FIXME: volatility
   Builder.CreateStore(AI, DeclPtr);
   DMEntry = DeclPtr;
   ++AI; ++AI;
@@ -152,6 +153,7 @@
 {
   if(const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurFuncDecl)) {
     llvm::Value *SelfPtr = LocalDeclMap[&(*OMD->getSelfDecl())];
+    // FIXME: Volatility
     return Builder.CreateLoad(SelfPtr, "self");
   }
   return NULL;
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 077a7bd..313d2d1 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -149,8 +149,7 @@
 /// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a
 /// bitrange.
 class LValue {
-  // FIXME: Volatility.  Restrict?
-  // alignment?
+  // FIXME: alignment?
   
   enum {
     Simple,       // This is a normal l-value, use getAddress().
@@ -174,12 +173,26 @@
       bool IsSigned;
     } BitfieldData;           // BitField start bit and size
   };
+
+  bool Volatile:1;
+  // FIXME: set but never used, what effect should it have?
+  bool Restrict:1;
+
+private:
+  static void SetQualifiers(unsigned Qualifiers, LValue& R) {
+    R.Volatile = (Qualifiers&QualType::Volatile)!=0;
+    R.Restrict = (Qualifiers&QualType::Restrict)!=0;
+  }
+
 public:
   bool isSimple() const { return LVType == Simple; }
   bool isVectorElt() const { return LVType == VectorElt; }
   bool isBitfield() const { return LVType == BitField; }
   bool isExtVectorElt() const { return LVType == ExtVectorElt; }
   
+  bool isVolatileQualified() const { return Volatile; }
+  bool isRestrictQualified() const { return Restrict; }
+
   // simple lvalue
   llvm::Value *getAddress() const { assert(isSimple()); return V; }
   // vector elt lvalue
@@ -206,37 +219,44 @@
     return BitfieldData.IsSigned;
   }
 
-  static LValue MakeAddr(llvm::Value *V) {
+  static LValue MakeAddr(llvm::Value *V, unsigned Qualifiers) {
     LValue R;
     R.LVType = Simple;
     R.V = V;
+    SetQualifiers(Qualifiers,R);
     return R;
   }
   
-  static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx) {
+  static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx,
+                              unsigned Qualifiers) {
     LValue R;
     R.LVType = VectorElt;
     R.V = Vec;
     R.VectorIdx = Idx;
+    SetQualifiers(Qualifiers,R);
     return R;
   }
   
-  static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts) {
+  static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts,
+                                 unsigned Qualifiers) {
     LValue R;
     R.LVType = ExtVectorElt;
     R.V = Vec;
     R.VectorElts = Elts;
+    SetQualifiers(Qualifiers,R);
     return R;
   }
 
   static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit,
-                             unsigned short Size, bool IsSigned) {
+                             unsigned short Size, bool IsSigned,
+                             unsigned Qualifiers) {
     LValue R;
     R.LVType = BitField;
     R.V = V;
     R.BitfieldData.StartBit = StartBit;
     R.BitfieldData.Size = Size;
     R.BitfieldData.IsSigned = IsSigned;
+    SetQualifiers(Qualifiers,R);
     return R;
   }
 };
@@ -440,7 +460,7 @@
   LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
 
   LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field,
-                            bool isUnion);
+                            bool isUnion, unsigned CVRQualifiers);
       
   LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E);
   //===--------------------------------------------------------------------===//