From ac7583ae2b142a8e95a2150ef5f702eea6fee827 Mon Sep 17 00:00:00 2001 From: Devin Coughlin Date: Sat, 17 Dec 2016 01:08:17 +0000 Subject: [PATCH] [analyzer] UnixAPIChecker: Don't diagnose for functions in C++ namespaces Update the UnixAPIChecker to not diagnose for calls to functions that are declared in C++ namespaces. This avoids false positives when a namespaced function has the same name as a Unix API. This address PR28331. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@290023 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/UnixAPIChecker.cpp | 6 ++ test/Analysis/unix-api.cpp | 62 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 test/Analysis/unix-api.cpp diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 0945bbf09f..26bf597bd9 100644 --- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -427,6 +427,12 @@ void UnixAPIChecker::checkPreStmt(const CallExpr *CE, if (!FD || FD->getKind() != Decl::Function) return; + // Don't treat functions in namespaces with the same name a Unix function + // as a call to the Unix function. + const DeclContext *NamespaceCtx = FD->getEnclosingNamespaceContext(); + if (NamespaceCtx && isa(NamespaceCtx)) + return; + StringRef FName = C.getCalleeName(FD); if (FName.empty()) return; diff --git a/test/Analysis/unix-api.cpp b/test/Analysis/unix-api.cpp new file mode 100644 index 0000000000..1c8f99632c --- /dev/null +++ b/test/Analysis/unix-api.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.API -verify %s +extern "C" { +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif + +#ifndef NULL +#define NULL ((void*) 0) +#endif + +int open(const char *, int, ...); +int close(int fildes); + +} // extern "C" + +namespace MyNameSpace { +int open(const char *a, int b, int c, int d); +} + +void unix_open(const char *path) { + int fd; + fd = open(path, O_RDONLY); // no-warning + if (fd > -1) + close(fd); +} + +void unix_open_misuse(const char *path) { + int fd; + int mode = 0x0; + fd = open(path, O_RDONLY, mode, NULL); // expected-warning{{Call to 'open' with more than 3 arguments}} + if (fd > -1) + close(fd); +} + +// Don't treat open() in namespaces as the POSIX open() +void namespaced_open(const char *path) { + MyNameSpace::open("Hi", 2, 3, 4); // no-warning + + using namespace MyNameSpace; + + open("Hi", 2, 3, 4); // no-warning + + int fd; + int mode = 0x0; + fd = ::open(path, O_RDONLY, mode, NULL); // expected-warning{{Call to 'open' with more than 3 arguments}} + if (fd > -1) + close(fd); +} + +class MyClass { +public: + static int open(const char *a, int b, int c, int d); + + int open(int a, int, int c, int d); +}; + +void class_qualified_open() { + MyClass::open("Hi", 2, 3, 4); // no-warning + + MyClass mc; + mc.open(1, 2, 3, 4); // no-warning +} -- 2.40.0