[cfe-commits] r167779 - /cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon Nov 12 15:33:00 PST 2012


Author: rsmith
Date: Mon Nov 12 17:33:00 2012
New Revision: 167779

URL: http://llvm.org/viewvc/llvm-project?rev=167779&view=rev
Log:
Factor duplicated implicit memcpy call generation code out of copy/move
assignment generation. This incidentally avoids reusing the same Expr* across
multiple statements in the same object; that was generating slightly broken
ASTs, but I couldn't trigger any observable bad behavior, so no test.

Modified:
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=167779&r1=167778&r2=167779&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Nov 12 17:33:00 2012
@@ -7439,10 +7439,72 @@
 ///
 /// \returns A statement or a loop that copies the expressions.
 static StmtResult
-BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, 
+BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
                       Expr *To, Expr *From,
                       bool CopyingBaseSubobject, bool Copying,
                       unsigned Depth = 0) {
+  // If the field should be copied with __builtin_memcpy rather than via
+  // explicit assignments, do so. This optimization only applies for arrays
+  // of scalars and arrays of class type with trivial copy-assignment
+  // operators.
+  QualType BaseType = S.Context.getBaseElementType(T);
+  if (T->isArrayType() && !T.isVolatileQualified()
+      && BaseType.hasTrivialAssignment(S.Context, Copying)) {
+    // Compute the size of the memory buffer to be copied.
+    QualType SizeType = S.Context.getSizeType();
+    llvm::APInt Size(S.Context.getTypeSize(SizeType),
+                     S.Context.getTypeSizeInChars(BaseType).getQuantity());
+    for (const ConstantArrayType *Array
+            = S.Context.getAsConstantArrayType(T);
+         Array;
+         Array = S.Context.getAsConstantArrayType(Array->getElementType())) {
+      llvm::APInt ArraySize
+        = Array->getSize().zextOrTrunc(Size.getBitWidth());
+      Size *= ArraySize;
+    }
+
+    // Take the address of the field references for "from" and "to". We
+    // directly construct UnaryOperators here because semantic analysis
+    // does not permit us to take the address of an xvalue.
+    From = new (S.Context) UnaryOperator(From, UO_AddrOf,
+                           S.Context.getPointerType(From->getType()),
+                           VK_RValue, OK_Ordinary, Loc);
+    To = new (S.Context) UnaryOperator(To, UO_AddrOf,
+                         S.Context.getPointerType(To->getType()),
+                         VK_RValue, OK_Ordinary, Loc);
+
+    bool NeedsCollectableMemCpy =
+        (BaseType->isRecordType() &&
+         BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
+
+    // Create a reference to the __builtin_objc_memmove_collectable function
+    StringRef MemCpyName = NeedsCollectableMemCpy ?
+        "__builtin_objc_memmove_collectable" :
+        "__builtin_memcpy";
+    LookupResult R(S, &S.Context.Idents.get(MemCpyName), Loc,
+                   Sema::LookupOrdinaryName);
+    S.LookupName(R, S.TUScope, true);
+
+    FunctionDecl *MemCpy = R.getAsSingle<FunctionDecl>();
+    if (!MemCpy)
+      // Something went horribly wrong earlier, and we will have complained
+      // about it.
+      return StmtError();
+
+    ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy,
+                                              VK_RValue, Loc, 0);
+    assert(MemCpyRef.isUsable() && "Builtin reference cannot fail");
+
+    Expr *CallArgs[] = {
+      To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc)
+    };
+    ExprResult Call = S.ActOnCallExpr(/*Scope=*/0, MemCpyRef.take(),
+                                      Loc, CallArgs, Loc);
+
+    assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
+    return S.Owned(Call.takeAs<Stmt>());
+  }
+
   // C++0x [class.copy]p28:
   //   Each subobject is assigned in the manner appropriate to its type:
   //
@@ -7461,6 +7523,8 @@
     S.LookupQualifiedName(OpLookup, ClassDecl, false);
     
     // Filter out any result that isn't a copy/move-assignment operator.
+    // FIXME: This is wrong in C++11. We should perform overload resolution
+    //        instead here.
     LookupResult::Filter F = OpLookup.makeFilter();
     while (F.hasNext()) {
       NamedDecl *D = F.next();
@@ -7521,6 +7585,7 @@
     if (Call.isInvalid())
       return StmtError();
     
+    // FIXME: ActOnFinishFullExpr, ActOnExprStmt.
     return S.Owned(Call.takeAs<Stmt>());
   }
 
@@ -7907,11 +7972,6 @@
     Statements.push_back(Copy.takeAs<Expr>());
   }
   
