mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1201314 - Make most of std:: non-memmovable for static analysis purposes. r=mystor r=ehsan
For simplicity, the exceptions are hard-coded in the plugin: currently std::pair and std::atomic.
This commit is contained in:
parent
c6d2d4f8dd
commit
f377ca14ea
@ -279,6 +279,8 @@ public:
|
||||
CustomTypeAnnotation(const char *Spelling, const char *Pretty)
|
||||
: Spelling(Spelling), Pretty(Pretty){};
|
||||
|
||||
virtual ~CustomTypeAnnotation() {}
|
||||
|
||||
// Checks if this custom annotation "effectively affects" the given type.
|
||||
bool hasEffectiveAnnotation(QualType T) {
|
||||
return directAnnotationReason(T).valid();
|
||||
@ -299,6 +301,10 @@ public:
|
||||
private:
|
||||
bool hasLiteralAnnotation(QualType T) const;
|
||||
AnnotationReason directAnnotationReason(QualType T);
|
||||
|
||||
protected:
|
||||
// Allow subclasses to apply annotations to external code:
|
||||
virtual bool hasFakeAnnotation(const TagDecl *D) const { return false; }
|
||||
};
|
||||
|
||||
static CustomTypeAnnotation StackClass =
|
||||
@ -313,8 +319,32 @@ static CustomTypeAnnotation NonTemporaryClass =
|
||||
CustomTypeAnnotation("moz_non_temporary_class", "non-temporary");
|
||||
static CustomTypeAnnotation MustUse =
|
||||
CustomTypeAnnotation("moz_must_use", "must-use");
|
||||
static CustomTypeAnnotation NonMemMovable =
|
||||
CustomTypeAnnotation("moz_non_memmovable", "non-memmove()able");
|
||||
|
||||
class MemMoveAnnotation final : public CustomTypeAnnotation {
|
||||
public:
|
||||
MemMoveAnnotation()
|
||||
: CustomTypeAnnotation("moz_non_memmovable", "non-memmove()able") {}
|
||||
|
||||
virtual ~MemMoveAnnotation() {}
|
||||
|
||||
protected:
|
||||
bool hasFakeAnnotation(const TagDecl *D) const override {
|
||||
// Annotate everything in ::std, with a few exceptions; see bug
|
||||
// 1201314 for discussion.
|
||||
if (getDeclarationNamespace(D) == "std") {
|
||||
// This doesn't check that it's really ::std::pair and not
|
||||
// ::std::something_else::pair, but should be good enough.
|
||||
StringRef Name = D->getName();
|
||||
if (Name == "pair" || Name == "atomic" || Name == "__atomic_base") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static MemMoveAnnotation NonMemMovable = MemMoveAnnotation();
|
||||
|
||||
class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
|
||||
DiagnosticsEngine &Diag;
|
||||
@ -768,7 +798,7 @@ bool CustomTypeAnnotation::hasLiteralAnnotation(QualType T) const {
|
||||
#else
|
||||
if (const CXXRecordDecl *D = T->getAsCXXRecordDecl()) {
|
||||
#endif
|
||||
return MozChecker::hasCustomAnnotation(D, Spelling);
|
||||
return hasFakeAnnotation(D) || MozChecker::hasCustomAnnotation(D, Spelling);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
21
build/clang-plugin/tests/TestNonMemMovableStd.cpp
Normal file
21
build/clang-plugin/tests/TestNonMemMovableStd.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
|
||||
|
||||
template<class T>
|
||||
class MOZ_NEEDS_MEMMOVABLE_TYPE Mover { T mForceInst; }; // expected-error-re 4 {{Cannot instantiate 'Mover<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
|
||||
|
||||
namespace std {
|
||||
// In theory defining things in std:: like this invokes undefined
|
||||
// behavior, but in practice it's good enough for this test case.
|
||||
template<class C> class basic_string { };
|
||||
typedef basic_string<char> string;
|
||||
template<class T, class U> class pair { T mT; U mU; }; // expected-note {{std::pair<bool, std::basic_string<char> >' is a non-memmove()able type because member 'mU' is a non-memmove()able type 'std::basic_string<char>'}}
|
||||
class arbitrary_name { };
|
||||
}
|
||||
|
||||
class HasString { std::string m; }; // expected-note {{'HasString' is a non-memmove()able type because member 'm' is a non-memmove()able type 'std::string' (aka 'basic_string<char>')}}
|
||||
|
||||
static Mover<std::string> bad; // expected-note {{instantiation of 'Mover<std::basic_string<char> >' requested here}}
|
||||
static Mover<HasString> bad_mem; // expected-note {{instantiation of 'Mover<HasString>' requested here}}
|
||||
static Mover<std::arbitrary_name> assumed_bad; // expected-note {{instantiation of 'Mover<std::arbitrary_name>' requested here}}
|
||||
static Mover<std::pair<bool, int>> good;
|
||||
static Mover<std::pair<bool, std::string>> not_good; // expected-note {{instantiation of 'Mover<std::pair<bool, std::basic_string<char> > >' requested here}}
|
@ -24,6 +24,7 @@ SOURCES += [
|
||||
'TestNoExplicitMoveConstructor.cpp',
|
||||
'TestNonHeapClass.cpp',
|
||||
'TestNonMemMovable.cpp',
|
||||
'TestNonMemMovableStd.cpp',
|
||||
'TestNonTemporaryClass.cpp',
|
||||
'TestNoRefcountedInsideLambdas.cpp',
|
||||
'TestRefCountedCopyConstructor.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user