]> granicus.if.org Git - clang/commitdiff
Fix a bunch of really nasty bugs in how we compute alignment for reference lvalues...
authorEli Friedman <eli.friedman@gmail.com>
Wed, 16 Nov 2011 00:42:57 +0000 (00:42 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 16 Nov 2011 00:42:57 +0000 (00:42 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144745 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExpr.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/references.cpp

index 0b6195dc79b8fdf5fc01ba376e4310ba31364c93..a35bb5f7118f0ba3b315c423e949edc9b0d22bed 100644 (file)
@@ -1319,14 +1319,19 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
          "Var decl must have external storage or be a file var decl!");
 
   llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD);
-  if (VD->getType()->isReferenceType())
-    V = CGF.Builder.CreateLoad(V);
-  
-  V = EmitBitCastOfLValueToProperType(CGF, V,
-                                CGF.getTypes().ConvertTypeForMem(E->getType()));
-
+  llvm::Type *RealVarTy = CGF.getTypes().ConvertTypeForMem(VD->getType());
+  V = EmitBitCastOfLValueToProperType(CGF, V, RealVarTy);
   unsigned Alignment = CGF.getContext().getDeclAlign(VD).getQuantity();
-  LValue LV = CGF.MakeAddrLValue(V, E->getType(), Alignment);
+  QualType T = E->getType();
+  LValue LV;
+  if (VD->getType()->isReferenceType()) {
+    llvm::LoadInst *LI = CGF.Builder.CreateLoad(V);
+    LI->setAlignment(Alignment);
+    V = LI;
+    LV = CGF.MakeNaturalAlignAddrLValue(V, T);
+  } else {
+    LV = CGF.MakeAddrLValue(V, E->getType(), Alignment);
+  }
   setObjCGCLValueClass(CGF.getContext(), E, LV);
   return LV;
 }
@@ -1353,6 +1358,7 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
 LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
   const NamedDecl *ND = E->getDecl();
   unsigned Alignment = getContext().getDeclAlign(ND).getQuantity();
+  QualType T = E->getType();
 
   if (ND->hasAttr<WeakRefAttr>()) {
     const ValueDecl *VD = cast<ValueDecl>(ND);
@@ -1377,14 +1383,17 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
 
     if (VD->hasAttr<BlocksAttr>())
       V = BuildBlockByrefAddress(V, VD);
-    
-    if (VD->getType()->isReferenceType())
-      V = Builder.CreateLoad(V);
 
-    V = EmitBitCastOfLValueToProperType(*this, V,
-                                    getTypes().ConvertTypeForMem(E->getType()));
+    LValue LV;
+    if (VD->getType()->isReferenceType()) {
+      llvm::LoadInst *LI = Builder.CreateLoad(V);
+      LI->setAlignment(Alignment);
+      V = LI;
+      LV = MakeNaturalAlignAddrLValue(V, T);
+    } else {
+      LV = MakeAddrLValue(V, T, Alignment);
+    }
 
-    LValue LV = MakeAddrLValue(V, E->getType(), Alignment);
     if (NonGCable) {
       LV.getQuals().removeObjCGCAttr();
       LV.setNonGC(true);
@@ -1843,6 +1852,7 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
 
   const RecordDecl *rec = field->getParent();
   QualType type = field->getType();
+  unsigned alignment = getContext().getDeclAlign(field).getQuantity();
 
   bool mayAlias = rec->hasAttr<MayAliasAttr>();
 
@@ -1859,6 +1869,7 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
     if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
       llvm::LoadInst *load = Builder.CreateLoad(addr, "ref");
       if (cvr & Qualifiers::Volatile) load->setVolatile(true);
+      load->setAlignment(alignment);
 
       if (CGM.shouldUseTBAA()) {
         llvm::MDNode *tbaa;
@@ -1872,6 +1883,10 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
       addr = load;
       mayAlias = false;
       type = refType->getPointeeType();
+      if (type->isIncompleteType())
+        alignment = 0;
+      else
+        alignment = getContext().getTypeAlignInChars(type).getQuantity();
       cvr = 0; // qualifiers don't recursively apply to referencee
     }
   }
@@ -1887,7 +1902,6 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
   if (field->hasAttr<AnnotateAttr>())
     addr = EmitFieldAnnotations(field, addr);
 
-  unsigned alignment = getContext().getDeclAlign(field).getQuantity();
   LValue LV = MakeAddrLValue(addr, type, alignment);
   LV.getQuals().addCVRQualifiers(cvr);
 
index 09b8b2b373a786e4357b93d5b1f4d311089fa66c..740a13e122b291465e41cddeae52b928b85449ba 100644 (file)
@@ -1541,6 +1541,15 @@ public:
     return LValue::MakeAddr(V, T, Alignment, getContext(),
                             CGM.getTBAAInfo(T));
   }
+  LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
+    unsigned Alignment;
+    if (T->isIncompleteType())
+      Alignment = 0;
+    else
+      Alignment = getContext().getTypeAlignInChars(T).getQuantity();
+    return LValue::MakeAddr(V, T, Alignment, getContext(),
+                            CGM.getTBAAInfo(T));
+  }
 
   /// CreateTempAlloca - This creates a alloca and inserts it into the entry
   /// block. The caller is responsible for setting an appropriate alignment on
index 4bbc251ab5d05c598f1f4ebf393be21a09de2f83..505f41893f715f64ec74f8ef3b268b8a6e19f544 100644 (file)
@@ -1,10 +1,16 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin -verify -emit-llvm -o - %s | FileCheck %s
 void t1() {
+  // CHECK: define void @_Z2t1v
+  // CHECK: [[REFLOAD:%.*]] = load i32** @a, align 8
+  // CHECK: load i32* [[REFLOAD]], align 4
   extern int& a;
   int b = a; 
 }
 
 void t2(int& a) {
+  // CHECK: define void @_Z2t2Ri
+  // CHECK: [[REFLOAD2:%.*]] = load i32** {{.*}}, align 8
+  // CHECK: load i32* [[REFLOAD2]], align 4
   int b = a;
 }
 
@@ -297,3 +303,11 @@ namespace PR9565 {
     // CHECK-NEXT: ret void
   }
 }
+
+namespace N6 {
+  extern struct x {char& x;}y;
+  int a() { return y.x; }
+  // CHECK: define i32 @_ZN2N61aEv
+  // CHECK: [[REFLOAD3:%.*]] = load i8** getelementptr inbounds (%"struct.N6::x"* @_ZN2N61yE, i32 0, i32 0), align 8
+  // CHECK: %0 = load i8* [[REFLOAD3]], align 1
+}