-  // \brief Reference to the __builtin_memcpy function.
-  Expr *BuiltinMemCpyRef = 0;
-  // \brief Reference to the __builtin_objc_memmove_collectable function.
-  Expr *CollectableMemCpyRef = 0;
-  
   // Assign non-static members.
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
                                   FieldEnd = ClassDecl->field_end(); 
@@ -7969,99 +8029,9 @@
                                              MemberLookup, 0);
     assert(!From.isInvalid() && "Implicit field reference cannot fail");
     assert(!To.isInvalid() && "Implicit field reference cannot fail");
-    
-    // If the field should be copied with __builtin_memcpy rather than via
-    // explicit assignments, do so. This optimization only applies for arrays 
-    // of scalars and arrays of class type with trivial copy-assignment 
-    // operators.
-    if (FieldType->isArrayType() && !FieldType.isVolatileQualified()
-        && BaseType.hasTrivialAssignment(Context, /*Copying=*/true)) {
-      // Compute the size of the memory buffer to be copied.
-      QualType SizeType = Context.getSizeType();
-      llvm::APInt Size(Context.getTypeSize(SizeType), 
-                       Context.getTypeSizeInChars(BaseType).getQuantity());
-      for (const ConstantArrayType *Array
-              = Context.getAsConstantArrayType(FieldType);
-           Array; 
-           Array = Context.getAsConstantArrayType(Array->getElementType())) {
-        llvm::APInt ArraySize
-          = Array->getSize().zextOrTrunc(Size.getBitWidth());
-        Size *= ArraySize;
-      }
-          
-      // Take the address of the field references for "from" and "to".
-      From = CreateBuiltinUnaryOp(Loc, UO_AddrOf, From.get());
-      To = CreateBuiltinUnaryOp(Loc, UO_AddrOf, To.get());
-          
-      bool NeedsCollectableMemCpy = 
-          (BaseType->isRecordType() && 
-           BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
-          
-      if (NeedsCollectableMemCpy) {
-        if (!CollectableMemCpyRef) {
-          // Create a reference to the __builtin_objc_memmove_collectable function.
-          LookupResult R(*this, 
-                         &Context.Idents.get("__builtin_objc_memmove_collectable"), 
-                         Loc, LookupOrdinaryName);
-          LookupName(R, TUScope, true);
-        
-          FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>();
-          if (!CollectableMemCpy) {
-            // Something went horribly wrong earlier, and we will have 
-            // complained about it.
-            Invalid = true;
-            continue;
-          }
-        
-          CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, 
-                                                  Context.BuiltinFnTy,
-                                                  VK_RValue, Loc, 0).take();
-          assert(CollectableMemCpyRef && "Builtin reference cannot fail");
-        }
-      }
-      // Create a reference to the __builtin_memcpy builtin function.
-      else if (!BuiltinMemCpyRef) {
-        LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc,
-                       LookupOrdinaryName);
-        LookupName(R, TUScope, true);
-        
-        FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>();
-        if (!BuiltinMemCpy) {
-          // Something went horribly wrong earlier, and we will have complained
-          // about it.
-          Invalid = true;
-          continue;
-        }
 
-        BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, 
-                                            Context.BuiltinFnTy,
-                                            VK_RValue, Loc, 0).take();
-        assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
-      }
-          
-      SmallVector<Expr*, 8> CallArgs;
-      CallArgs.push_back(To.takeAs<Expr>());
-      CallArgs.push_back(From.takeAs<Expr>());
-      CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc));
-      ExprResult Call = ExprError();
-      if (NeedsCollectableMemCpy)
-        Call = ActOnCallExpr(/*Scope=*/0,
-                             CollectableMemCpyRef,
-                             Loc, CallArgs,
-                             Loc);
-      else
-        Call = ActOnCallExpr(/*Scope=*/0,
-                             BuiltinMemCpyRef,
-                             Loc, CallArgs,
-                             Loc);
-          
-      assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
-      Statements.push_back(Call.takeAs<Expr>());
-      continue;
-    }
-    
     // Build the copy of this field.
-    StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType, 
+    StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType,
                                             To.get(), From.get(),
                                             /*CopyingBaseSubobject=*/false,
                                             /*Copying=*/true);
@@ -8446,11 +8416,6 @@
     Statements.push_back(Move.takeAs<Expr>());
   }
 
-  // \brief Reference to the __builtin_memcpy function.
-  Expr *BuiltinMemCpyRef = 0;
-  // \brief Reference to the __builtin_objc_memmove_collectable function.
-  Expr *CollectableMemCpyRef = 0;
-
   // Assign non-static members.
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
                                   FieldEnd = ClassDecl->field_end(); 
