Don't apply NRVO to over-aligned variables. The caller only

guarantees alignment up to the ABI alignment of the return type.

llvm-svn: 144364
This commit is contained in:
John McCall 2011-11-11 03:57:31 +00:00
parent f1a3c2aee1
commit 03318c1dcf
2 changed files with 35 additions and 7 deletions

View 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;
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 VD;
}
/// \brief Perform the initialization of a potentially-movable value, which

View 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
}