Mercurial > hg > CbC > CbC_llvm
diff clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 0572611fdcc8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp Thu Feb 13 15:10:13 2020 +0900 @@ -0,0 +1,66 @@ +//===--- ExceptionBaseclassCheck.cpp - clang-tidy--------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ExceptionBaseclassCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace hicpp { + +void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + Finder->addMatcher( + cxxThrowExpr( + unless(has(expr(anyOf(isTypeDependent(), isValueDependent())))), + // The thrown value is not derived from 'std::exception'. + has(expr(unless( + hasType(qualType(hasCanonicalType(hasDeclaration(cxxRecordDecl( + isSameOrDerivedFrom(hasName("::std::exception")))))))))), + // This condition is always true, but will bind to the + // template value if the thrown type is templated. + anyOf(has(expr( + hasType(substTemplateTypeParmType().bind("templ_type")))), + anything()), + // Bind to the declaration of the type of the value that + // is thrown. 'anything()' is necessary to always suceed + // in the 'eachOf' because builtin types are not + // 'namedDecl'. + eachOf(has(expr(hasType(namedDecl().bind("decl")))), anything())) + .bind("bad_throw"), + this); +} + +void ExceptionBaseclassCheck::check(const MatchFinder::MatchResult &Result) { + const auto *BadThrow = Result.Nodes.getNodeAs<CXXThrowExpr>("bad_throw"); + assert(BadThrow && "Did not match the throw expression"); + + diag(BadThrow->getSubExpr()->getBeginLoc(), "throwing an exception whose " + "type %0 is not derived from " + "'std::exception'") + << BadThrow->getSubExpr()->getType() << BadThrow->getSourceRange(); + + if (const auto *Template = + Result.Nodes.getNodeAs<SubstTemplateTypeParmType>("templ_type")) + diag(BadThrow->getSubExpr()->getBeginLoc(), + "type %0 is a template instantiation of %1", DiagnosticIDs::Note) + << BadThrow->getSubExpr()->getType() + << Template->getReplacedParameter()->getDecl(); + + if (const auto *TypeDecl = Result.Nodes.getNodeAs<NamedDecl>("decl")) + diag(TypeDecl->getBeginLoc(), "type defined here", DiagnosticIDs::Note); +} + +} // namespace hicpp +} // namespace tidy +} // namespace clang