/* 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 "ParamTraitsEnumChecker.h" #include "CustomMatchers.h" void ParamTraitsEnumChecker::registerMatchers(MatchFinder *AstMatcher) { AstMatcher->addMatcher( classTemplateSpecializationDecl( hasName("ParamTraits"), unless(anyOf( // Exclude ParamTraits that derive from EnumSerializer (e.g., // ContiguousEnumSerializer) as these are the recommended way to // serialize enums. isDerivedFrom("EnumSerializer"), // Exclude ParamTraits_IsEnumCase, which is an alternative to // EnumSerializer. isDerivedFrom("ParamTraits_IsEnumCase"), // Exclude nsresult specifically, which has a legitimate // ParamTraitsMozilla specialization. hasTemplateArgument( 0, refersToType(hasDeclaration(namedDecl(hasName("nsresult")))))))) .bind("decl"), this); } void ParamTraitsEnumChecker::check(const MatchFinder::MatchResult &Result) { const ClassTemplateSpecializationDecl *Decl = Result.Nodes.getNodeAs("decl"); const TemplateArgumentList &ArgumentList = Decl->getTemplateArgs(); if (ArgumentList.size() != 1) { diag(Decl->getBeginLoc(), "ParamTraits specialization should have exactly one template argument", DiagnosticIDs::Error); return; } QualType ArgType = ArgumentList[0].getAsType(); if (const clang::Type *TypePtr = ArgType.getTypePtrOrNull()) { if (TypePtr->isEnumeralType()) { diag(Decl->getBeginLoc(), "Custom ParamTraits implementation for an enum type", DiagnosticIDs::Error); diag(Decl->getBeginLoc(), "Please use a helper class for example ContiguousEnumSerializer", DiagnosticIDs::Note); } } }