]> granicus.if.org Git - clang/commitdiff
Don't apply NRVO to over-aligned variables. The caller only
authorJohn McCall <rjmccall@apple.com>
Fri, 11 Nov 2011 03:57:31 +0000 (03:57 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 11 Nov 2011 03:57:31 +0000 (03:57 +0000)
guarantees alignment up to the ABI alignment of the return type.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144364 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaStmt.cpp
test/CodeGenCXX/nrvo.cpp

index a34d83812f61972c94fd36d2d87f9cddec98cc19..a424a8a1b0e1bcbfd13989a30fa3022d03471790 100644 (file)
@@ -18,6 +18,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/AST/APValue.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
@@ -1650,14 +1651,29 @@ const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType,
   if (!VD)
     return 0;
 
-  if (VD->hasLocalStorage() && !VD->isExceptionVariable() &&
-      !VD->getType()->isReferenceType() && !VD->hasAttr<BlocksAttr>() &&
-      !VD->getType().isVolatileQualified() &&
-      ((VD->getKind() == Decl::Var) ||
-       (AllowFunctionParameter && VD->getKind() == Decl::ParmVar)))
-    return VD;
+  // ...object (other than a function or catch-clause parameter)...
+  if (VD->getKind() != Decl::Var &&
+      !(AllowFunctionParameter && VD->getKind() == Decl::ParmVar))
+    return 0;
+  if (VD->isExceptionVariable()) return 0;
+
+  // ...automatic...
+  if (!VD->hasLocalStorage()) return 0;
+
+  // ...non-volatile...
+  if (VD->getType().isVolatileQualified()) return 0;
+  if (VD->getType()->isReferenceType()) return 0;
+
+  // __block variables can't be allocated in a way that permits NRVO.
+  if (VD->hasAttr<BlocksAttr>()) return 0;
+
+  // Variables with higher required alignment than their type's ABI
+  // alignment cannot use NRVO.
+  if (VD->hasAttr<AlignedAttr>() &&
+      Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType()))
+    return 0;
 
-  return 0;
+  return VD;
 }
 
 /// \brief Perform the initialization of a potentially-movable value, which
index 57bf27ab7aff98a582c7fa5318ca949afba7f42d..4a117f1df09ba4f8a6aa488e0ba8cadb117a709c 100644 (file)
@@ -147,3 +147,15 @@ X test5() {
   }
 }
 #endif
+
+// rdar://problem/10430868
+// CHECK: define void @_Z5test6v
+X test6() {
+  X a __attribute__((aligned(8)));
+  return a;
+  // CHECK:      [[A:%.*]] = alloca [[X:%.*]], align 8
+  // CHECK-NEXT: call void @_ZN1XC1Ev([[X]]* [[A]])
+  // CHECK-NEXT: call void @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* [[A]])
+  // CHECK-NEXT: call void @_ZN1XD1Ev([[X]]* [[A]])
+  // CHECK-NEXT: ret void
+}