aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h10
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp3
-rw-r--r--test/Analysis/new.cpp15
3 files changed, 24 insertions, 4 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
index f01bad02c2..8fc4050c7e 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
+++ b/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<FunctionDecl>(D))
+ return FD->isOverloadedOperator() && FD->isImplicit() && FD->isGlobal();
}
return false;
}
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 50d4273e48..1aa9b824e3 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/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/test/Analysis/new.cpp b/test/Analysis/new.cpp
index 8093eff3a1..723d033bc7 100644
--- a/test/Analysis/new.cpp
+++ b/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()
{