[PATCH] D17462: Fix a codegen bug for variadic functions with pass_object_size params
George Burgess IV via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 19 12:59:04 PST 2016
george.burgess.iv created this revision.
george.burgess.iv added a reviewer: rsmith.
george.burgess.iv added subscribers: srhines, cfe-commits.
Currently, we get assertion failures/segfaults for variadic functions with `pass_object_size` params, e.g.:
```
void foo(void *const __attribute__((pass_object_size(0))) a, ...) {}
```
This is because we didn't consider the parameter injected by `pass_object_size` "required" when generating the `CGFunctionInfo` for `foo`. This patch teaches clang that said injected params are required.
(N.B. Only one user of `appendParameterTypes` is patched here because the other user, `arrangeCXXStructorDeclaration`, considers all args to be required).
http://reviews.llvm.org/D17462
Files:
lib/CodeGen/CGCall.cpp
test/CodeGen/pass-object-size.c
Index: test/CodeGen/pass-object-size.c
===================================================================
--- test/CodeGen/pass-object-size.c
+++ test/CodeGen/pass-object-size.c
@@ -351,3 +351,18 @@
ObjectSize0(++p);
ObjectSize0(p++);
}
+
+// There was a bug where variadic functions with pass_object_size would cause
+// problems in the form of failed assertions.
+void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {}
+
+// CHECK-LABEL: define void @test14
+void test14(char *c) {
+ // CHECK: @llvm.objectsize
+ // CHECK: call void (i8*, i64, ...) @my_sprintf
+ my_sprintf(c);
+
+ // CHECK: @llvm.objectsize
+ // CHECK: call void (i8*, i64, ...) @my_sprintf
+ my_sprintf(c, 1, 2, 3);
+}
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -96,27 +96,36 @@
/// Adds the formal paramaters in FPT to the given prefix. If any parameter in
/// FPT has pass_object_size attrs, then we'll add parameters for those, too.
+///
+/// If NumSynthesizedParams is non-null, the number of pass_object_size
+/// parameters that we encounter will be stored in it.
static void appendParameterTypes(const CodeGenTypes &CGT,
SmallVectorImpl<CanQualType> &prefix,
const CanQual<FunctionProtoType> &FPT,
- const FunctionDecl *FD) {
- // Fast path: unknown target.
- if (FD == nullptr) {
+ const FunctionDecl *FD,
+ unsigned *NumSynthesizedParams = nullptr) {
+ unsigned NumPassObjSizeParams = 0;
+ if (!FD) {
+ // Fast path: unknown target.
prefix.append(FPT->param_type_begin(), FPT->param_type_end());
- return;
+ } else {
+ // In the vast majority of cases, we'll have precisely FPT->getNumParams()
+ // parameters; the only thing that can change this is the presence of
+ // pass_object_size. So, we preallocate for the common case.
+ prefix.reserve(prefix.size() + FPT->getNumParams());
+
+ assert(FD->getNumParams() == FPT->getNumParams());
+ for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) {
+ prefix.push_back(FPT->getParamType(I));
+ if (FD->getParamDecl(I)->hasAttr<PassObjectSizeAttr>()) {
+ ++NumPassObjSizeParams;
+ prefix.push_back(CGT.getContext().getSizeType());
+ }
+ }
}
- // In the vast majority cases, we'll have precisely FPT->getNumParams()
- // parameters; the only thing that can change this is the presence of
- // pass_object_size. So, we preallocate for the common case.
- prefix.reserve(prefix.size() + FPT->getNumParams());
-
- assert(FD->getNumParams() == FPT->getNumParams());
- for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) {
- prefix.push_back(FPT->getParamType(I));
- if (FD->getParamDecl(I)->hasAttr<PassObjectSizeAttr>())
- prefix.push_back(CGT.getContext().getSizeType());
- }
+ if (NumSynthesizedParams)
+ *NumSynthesizedParams = NumPassObjSizeParams;
}
/// Arrange the LLVM function layout for a value of the given function
@@ -126,13 +135,16 @@
SmallVectorImpl<CanQualType> &prefix,
CanQual<FunctionProtoType> FTP,
const FunctionDecl *FD) {
- RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size());
+ unsigned StartParams = prefix.size();
+ unsigned SynthesizedParams;
// FIXME: Kill copy.
- appendParameterTypes(CGT, prefix, FTP, FD);
+ appendParameterTypes(CGT, prefix, FTP, FD, &SynthesizedParams);
+ RequiredArgs Required =
+ RequiredArgs::forPrototypePlus(FTP, StartParams + SynthesizedParams);
CanQualType resultType = FTP->getReturnType().getUnqualifiedType();
return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod,
/*chainCall=*/false, prefix,
- FTP->getExtInfo(), required);
+ FTP->getExtInfo(), Required);
}
/// Arrange the argument and result information for a value of the
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D17462.48538.patch
Type: text/x-patch
Size: 4171 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160219/d8df25bd/attachment.bin>
More information about the cfe-commits
mailing list