forked from OSchip/llvm-project
[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:
parent
3d4417c7fd
commit
c7d0acaf34
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue