From 4688e608612d9582e150815f39a2b6a5d60596fd Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Mon, 25 Jun 2012 20:48:28 +0000 Subject: [PATCH] [analyzer] Be careful about implicitly-declared operator new/delete. (PR13090) The implicit global allocation functions do not have valid source locations, but we still want to treat them as being "system header" functions for the purposes of how they affect program state. llvm-svn: 159160 --- .../Core/PathSensitive/ObjCMessage.h | 10 ++++++++-- .../lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 3 +-- clang/test/Analysis/new.cpp | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h index f01bad02c203..8fc4050c7e08 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h @@ -199,10 +199,16 @@ public: /// Check if the callee is declared in the system header. bool isInSystemHeader() const { - if (const Decl *FD = getDecl()) { + if (const Decl *D = getDecl()) { const SourceManager &SM = State->getStateManager().getContext().getSourceManager(); - return SM.isInSystemHeader(FD->getLocation()); + SourceLocation Loc = D->getLocation(); + // Be careful: the implicit declarations of operator new/delete have + // invalid source locations but should still count as system files. + if (Loc.isValid()) + return SM.isInSystemHeader(D->getLocation()); + else if (const FunctionDecl *FD = dyn_cast(D)) + return FD->isOverloadedOperator() && FD->isImplicit() && FD->isGlobal(); } return false; } diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 50d4273e48c0..1aa9b824e306 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -1338,8 +1338,7 @@ bool MallocChecker::doesNotFreeMemory(const CallOrObjCMessage *Call, } // If it's not a system call, assume it frees memory. - SourceManager &SM = ASTC.getSourceManager(); - if (!SM.isInSystemHeader(D->getLocation())) + if (!Call->isInSystemHeader()) return false; // Process C/ObjC functions. diff --git a/clang/test/Analysis/new.cpp b/clang/test/Analysis/new.cpp index 8093eff3a1c2..723d033bc794 100644 --- a/clang/test/Analysis/new.cpp +++ b/clang/test/Analysis/new.cpp @@ -5,6 +5,21 @@ void clang_analyzer_eval(bool); typedef typeof(sizeof(int)) size_t; extern "C" void *malloc(size_t); +int someGlobal; +void testImplicitlyDeclaredGlobalNew() { + if (someGlobal != 0) + return; + + // This used to crash because the global operator new is being implicitly + // declared and it does not have a valid source location. (PR13090) + void *x = ::operator new(0); + ::operator delete(x); + + // Check that the new/delete did not invalidate someGlobal; + clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}} +} + + // This is the standard placement new. inline void* operator new(size_t, void* __p) throw() {