[analyzer] Just silence all warnings coming out of std::basic_string.

This means always walking the whole call stack for the end path node, but
we'll assume that's always fairly tractable.

<rdar://problem/15952973>

llvm-svn: 200980
This commit is contained in:
Jordan Rose 2014-02-07 17:35:04 +00:00
parent 3d4417c7fd
commit c7d0acaf34
3 changed files with 35 additions and 14 deletions

View File

@ -1558,25 +1558,18 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
// std::u16string s; s += u'a';
// because we cannot reason about the internal invariants of the
// datastructure.
const LocationContext *LCtx = N->getLocationContext();
do {
for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
LCtx = LCtx->getParent()) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
if (!MD)
break;
continue;
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "basic_string") {
BR.markInvalid(getTag(), 0);
return 0;
} else if (CD->getName().find("allocator") == StringRef::npos) {
// Only keep searching if the current method is in a class with the
// word "allocator" in its name, e.g. std::allocator or
// allocator_traits.
break;
}
LCtx = LCtx->getParent();
} while (LCtx);
}
}
}

View File

@ -155,11 +155,21 @@ namespace std {
// basic_string
template<class _CharT, class _Alloc = allocator<_CharT> >
class __attribute__ ((__type_visibility__("default"))) basic_string {
_CharT localStorage[4];
bool isLong;
union {
_CharT localStorage[4];
_CharT *externalStorage;
void assignExternal(_CharT *newExternal) {
externalStorage = newExternal;
}
} storage;
typedef allocator_traits<_Alloc> __alloc_traits;
public:
basic_string();
void push_back(int c) {
// Fake error trigger.
// No warning is expected as we are suppressing warning coming
@ -168,11 +178,24 @@ namespace std {
z = 5/z;
}
_CharT *getBuffer() {
return isLong ? storage.externalStorage : storage.localStorage;
}
basic_string &operator +=(int c) {
// Fake deallocate stack-based storage.
// No warning is expected as we are suppressing warnings within
// allocators being used by std::basic_string.
__alloc_traits::deallocate(&localStorage);
// std::basic_string.
__alloc_traits::deallocate(getBuffer());
}
basic_string &operator =(const basic_string &other) {
// Fake deallocate stack-based storage, then use the variable in the
// same union.
// No warning is expected as we are suppressing warnings within
// std::basic_string.
__alloc_traits::deallocate(getBuffer());
storage.assignExternal(new _CharT[4]);
}
};
}

View File

@ -42,3 +42,8 @@ void testBasicStringSuppression_append() {
std::basic_string<char32_t> v;
v += 'c'; // no-warning
}
void testBasicStringSuppression_assign(std::basic_string<char32_t> &v,
const std::basic_string<char32_t> &v2) {
v = v2;
}