@@ -8513,104 +8478,8 @@
         "Member reference with rvalue base must be rvalue except for reference "
         "members, which aren't allowed for move assignment.");
 
-    // If the field should be copied with __builtin_memcpy rather than via
-    // explicit assignments, do so. This optimization only applies for arrays 
-    // of scalars and arrays of class type with trivial move-assignment 
-    // operators.
-    if (FieldType->isArrayType() && !FieldType.isVolatileQualified()
-        && BaseType.hasTrivialAssignment(Context, /*Copying=*/false)) {
-      // Compute the size of the memory buffer to be copied.
-      QualType SizeType = Context.getSizeType();
-      llvm::APInt Size(Context.getTypeSize(SizeType), 
-                       Context.getTypeSizeInChars(BaseType).getQuantity());
-      for (const ConstantArrayType *Array
-              = Context.getAsConstantArrayType(FieldType);
-           Array; 
-           Array = Context.getAsConstantArrayType(Array->getElementType())) {
-        llvm::APInt ArraySize
-          = Array->getSize().zextOrTrunc(Size.getBitWidth());
-        Size *= ArraySize;
-      }
-
-      // Take the address of the field references for "from" and "to". We
-      // directly construct UnaryOperators here because semantic analysis
-      // does not permit us to take the address of an xvalue.
-      From = new (Context) UnaryOperator(From.get(), UO_AddrOf,
-                             Context.getPointerType(From.get()->getType()),
-                             VK_RValue, OK_Ordinary, Loc);
-      To = new (Context) UnaryOperator(To.get(), UO_AddrOf,
-                           Context.getPointerType(To.get()->getType()),
-                           VK_RValue, OK_Ordinary, Loc);
-          
-      bool NeedsCollectableMemCpy = 
-          (BaseType->isRecordType() && 
-           BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
-          
-      if (NeedsCollectableMemCpy) {
-        if (!CollectableMemCpyRef) {
-          // Create a reference to the __builtin_objc_memmove_collectable function.
-          LookupResult R(*this, 
-                         &Context.Idents.get("__builtin_objc_memmove_collectable"), 
-                         Loc, LookupOrdinaryName);
-          LookupName(R, TUScope, true);
-        
-          FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>();
-          if (!CollectableMemCpy) {
-            // Something went horribly wrong earlier, and we will have 
-            // complained about it.
-            Invalid = true;
-            continue;
-          }
-        
-          CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, 
-                                                  Context.BuiltinFnTy,
-                                                  VK_RValue, Loc, 0).take();
-          assert(CollectableMemCpyRef && "Builtin reference cannot fail");
-        }
-      }
-      // Create a reference to the __builtin_memcpy builtin function.
-      else if (!BuiltinMemCpyRef) {
-        LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc,
-                       LookupOrdinaryName);
-        LookupName(R, TUScope, true);
-        
-        FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>();
-        if (!BuiltinMemCpy) {
-          // Something went horribly wrong earlier, and we will have complained
-          // about it.
-          Invalid = true;
-          continue;
-        }
-
-        BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, 
-                                            Context.BuiltinFnTy,
-                                            VK_RValue, Loc, 0).take();
-        assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
-      }
-          
-      SmallVector<Expr*, 8> CallArgs;
-      CallArgs.push_back(To.takeAs<Expr>());
-      CallArgs.push_back(From.takeAs<Expr>());
-      CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc));
-      ExprResult Call = ExprError();
-      if (NeedsCollectableMemCpy)
-        Call = ActOnCallExpr(/*Scope=*/0,
-                             CollectableMemCpyRef,
-                             Loc, CallArgs,
-                             Loc);
-      else
-        Call = ActOnCallExpr(/*Scope=*/0,
-                             BuiltinMemCpyRef,
-                             Loc, CallArgs,
-                             Loc);
-          
-      assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
-      Statements.push_back(Call.takeAs<Expr>());
-      continue;
-    }
-    
     // Build the move of this field.
-    StmtResult Move = BuildSingleCopyAssign(*this, Loc, FieldType, 
+    StmtResult Move = BuildSingleCopyAssign(*this, Loc, FieldType,
                                             To.get(), From.get(),
                                             /*CopyingBaseSubobject=*/false,
                                             /*Copying=*/false);
@@ -8620,7 +8489,7 @@
       MoveAssignOperator->setInvalidDecl();
       return;
     }
-    
+
     // Success! Record the copy.
     Statements.push_back(Move.takeAs<Stmt>());
   }





More information about the cfe-commits mailing list