================
@@ -1165,7 +1165,103 @@ void
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
unsigned BuiltinID = UseDecl->getBuiltinID(/*ConsiderWrappers=*/true);
- if (!BuiltinID)
+ // Some libc I/O functions are intentionally not Clang builtins:
+ // * "read", "write", "readlink", "readlinkat", and "getcwd" are common
+ // identifiers (or names that appear in asm-label wrappers); declaring
+ // them as builtins triggers -Wincompatible-library-redeclaration on
+ // harmless local declarations (an error under -Werror).
+ // * pread/pwrite prototypes use off_t, whose width is platform- and
+ // macro-dependent (notably _FILE_OFFSET_BITS); a fixed builtin signature
+ // would clash with the system header on some targets.
+ // Recognize them by name, but only after checking the full POSIX prototype
+ // so that an unrelated function happening to share the name is not
+ // diagnosed as if it were the libc function.
+ struct LibcFuncDesc {
+ StringRef Name;
+ QualType Return;
+ SmallVector<QualType, 4> Params;
+ std::optional<unsigned> SourceSizeIdx; // __bos buffer; reads from
+ std::optional<unsigned> MaxOpSizeIdx; // count arg (constant-evaluated)
+ std::optional<unsigned> DestSizeIdx; // __bos buffer; writes to
+ };
+
+ std::optional<LibcFuncDesc> LibCMatch;
+ if (!BuiltinID && FD->isExternC() && FD->getIdentifier() &&
+ !FD->isVariadic()) {
+ ASTContext &Ctx = getASTContext();
+ QualType IntTy = Ctx.IntTy;
+ QualType SizeTy = Ctx.getSizeType();
+ QualType VoidPtrTy = Ctx.VoidPtrTy;
+ QualType ConstVoidPtrTy = Ctx.getPointerType(Ctx.VoidTy.withConst());
+ QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
+ QualType ConstCharPtrTy = Ctx.getPointerType(Ctx.CharTy.withConst());
+ // ssize_t / off_t / off64_t aren't single Clang types (ssize_t differs
+ // across libcs, off_t depends on _FILE_OFFSET_BITS, off64_t is always
+ // 64-bit). The name match has already pinned us to POSIX intent, so
+ // MatchSlot below treats any integer-typed slot as compatible with any
+ // integer-typed argument; these aliases just keep the table readable.
+ QualType SSizeTy = IntTy;
+ QualType OffTy = IntTy;
+ QualType Off64Ty = IntTy;
+
+ // Same unqualified type, or both integer types: accepts libc typedef
+ // divergence (ssize_t/off_t/off64_t) while still rejecting pointer or
+ // aggregate mismatches.
+ auto MatchSlot = [&](QualType Expected, QualType Actual) {
+ if (Ctx.hasSameUnqualifiedType(Expected, Actual))
+ return true;
+ return Expected->isIntegerType() && Actual->isIntegerType();
+ };
+
+ auto Make = [](StringRef Name, QualType Ret,
+ std::initializer_list<QualType> Params,
+ std::optional<unsigned> Src, std::optional<unsigned> MaxOp,
+ std::optional<unsigned> Dest) {
+ return LibcFuncDesc{Name, Ret, Params, Src, MaxOp, Dest};
+ };
+
+ auto LookupLibc = [&](StringRef Name) -> std::optional<LibcFuncDesc> {
+ if (Name == "getcwd")
+ return Make(Name, CharPtrTy, {CharPtrTy, SizeTy}, std::nullopt, 1, 0);
+ if (Name == "read")
+ return Make(Name, SSizeTy, {IntTy, VoidPtrTy, SizeTy}, std::nullopt, 2,
+ 1);
----------------
nuclearcat wrote:
replaced the LibCDispatch enum + switch with a table-driven approach
https://github.com/llvm/llvm-project/pull/196499
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits