mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 1487622 - Refactor the clang plugin wrt attributes r=andi
- We forcefully remove annotations from the AST so that they don't end up impacting codegen. - We change the API such that we use identifiers instead of strings, reducing the chances of typo errors. Differential Revision: https://phabricator.services.mozilla.com/D5493 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
cdd1898856
commit
f8798bbeb2
@ -110,7 +110,7 @@ void FuncSetCallback::run(const MatchFinder::MatchResult &Result) {
|
||||
const FunctionDecl *Func;
|
||||
if (auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda")) {
|
||||
Func = Lambda->getCallOperator();
|
||||
if (!Func || !hasCustomAnnotation(Func, "moz_can_run_script"))
|
||||
if (!Func || !hasCustomAttribute<moz_can_run_script>(Func))
|
||||
return;
|
||||
} else {
|
||||
Func = Result.Nodes.getNodeAs<FunctionDecl>("canRunScriptFunction");
|
||||
@ -211,7 +211,7 @@ void CanRunScriptChecker::check(const MatchFinder::MatchResult &Result) {
|
||||
// Bindings.
|
||||
if (ParentFunction &&
|
||||
(CanRunScriptFuncs.count(ParentFunction) ||
|
||||
hasCustomAnnotation(ParentFunction, "moz_can_run_script_boundary"))) {
|
||||
hasCustomAttribute<moz_can_run_script_boundary>(ParentFunction))) {
|
||||
ParentFunction = nullptr;
|
||||
}
|
||||
|
||||
@ -236,7 +236,7 @@ void CanRunScriptChecker::check(const MatchFinder::MatchResult &Result) {
|
||||
// If the parent function is not marked as MOZ_CAN_RUN_SCRIPT, we emit an
|
||||
// error and a not indicating it.
|
||||
if (ParentFunction) {
|
||||
assert(!hasCustomAnnotation(ParentFunction, "moz_can_run_script") &&
|
||||
assert(!hasCustomAttribute<moz_can_run_script>(ParentFunction) &&
|
||||
"Matcher missed something");
|
||||
|
||||
diag(CallRange.getBegin(), ErrorNonCanRunScriptParent, DiagnosticIDs::Error)
|
||||
|
122
build/clang-plugin/CustomAttributes.cpp
Normal file
122
build/clang-plugin/CustomAttributes.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <algorithm>
|
||||
#include "CustomAttributes.h"
|
||||
#include "plugin.h"
|
||||
#include "clang/Frontend/FrontendPluginRegistry.h"
|
||||
|
||||
/* Having annotations in the AST unexpectedly impacts codegen.
|
||||
* Ideally, we'd avoid having annotations at all, by using an API such as
|
||||
* the one from https://reviews.llvm.org/D31338, and storing the attributes
|
||||
* data separately from the AST on our own. Unfortunately, there is no such
|
||||
* API currently in clang, so we must do without.
|
||||
* We can do something similar, though, where we go through the AST before
|
||||
* running the checks, create a mapping of AST nodes to attributes, and
|
||||
* remove the attributes/annotations from the AST nodes.
|
||||
* Not all declarations can be reached from the decl() AST matcher, though,
|
||||
* so we do our best effort (getting the other declarations we look at in
|
||||
* checks). We emit a warning when checks look at a note that still has
|
||||
* annotations attached (aka, hasn't been seen during our first pass),
|
||||
* so that those don't go unnoticed. (-Werror should then take care of
|
||||
* making that an error)
|
||||
*/
|
||||
|
||||
using namespace clang;
|
||||
using namespace llvm;
|
||||
|
||||
static DenseMap<const Decl*, CustomAttributesSet> AttributesCache;
|
||||
|
||||
static CustomAttributesSet CacheAttributes(const Decl* D)
|
||||
{
|
||||
CustomAttributesSet attrs = {};
|
||||
for (auto Attr : D->specific_attrs<AnnotateAttr>()) {
|
||||
auto annotation = Attr->getAnnotation();
|
||||
#define ATTR(a) \
|
||||
if (annotation == #a) { \
|
||||
attrs.has_ ## a = true; \
|
||||
} else
|
||||
#include "CustomAttributes.inc"
|
||||
#undef ATTR
|
||||
{}
|
||||
}
|
||||
const_cast<Decl*>(D)->dropAttr<AnnotateAttr>();
|
||||
AttributesCache.insert(std::make_pair(D, attrs));
|
||||
return attrs;
|
||||
}
|
||||
|
||||
static void Report(const Decl* D, const char* message)
|
||||
{
|
||||
ASTContext& Context = D->getASTContext();
|
||||
DiagnosticsEngine& Diag = Context.getDiagnostics();
|
||||
unsigned ID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Warning, message);
|
||||
Diag.Report(D->getLocStart(), ID);
|
||||
}
|
||||
|
||||
CustomAttributesSet GetAttributes(const Decl* D)
|
||||
{
|
||||
CustomAttributesSet attrs = {};
|
||||
if (D->hasAttr<AnnotateAttr>()) {
|
||||
Report(D, "Declaration has unhandled annotations.");
|
||||
attrs = CacheAttributes(D);
|
||||
} else {
|
||||
auto attributes = AttributesCache.find(D);
|
||||
if (attributes != AttributesCache.end()) {
|
||||
attrs = attributes->second;
|
||||
}
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
|
||||
bool hasCustomAttribute(const clang::Decl* D, CustomAttributes A)
|
||||
{
|
||||
CustomAttributesSet attrs = GetAttributes(D);
|
||||
switch (A) {
|
||||
#define ATTR(a) case a: return attrs.has_ ## a;
|
||||
#include "CustomAttributes.inc"
|
||||
#undef ATTR
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class CustomAttributesMatcher : public ast_matchers::MatchFinder::MatchCallback {
|
||||
public:
|
||||
virtual void
|
||||
run(const ast_matchers::MatchFinder::MatchResult &Result) final
|
||||
{
|
||||
if (auto D = Result.Nodes.getNodeAs<Decl>("decl")) {
|
||||
CacheAttributes(D);
|
||||
} else if (auto L = Result.Nodes.getNodeAs<LambdaExpr>("lambda")) {
|
||||
CacheAttributes(L->getCallOperator());
|
||||
CacheAttributes(L->getLambdaClass());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CustomAttributesAction : public PluginASTAction {
|
||||
public:
|
||||
ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI,
|
||||
StringRef FileName) override {
|
||||
auto& Context = CI.getASTContext();
|
||||
auto AstMatcher = new (Context.Allocate<MatchFinder>()) MatchFinder();
|
||||
auto Matcher = new (Context.Allocate<CustomAttributesMatcher>()) CustomAttributesMatcher();
|
||||
AstMatcher->addMatcher(decl().bind("decl"), Matcher);
|
||||
AstMatcher->addMatcher(lambdaExpr().bind("lambda"), Matcher);
|
||||
return AstMatcher->newASTConsumer();
|
||||
}
|
||||
|
||||
bool ParseArgs(const CompilerInstance &CI,
|
||||
const std::vector<std::string> &Args) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
ActionType getActionType() override {
|
||||
return AddBeforeMainAction;
|
||||
}
|
||||
};
|
||||
|
||||
static FrontendPluginRegistry::Add<CustomAttributesAction> X(
|
||||
"moz-custom-attributes",
|
||||
"prepare custom attributes for moz-check");
|
40
build/clang-plugin/CustomAttributes.h
Normal file
40
build/clang-plugin/CustomAttributes.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CustomAttributes_h__
|
||||
#define CustomAttributes_h__
|
||||
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
enum CustomAttributes {
|
||||
#define ATTR(a) a,
|
||||
#include "CustomAttributes.inc"
|
||||
#undef ATTR
|
||||
};
|
||||
|
||||
struct CustomAttributesSet {
|
||||
#define ATTR(a) bool has_ ## a: 1;
|
||||
#include "CustomAttributes.inc"
|
||||
#undef ATTR
|
||||
};
|
||||
|
||||
template<CustomAttributes A>
|
||||
bool hasCustomAttribute(const clang::Decl* D) {
|
||||
return false;
|
||||
}
|
||||
|
||||
extern CustomAttributesSet GetAttributes(const clang::Decl* D);
|
||||
|
||||
#define ATTR(name) \
|
||||
template<> \
|
||||
inline bool hasCustomAttribute<name>(const clang::Decl* D) { \
|
||||
return GetAttributes(D).has_ ## name; \
|
||||
}
|
||||
#include "CustomAttributes.inc"
|
||||
#undef ATTR
|
||||
|
||||
extern bool hasCustomAttribute(const clang::Decl* D, CustomAttributes A);
|
||||
|
||||
#endif /* CustomAttributes_h__ */
|
27
build/clang-plugin/CustomAttributes.inc
Normal file
27
build/clang-plugin/CustomAttributes.inc
Normal file
@ -0,0 +1,27 @@
|
||||
ATTR(moz_can_run_script)
|
||||
ATTR(moz_can_run_script_boundary)
|
||||
ATTR(moz_global_class)
|
||||
ATTR(moz_heap_allocator)
|
||||
ATTR(moz_heap_class)
|
||||
ATTR(moz_implicit)
|
||||
ATTR(moz_inherit_type_annotations_from_template_args)
|
||||
ATTR(moz_is_smartptr_to_refcounted)
|
||||
ATTR(moz_may_call_after_must_return)
|
||||
ATTR(moz_must_override)
|
||||
ATTR(moz_must_return_from_caller)
|
||||
ATTR(moz_must_use_type)
|
||||
ATTR(moz_needs_memmovable_members)
|
||||
ATTR(moz_needs_memmovable_type)
|
||||
ATTR(moz_needs_no_vtable_type)
|
||||
ATTR(moz_no_addref_release_on_return)
|
||||
ATTR(moz_no_arith_expr_in_arg)
|
||||
ATTR(moz_no_dangling_on_temporaries)
|
||||
ATTR(moz_non_autoable)
|
||||
ATTR(moz_non_memmovable)
|
||||
ATTR(moz_non_param)
|
||||
ATTR(moz_non_temporary_class)
|
||||
ATTR(moz_nonheap_class)
|
||||
ATTR(moz_required_base_method)
|
||||
ATTR(moz_stack_class)
|
||||
ATTR(moz_temporary_class)
|
||||
ATTR(moz_trivial_ctor_dtor)
|
@ -14,19 +14,19 @@ namespace ast_matchers {
|
||||
/// This matcher will match any function declaration that is declared as a heap
|
||||
/// allocator.
|
||||
AST_MATCHER(FunctionDecl, heapAllocator) {
|
||||
return hasCustomAnnotation(&Node, "moz_heap_allocator");
|
||||
return hasCustomAttribute<moz_heap_allocator>(&Node);
|
||||
}
|
||||
|
||||
/// This matcher will match any declaration that is marked as not accepting
|
||||
/// arithmetic expressions in its arguments.
|
||||
AST_MATCHER(Decl, noArithmeticExprInArgs) {
|
||||
return hasCustomAnnotation(&Node, "moz_no_arith_expr_in_arg");
|
||||
return hasCustomAttribute<moz_no_arith_expr_in_arg>(&Node);
|
||||
}
|
||||
|
||||
/// This matcher will match any C++ class that is marked as having a trivial
|
||||
/// constructor and destructor.
|
||||
AST_MATCHER(CXXRecordDecl, hasTrivialCtorDtor) {
|
||||
return hasCustomAnnotation(&Node, "moz_trivial_ctor_dtor");
|
||||
return hasCustomAttribute<moz_trivial_ctor_dtor>(&Node);
|
||||
}
|
||||
|
||||
/// This matcher will match lvalue-ref-qualified methods.
|
||||
@ -56,19 +56,19 @@ AST_MATCHER(Expr, isTemporary) {
|
||||
/// This matcher will match any method declaration that is marked as returning
|
||||
/// a pointer deleted by the destructor of the class.
|
||||
AST_MATCHER(CXXMethodDecl, noDanglingOnTemporaries) {
|
||||
return hasCustomAnnotation(&Node, "moz_no_dangling_on_temporaries");
|
||||
return hasCustomAttribute<moz_no_dangling_on_temporaries>(&Node);
|
||||
}
|
||||
|
||||
/// This matcher will match any function declaration that is marked to prohibit
|
||||
/// calling AddRef or Release on its return value.
|
||||
AST_MATCHER(FunctionDecl, hasNoAddRefReleaseOnReturnAttr) {
|
||||
return hasCustomAnnotation(&Node, "moz_no_addref_release_on_return");
|
||||
return hasCustomAttribute<moz_no_addref_release_on_return>(&Node);
|
||||
}
|
||||
|
||||
/// This matcher will match any function declaration that is marked as being
|
||||
/// allowed to run script.
|
||||
AST_MATCHER(FunctionDecl, hasCanRunScriptAnnotation) {
|
||||
return hasCustomAnnotation(&Node, "moz_can_run_script");
|
||||
return hasCustomAttribute<moz_can_run_script>(&Node);
|
||||
}
|
||||
|
||||
/// This matcher will match all arithmetic binary operators.
|
||||
@ -156,7 +156,7 @@ AST_MATCHER(CXXRecordDecl, isRefCounted) { return isClassRefCounted(&Node); }
|
||||
AST_MATCHER(QualType, hasVTable) { return typeHasVTable(Node); }
|
||||
|
||||
AST_MATCHER(CXXRecordDecl, hasNeedsNoVTableTypeAttr) {
|
||||
return hasCustomAnnotation(&Node, "moz_needs_no_vtable_type");
|
||||
return hasCustomAttribute<moz_needs_no_vtable_type>(&Node);
|
||||
}
|
||||
|
||||
/// This matcher will select classes which are non-memmovable
|
||||
@ -166,12 +166,12 @@ AST_MATCHER(QualType, isNonMemMovable) {
|
||||
|
||||
/// This matcher will select classes which require a memmovable template arg
|
||||
AST_MATCHER(CXXRecordDecl, needsMemMovableTemplateArg) {
|
||||
return hasCustomAnnotation(&Node, "moz_needs_memmovable_type");
|
||||
return hasCustomAttribute<moz_needs_memmovable_type>(&Node);
|
||||
}
|
||||
|
||||
/// This matcher will select classes which require all members to be memmovable
|
||||
AST_MATCHER(CXXRecordDecl, needsMemMovableMembers) {
|
||||
return hasCustomAnnotation(&Node, "moz_needs_memmovable_members");
|
||||
return hasCustomAttribute<moz_needs_memmovable_members>(&Node);
|
||||
}
|
||||
|
||||
AST_MATCHER(CXXConstructorDecl, isInterestingImplicitCtor) {
|
||||
@ -198,7 +198,7 @@ AST_MATCHER_P(Expr, ignoreTrivials, internal::Matcher<Expr>, InnerMatcher) {
|
||||
// We can't call this "isImplicit" since it clashes with an existing matcher in
|
||||
// clang.
|
||||
AST_MATCHER(CXXConstructorDecl, isMarkedImplicit) {
|
||||
return hasCustomAnnotation(&Node, "moz_implicit");
|
||||
return hasCustomAttribute<moz_implicit>(&Node);
|
||||
}
|
||||
|
||||
AST_MATCHER(CXXRecordDecl, isConcreteClass) { return !Node.isAbstract(); }
|
||||
@ -206,7 +206,7 @@ AST_MATCHER(CXXRecordDecl, isConcreteClass) { return !Node.isAbstract(); }
|
||||
AST_MATCHER(QualType, autoNonAutoableType) {
|
||||
if (const AutoType *T = Node->getContainedAutoType()) {
|
||||
if (const CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) {
|
||||
return hasCustomAnnotation(Rec, "moz_non_autoable");
|
||||
return hasCustomAttribute<moz_non_autoable>(Rec);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -258,7 +258,7 @@ AST_MATCHER(QualType, isSmartPtrToRefCounted) {
|
||||
|
||||
D = D->getCanonicalDecl();
|
||||
|
||||
return D && hasCustomAnnotation(D, "moz_is_smartptr_to_refcounted");
|
||||
return D && hasCustomAttribute<moz_is_smartptr_to_refcounted>(D);
|
||||
}
|
||||
|
||||
AST_MATCHER(CXXRecordDecl, hasBaseClasses) {
|
||||
@ -270,7 +270,7 @@ AST_MATCHER(CXXRecordDecl, hasBaseClasses) {
|
||||
|
||||
AST_MATCHER(CXXMethodDecl, isRequiredBaseMethod) {
|
||||
const CXXMethodDecl *Decl = Node.getCanonicalDecl();
|
||||
return Decl && hasCustomAnnotation(Decl, "moz_required_base_method");
|
||||
return Decl && hasCustomAttribute<moz_required_base_method>(Decl);
|
||||
}
|
||||
|
||||
AST_MATCHER(CXXMethodDecl, isNonVirtual) {
|
||||
@ -280,7 +280,7 @@ AST_MATCHER(CXXMethodDecl, isNonVirtual) {
|
||||
|
||||
AST_MATCHER(FunctionDecl, isMozMustReturnFromCaller) {
|
||||
const FunctionDecl *Decl = Node.getCanonicalDecl();
|
||||
return Decl && hasCustomAnnotation(Decl, "moz_must_return_from_caller");
|
||||
return Decl && hasCustomAttribute<moz_must_return_from_caller>(Decl);
|
||||
}
|
||||
|
||||
#if CLANG_VERSION_FULL < 309
|
||||
|
@ -6,16 +6,16 @@
|
||||
#include "Utils.h"
|
||||
|
||||
CustomTypeAnnotation StackClass =
|
||||
CustomTypeAnnotation("moz_stack_class", "stack");
|
||||
CustomTypeAnnotation(moz_stack_class, "stack");
|
||||
CustomTypeAnnotation GlobalClass =
|
||||
CustomTypeAnnotation("moz_global_class", "global");
|
||||
CustomTypeAnnotation(moz_global_class, "global");
|
||||
CustomTypeAnnotation NonHeapClass =
|
||||
CustomTypeAnnotation("moz_nonheap_class", "non-heap");
|
||||
CustomTypeAnnotation HeapClass = CustomTypeAnnotation("moz_heap_class", "heap");
|
||||
CustomTypeAnnotation(moz_nonheap_class, "non-heap");
|
||||
CustomTypeAnnotation HeapClass = CustomTypeAnnotation(moz_heap_class, "heap");
|
||||
CustomTypeAnnotation NonTemporaryClass =
|
||||
CustomTypeAnnotation("moz_non_temporary_class", "non-temporary");
|
||||
CustomTypeAnnotation(moz_non_temporary_class, "non-temporary");
|
||||
CustomTypeAnnotation TemporaryClass =
|
||||
CustomTypeAnnotation("moz_temporary_class", "temporary");
|
||||
CustomTypeAnnotation(moz_temporary_class, "temporary");
|
||||
|
||||
void CustomTypeAnnotation::dumpAnnotationReason(BaseCheck &Check, QualType T,
|
||||
SourceLocation Loc) {
|
||||
@ -74,7 +74,7 @@ void CustomTypeAnnotation::dumpAnnotationReason(BaseCheck &Check, QualType T,
|
||||
CustomTypeAnnotation::AnnotationReason
|
||||
CustomTypeAnnotation::directAnnotationReason(QualType T) {
|
||||
if (const TagDecl *D = T->getAsTagDecl()) {
|
||||
if (hasCustomAnnotation(D, Spelling)) {
|
||||
if (hasCustomAttribute(D, Attribute)) {
|
||||
AnnotationReason Reason = {T, RK_Direct, nullptr, ""};
|
||||
return Reason;
|
||||
}
|
||||
@ -127,8 +127,8 @@ CustomTypeAnnotation::directAnnotationReason(QualType T) {
|
||||
|
||||
// Recurse into template arguments if the annotation
|
||||
// MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
|
||||
if (hasCustomAnnotation(
|
||||
Declaration, "moz_inherit_type_annotations_from_template_args")) {
|
||||
if (hasCustomAttribute<moz_inherit_type_annotations_from_template_args>(
|
||||
Declaration)) {
|
||||
const ClassTemplateSpecializationDecl *Spec =
|
||||
dyn_cast<ClassTemplateSpecializationDecl>(Declaration);
|
||||
if (Spec) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef CustomTypeAnnotation_h__
|
||||
#define CustomTypeAnnotation_h__
|
||||
|
||||
#include "CustomAttributes.h"
|
||||
#include "plugin.h"
|
||||
|
||||
class CustomTypeAnnotation {
|
||||
@ -27,13 +28,13 @@ class CustomTypeAnnotation {
|
||||
};
|
||||
typedef DenseMap<void *, AnnotationReason> ReasonCache;
|
||||
|
||||
const char *Spelling;
|
||||
CustomAttributes Attribute;
|
||||
const char *Pretty;
|
||||
ReasonCache Cache;
|
||||
|
||||
public:
|
||||
CustomTypeAnnotation(const char *Spelling, const char *Pretty)
|
||||
: Spelling(Spelling), Pretty(Pretty){};
|
||||
CustomTypeAnnotation(CustomAttributes Attribute, const char *Pretty)
|
||||
: Attribute(Attribute), Pretty(Pretty){};
|
||||
|
||||
virtual ~CustomTypeAnnotation() {}
|
||||
|
||||
|
@ -22,7 +22,7 @@ void ExplicitOperatorBoolChecker::check(
|
||||
const CXXRecordDecl *Clazz = Method->getParent();
|
||||
|
||||
if (!Method->isExplicitSpecified() &&
|
||||
!hasCustomAnnotation(Method, "moz_implicit") &&
|
||||
!hasCustomAttribute<moz_implicit>(Method) &&
|
||||
!ASTIsInSystemHeader(Method->getASTContext(), *Method) &&
|
||||
isInterestingDeclForImplicitConversion(Method)) {
|
||||
diag(Method->getLocStart(), "bad implicit conversion operator for %0",
|
||||
|
@ -12,7 +12,7 @@
|
||||
class MemMoveAnnotation final : public CustomTypeAnnotation {
|
||||
public:
|
||||
MemMoveAnnotation()
|
||||
: CustomTypeAnnotation("moz_non_memmovable", "non-memmove()able") {}
|
||||
: CustomTypeAnnotation(moz_non_memmovable, "non-memmove()able") {}
|
||||
|
||||
virtual ~MemMoveAnnotation() {}
|
||||
|
||||
|
@ -34,7 +34,7 @@ void MustOverrideChecker::check(const MatchFinder::MatchResult &Result) {
|
||||
}
|
||||
Parent = Parent->getDefinition();
|
||||
for (const auto &M : Parent->methods()) {
|
||||
if (hasCustomAnnotation(M, "moz_must_override"))
|
||||
if (hasCustomAttribute<moz_must_override>(M))
|
||||
MustOverrides.push_back(M);
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ bool MustReturnFromCallerChecker::immediatelyReturns(
|
||||
if (auto CE = dyn_cast<CallExpr>(AfterTrivials)) {
|
||||
auto Callee = CE->getDirectCallee();
|
||||
if (Callee &&
|
||||
hasCustomAnnotation(Callee, "moz_may_call_after_must_return")) {
|
||||
hasCustomAttribute<moz_may_call_after_must_return>(Callee)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "CustomTypeAnnotation.h"
|
||||
|
||||
CustomTypeAnnotation MustUse =
|
||||
CustomTypeAnnotation("moz_must_use_type", "must-use");
|
||||
CustomTypeAnnotation(moz_must_use_type, "must-use");
|
||||
|
||||
void MustUseChecker::registerMatchers(MatchFinder *AstMatcher) {
|
||||
AstMatcher->addMatcher(switchCase().bind("switchcase"), this);
|
||||
|
@ -21,7 +21,7 @@ void NoAddRefReleaseOnReturnChecker::check(
|
||||
// to a MOZ_NO_ADDREF_RELEASE_ON_RETURN function or method.
|
||||
if (auto *Call = dyn_cast<CallExpr>(Base)) {
|
||||
if (auto *Callee = Call->getDirectCallee()) {
|
||||
if (hasCustomAnnotation(Callee, "moz_no_addref_release_on_return")) {
|
||||
if (hasCustomAttribute<moz_no_addref_release_on_return>(Callee)) {
|
||||
diag(Call->getLocStart(),
|
||||
"%1 cannot be called on the return value of %0",
|
||||
DiagnosticIDs::Error)
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
class NonParamAnnotation : public CustomTypeAnnotation {
|
||||
public:
|
||||
NonParamAnnotation() : CustomTypeAnnotation("moz_non_param", "non-param"){};
|
||||
NonParamAnnotation() : CustomTypeAnnotation(moz_non_param, "non-param"){};
|
||||
|
||||
protected:
|
||||
// Adding alignas(_) on a struct implicitly marks it as MOZ_NON_PARAM, due to
|
||||
|
@ -11,7 +11,7 @@ void OverrideBaseCallChecker::registerMatchers(MatchFinder *AstMatcher) {
|
||||
|
||||
bool OverrideBaseCallChecker::isRequiredBaseMethod(
|
||||
const CXXMethodDecl *Method) {
|
||||
return hasCustomAnnotation(Method, "moz_required_base_method");
|
||||
return hasCustomAttribute<moz_required_base_method>(Method);
|
||||
}
|
||||
|
||||
void OverrideBaseCallChecker::evaluateExpression(
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef Utils_h__
|
||||
#define Utils_h__
|
||||
|
||||
#include "CustomAttributes.h"
|
||||
#include "ThirdPartyPaths.h"
|
||||
#include "plugin.h"
|
||||
|
||||
@ -333,25 +334,12 @@ inline const FieldDecl *getBaseRefCntMember(QualType T) {
|
||||
return Clazz ? getBaseRefCntMember(Clazz) : 0;
|
||||
}
|
||||
|
||||
inline bool hasCustomAnnotation(const Decl *D, StringRef Spelling) {
|
||||
iterator_range<specific_attr_iterator<AnnotateAttr>> Attrs =
|
||||
D->specific_attrs<AnnotateAttr>();
|
||||
|
||||
for (AnnotateAttr *Attr : Attrs) {
|
||||
if (Attr->getAnnotation() == Spelling) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isPlacementNew(const CXXNewExpr *Expression) {
|
||||
// Regular new expressions aren't placement new
|
||||
if (Expression->getNumPlacementArgs() == 0)
|
||||
return false;
|
||||
const FunctionDecl *Declaration = Expression->getOperatorNew();
|
||||
if (Declaration && hasCustomAnnotation(Declaration, "moz_heap_allocator")) {
|
||||
if (Declaration && hasCustomAttribute<moz_heap_allocator>(Declaration)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -12,6 +12,7 @@ HOST_SOURCES += [
|
||||
'ArithmeticArgChecker.cpp',
|
||||
'AssertAssignmentChecker.cpp',
|
||||
'CanRunScriptChecker.cpp',
|
||||
'CustomAttributes.cpp',
|
||||
'CustomTypeAnnotation.cpp',
|
||||
'DanglingOnTemporaryChecker.cpp',
|
||||
'DiagnosticsMatcher.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user