diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-10-20 02:32:51 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-10-20 02:32:51 +0000 |
commit | 3957fd5858e258c340d03a71eb617929a8262b9f (patch) | |
tree | 3a912a668f72629fe0ac37a9ea6190613bdcc128 /clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | |
parent | 8f688177388a1aa20dbce0d76f6ea73b2830f243 (diff) | |
download | bcm5719-llvm-3957fd5858e258c340d03a71eb617929a8262b9f.tar.gz bcm5719-llvm-3957fd5858e258c340d03a71eb617929a8262b9f.zip |
[analyzer] Assume 'new' never returns NULL if it could throw an exception.
This is actually required by the C++ standard in
[basic.stc.dynamic.allocation]p3:
If an allocation function declared with a non-throwing
exception-specification fails to allocate storage, it shall return a
null pointer. Any other allocation function that fails to allocate
storage shall indicate failure only by throwing an exception of a type
that would match a handler of type std::bad_alloc.
We don't bother checking for the specific exception type, but just go off
the operator new prototype. This should help with a certain class of lazy
initalization false positives.
<rdar://problem/12115221>
llvm-svn: 166363
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 60c73c62965..b3baa790578 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -229,6 +229,18 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // we should be using the usual pre-/(default-)eval-/post-call checks here. State = Call->invalidateRegions(blockCount); + // If we're compiling with exceptions enabled, and this allocation function + // is not declared as non-throwing, failures /must/ be signalled by + // exceptions, and thus the return value will never be NULL. + // C++11 [basic.stc.dynamic.allocation]p3. + FunctionDecl *FD = CNE->getOperatorNew(); + if (FD && getContext().getLangOpts().CXXExceptions) { + QualType Ty = FD->getType(); + if (const FunctionProtoType *ProtoType = Ty->getAs<FunctionProtoType>()) + if (!ProtoType->isNothrow(getContext())) + State = State->assume(symVal, true); + } + if (CNE->isArray()) { // FIXME: allocating an array requires simulating the constructors. // For now, just return a symbolicated region. @@ -246,7 +258,6 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // CXXNewExpr, we need to make sure that the constructed object is not // immediately invalidated here. (The placement call should happen before // the constructor call anyway.) - FunctionDecl *FD = CNE->getOperatorNew(); if (FD && FD->isReservedGlobalPlacementOperator()) { // Non-array placement new should always return the placement location. SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); |