From 1cd76e8ca8f890a4defadcae3372c025ebe7607c Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 11 Nov 2011 03:57:31 +0000 Subject: [PATCH] Don't apply NRVO to over-aligned variables. The caller only 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 | 30 +++++++++++++++++++++++------- test/CodeGenCXX/nrvo.cpp | 12 ++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index a34d83812f..a424a8a1b0 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -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() && - !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()) return 0; + + // Variables with higher required alignment than their type's ABI + // alignment cannot use NRVO. + if (VD->hasAttr() && + Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType())) + return 0; - return 0; + return VD; } /// \brief Perform the initialization of a potentially-movable value, which diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index 57bf27ab7a..4a117f1df0 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -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 +} -- 2.40.0