https://github.com/Aadhu23 updated https://github.com/llvm/llvm-project/pull/226207
>From ff729b39e00948fb77e51a47f3a35bd3cb4a4477 Mon Sep 17 00:00:00 2001 From: Aadhu23 <[email protected]> Date: Thu, 24 Sep 2026 04:37:55 +0530 Subject: [PATCH] [InferAttrs] Avoid conflicting argument memory attributes --- clang/test/CodeGen/inferattrs-const-variadic.c | 6 ++++++ llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 14 ++++++++++++-- .../argument-memory-attributes.ll | 10 ++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGen/inferattrs-const-variadic.c create mode 100644 llvm/test/Transforms/InferFunctionAttrs/argument-memory-attributes.ll diff --git a/clang/test/CodeGen/inferattrs-const-variadic.c b/clang/test/CodeGen/inferattrs-const-variadic.c new file mode 100644 index 00000000000000..fffeb0c9b1ec80 --- /dev/null +++ b/clang/test/CodeGen/inferattrs-const-variadic.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -O1 -triple x86_64-unknown-linux-gnu -emit-llvm -o /dev/null -verify %s +// expected-no-diagnostics + +int __attribute__((const)) snprintf(char *, __SIZE_TYPE__, const char *, ...); + +long foo(char c, long d) { return snprintf(&c, d, ""); } diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index fa61a18de15de3..2b70a0dbf0d231 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -205,7 +205,13 @@ static bool setDoesNotSync(Function &F) { } static bool setOnlyReadsMemory(Function &F, unsigned ArgNo) { - if (F.hasParamAttribute(ArgNo, Attribute::ReadOnly)) + // readnone, readonly, and writeonly are mutually exclusive. In particular, + // a frontend can add readnone to a const variadic function's fixed pointer + // arguments before libcall inference runs. Do not add a conflicting + // inferred attribute. + if (F.hasParamAttribute(ArgNo, Attribute::ReadNone) || + F.hasParamAttribute(ArgNo, Attribute::ReadOnly) || + F.hasParamAttribute(ArgNo, Attribute::WriteOnly)) return false; F.addParamAttr(ArgNo, Attribute::ReadOnly); ++NumReadOnlyArg; @@ -213,7 +219,11 @@ static bool setOnlyReadsMemory(Function &F, unsigned ArgNo) { } static bool setOnlyWritesMemory(Function &F, unsigned ArgNo) { - if (F.hasParamAttribute(ArgNo, Attribute::WriteOnly)) + // See setOnlyReadsMemory above. Preserve an existing access attribute + // rather than creating an invalid combination with an inferred one. + if (F.hasParamAttribute(ArgNo, Attribute::ReadNone) || + F.hasParamAttribute(ArgNo, Attribute::ReadOnly) || + F.hasParamAttribute(ArgNo, Attribute::WriteOnly)) return false; F.addParamAttr(ArgNo, Attribute::WriteOnly); ++NumWriteOnlyArg; diff --git a/llvm/test/Transforms/InferFunctionAttrs/argument-memory-attributes.ll b/llvm/test/Transforms/InferFunctionAttrs/argument-memory-attributes.ll new file mode 100644 index 00000000000000..94b1414cf9153a --- /dev/null +++ b/llvm/test/Transforms/InferFunctionAttrs/argument-memory-attributes.ll @@ -0,0 +1,10 @@ +; RUN: opt -mtriple=x86_64-unknown-linux-gnu -passes=inferattrs,verify -S %s | FileCheck %s + +; A const variadic declaration can already have readnone on its fixed pointer +; arguments. Libcall inference must not add conflicting access attributes. +; CHECK: declare noundef i32 @snprintf(ptr {{.*}}readnone{{.*}}, i64 noundef, ptr {{.*}}readnone{{.*}}, ...) +declare i32 @snprintf(ptr readnone, i64, ptr readnone, ...) + +; The same applies to sprintf, which exercises both inferred access directions. +; CHECK: declare noundef i32 @sprintf(ptr {{.*}}readnone{{.*}}, ptr {{.*}}readnone{{.*}}, ...) +declare i32 @sprintf(ptr readnone, ptr readnone, ...) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
