Bug 1744604 - Part 1: Make CustomTypeAnnotation more flexible, r=andi

This allows CustomTypeAnnotation to customize the type traversal behaviour to
allow things like opting library types out of static analysis easier. It will
be used in parts 2 and 3 to improve the non-memmoveable and non-param trait
analysis.

Differential Revision: https://phabricator.services.mozilla.com/D132995
This commit is contained in:
Nika Layzell 2021-12-14 16:49:17 +00:00
Родитель 32999573e3
Коммит ab7c298175
4 изменённых файлов: 50 добавлений и 22 удалений

Просмотреть файл

@ -75,13 +75,22 @@ void CustomTypeAnnotation::dumpAnnotationReason(BaseCheck &Check, QualType T,
CustomTypeAnnotation::AnnotationReason
CustomTypeAnnotation::directAnnotationReason(QualType T) {
VisitFlags ToVisit = VISIT_FIELDS | VISIT_BASES;
if (const TagDecl *D = T->getAsTagDecl()) {
// Recurse into template arguments if the annotation
// MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
if (hasCustomAttribute<moz_inherit_type_annotations_from_template_args>(
D)) {
ToVisit |= VISIT_TMPL_ARGS;
}
if (hasCustomAttribute(D, Attribute)) {
AnnotationReason Reason = {T, RK_Direct, nullptr, ""};
return Reason;
}
std::string ImplAnnotReason = getImplicitReason(D);
std::string ImplAnnotReason = getImplicitReason(D, ToVisit);
if (!ImplAnnotReason.empty()) {
AnnotationReason Reason = {T, RK_Implicit, nullptr, ImplAnnotReason};
return Reason;
@ -98,8 +107,8 @@ CustomTypeAnnotation::directAnnotationReason(QualType T) {
// Check if we have a type which we can recurse into
if (const clang::ArrayType *Array = T->getAsArrayTypeUnsafe()) {
if (hasEffectiveAnnotation(Array->getElementType())) {
AnnotationReason Reason = {Array->getElementType(), RK_ArrayElement,
nullptr, ""};
AnnotationReason Reason{Array->getElementType(), RK_ArrayElement, nullptr,
""};
Cache[Key] = Reason;
return Reason;
}
@ -110,27 +119,27 @@ CustomTypeAnnotation::directAnnotationReason(QualType T) {
if (Declaration->hasDefinition()) {
Declaration = Declaration->getDefinition();
for (const CXXBaseSpecifier &Base : Declaration->bases()) {
if (hasEffectiveAnnotation(Base.getType())) {
AnnotationReason Reason = {Base.getType(), RK_BaseClass, nullptr, ""};
Cache[Key] = Reason;
return Reason;
if (ToVisit & VISIT_BASES) {
for (const CXXBaseSpecifier &Base : Declaration->bases()) {
if (hasEffectiveAnnotation(Base.getType())) {
AnnotationReason Reason{Base.getType(), RK_BaseClass, nullptr, ""};
Cache[Key] = Reason;
return Reason;
}
}
}
// Recurse into members
for (const FieldDecl *Field : Declaration->fields()) {
if (hasEffectiveAnnotation(Field->getType())) {
AnnotationReason Reason = {Field->getType(), RK_Field, Field, ""};
Cache[Key] = Reason;
return Reason;
if (ToVisit & VISIT_FIELDS) {
for (const FieldDecl *Field : Declaration->fields()) {
if (hasEffectiveAnnotation(Field->getType())) {
AnnotationReason Reason{Field->getType(), RK_Field, Field, ""};
Cache[Key] = Reason;
return Reason;
}
}
}
// Recurse into template arguments if the annotation
// MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
if (hasCustomAttribute<moz_inherit_type_annotations_from_template_args>(
Declaration)) {
if (ToVisit & VISIT_TMPL_ARGS) {
const ClassTemplateSpecializationDecl *Spec =
dyn_cast<ClassTemplateSpecializationDecl>(Declaration);
if (Spec) {
@ -146,7 +155,7 @@ CustomTypeAnnotation::directAnnotationReason(QualType T) {
}
}
AnnotationReason Reason = {QualType(), RK_None, nullptr, ""};
AnnotationReason Reason{QualType(), RK_None, nullptr, ""};
Cache[Key] = Reason;
return Reason;
}

Просмотреть файл

@ -7,6 +7,7 @@
#include "CustomAttributes.h"
#include "plugin.h"
#include "llvm/ADT/BitmaskEnum.h"
class CustomTypeAnnotation {
enum ReasonKind {
@ -58,10 +59,26 @@ private:
AnnotationReason tmplArgAnnotationReason(ArrayRef<TemplateArgument> Args);
protected:
// Flags specifying which properties of the underlying type we want to visit.
enum VisitFlags {
VISIT_NONE = 0,
VISIT_FIELDS = 1,
VISIT_TMPL_ARGS = 2,
VISIT_BASES = 4,
LLVM_MARK_AS_BITMASK_ENUM(VISIT_BASES)
};
// Allow subclasses to apply annotations for reasons other than a direct
// annotation. A non-empty string return value means that the object D is
// annotated, and should contain the reason why.
virtual std::string getImplicitReason(const TagDecl *D) const { return ""; }
//
// The subclass may also modify `VisitFlags` to change what properties of the
// type will be inspected to skip inspecting fields, force template arguments
// to be inspected, etc.
virtual std::string getImplicitReason(const TagDecl *D,
VisitFlags &Flags) const {
return "";
}
};
extern CustomTypeAnnotation StackClass;

Просмотреть файл

@ -19,7 +19,8 @@ public:
virtual ~MemMoveAnnotation() {}
protected:
std::string getImplicitReason(const TagDecl *D) const override {
std::string getImplicitReason(const TagDecl *D,
VisitFlags &ToVisit) const override {
// Annotate everything in ::std, with a few exceptions; see bug
// 1201314 for discussion.
if (getDeclarationNamespace(D) == "std") {

Просмотреть файл

@ -14,7 +14,8 @@ protected:
// MSVC limitations which prevent passing explcitly aligned types by value as
// parameters. This overload of hasFakeAnnotation injects fake MOZ_NON_PARAM
// annotations onto these types.
std::string getImplicitReason(const TagDecl *D) const override {
std::string getImplicitReason(const TagDecl *D,
VisitFlags &ToVisit) const override {
// Check if the decl itself has an AlignedAttr on it.
for (const Attr *A : D->attrs()) {
if (isa<AlignedAttr>(A)) {