1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- //===--- NonCopyableObjects.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 "NonCopyableObjects.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/ASTMatchers/ASTMatchFinder.h"
- #include <algorithm>
- using namespace clang::ast_matchers;
- namespace clang::tidy::misc {
- void NonCopyableObjectsCheck::registerMatchers(MatchFinder *Finder) {
- // There are two ways to get into trouble with objects like FILE *:
- // dereferencing the pointer type to be a non-pointer type, and declaring
- // the type as a non-pointer type in the first place. While the declaration
- // itself could technically be well-formed in the case where the type is not
- // an opaque type, it's highly suspicious behavior.
- //
- // POSIX types are a bit different in that it's reasonable to declare a
- // non-pointer variable or data member of the type, but it is not reasonable
- // to dereference a pointer to the type, or declare a parameter of non-pointer
- // type.
- // FIXME: it would be good to make a list that is also user-configurable so
- // that users can add their own elements to the list. However, it may require
- // some extra thought since POSIX types and FILE types are usable in different
- // ways.
- auto BadFILEType = hasType(
- namedDecl(hasAnyName("::FILE", "FILE", "std::FILE")).bind("type_decl"));
- auto BadPOSIXType =
- hasType(namedDecl(hasAnyName("::pthread_cond_t", "::pthread_mutex_t",
- "pthread_cond_t", "pthread_mutex_t"))
- .bind("type_decl"));
- auto BadEitherType = anyOf(BadFILEType, BadPOSIXType);
- Finder->addMatcher(
- namedDecl(anyOf(varDecl(BadFILEType), fieldDecl(BadFILEType)))
- .bind("decl"),
- this);
- Finder->addMatcher(parmVarDecl(BadPOSIXType).bind("decl"), this);
- Finder->addMatcher(
- expr(unaryOperator(hasOperatorName("*"), BadEitherType)).bind("expr"),
- this);
- }
- void NonCopyableObjectsCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *D = Result.Nodes.getNodeAs<NamedDecl>("decl");
- const auto *BD = Result.Nodes.getNodeAs<NamedDecl>("type_decl");
- const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
- if (D && BD)
- diag(D->getLocation(), "%0 declared as type '%1', which is unsafe to copy"
- "; did you mean '%1 *'?")
- << D << BD->getName();
- else if (E)
- diag(E->getExprLoc(),
- "expression has opaque data structure type %0; type should only be "
- "used as a pointer and not dereferenced")
- << BD;
- }
- } // namespace clang::tidy::misc
|