clang-tools  10.0.0svn
NonCopyableObjects.cpp
Go to the documentation of this file.
1 //===--- NonCopyableObjects.cpp - clang-tidy-------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "NonCopyableObjects.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include <algorithm>
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace misc {
19 
20 void NonCopyableObjectsCheck::registerMatchers(MatchFinder *Finder) {
21  // There are two ways to get into trouble with objects like FILE *:
22  // dereferencing the pointer type to be a non-pointer type, and declaring
23  // the type as a non-pointer type in the first place. While the declaration
24  // itself could technically be well-formed in the case where the type is not
25  // an opaque type, it's highly suspicious behavior.
26  //
27  // POSIX types are a bit different in that it's reasonable to declare a
28  // non-pointer variable or data member of the type, but it is not reasonable
29  // to dereference a pointer to the type, or declare a parameter of non-pointer
30  // type.
31  // FIXME: it would be good to make a list that is also user-configurable so
32  // that users can add their own elements to the list. However, it may require
33  // some extra thought since POSIX types and FILE types are usable in different
34  // ways.
35 
36  auto BadFILEType = hasType(
37  namedDecl(hasAnyName("::FILE", "FILE", "std::FILE")).bind("type_decl"));
38  auto BadPOSIXType =
39  hasType(namedDecl(hasAnyName("::pthread_cond_t", "::pthread_mutex_t",
40  "pthread_cond_t", "pthread_mutex_t"))
41  .bind("type_decl"));
42  auto BadEitherType = anyOf(BadFILEType, BadPOSIXType);
43 
44  Finder->addMatcher(
45  namedDecl(anyOf(varDecl(BadFILEType), fieldDecl(BadFILEType)))
46  .bind("decl"),
47  this);
48  Finder->addMatcher(parmVarDecl(BadPOSIXType).bind("decl"), this);
49  Finder->addMatcher(
50  expr(unaryOperator(hasOperatorName("*"), BadEitherType)).bind("expr"),
51  this);
52 }
53 
54 void NonCopyableObjectsCheck::check(const MatchFinder::MatchResult &Result) {
55  const auto *D = Result.Nodes.getNodeAs<NamedDecl>("decl");
56  const auto *BD = Result.Nodes.getNodeAs<NamedDecl>("type_decl");
57  const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
58 
59  if (D && BD)
60  diag(D->getLocation(), "%0 declared as type '%1', which is unsafe to copy"
61  "; did you mean '%1 *'?")
62  << D << BD->getName();
63  else if (E)
64  diag(E->getExprLoc(),
65  "expression has opaque data structure type %0; type should only be "
66  "used as a pointer and not dereferenced")
67  << BD;
68 }
69 
70 } // namespace misc
71 } // namespace tidy
72 } // namespace clang
73 
const Decl * D
Definition: XRefs.cpp:868
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: Rename.cpp:36