1 //===--- DefaultOperatorNewCheck.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 "DefaultOperatorNewAlignmentCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 
13 using namespace clang::ast_matchers;
14 
15 namespace clang {
16 namespace tidy {
17 namespace cert {
18 
19 AST_MATCHER(CXXNewExpr, isPlacementNew) {
20   return Node.getNumPlacementArgs() > 0;
21 }
22 
23 void DefaultOperatorNewAlignmentCheck::registerMatchers(MatchFinder *Finder) {
24   // Check not applicable in C++17 (or newer).
25   if (getLangOpts().CPlusPlus17)
26     return;
27 
28   Finder->addMatcher(cxxNewExpr(unless(isPlacementNew())).bind("new"), this);
29 }
30 
31 void DefaultOperatorNewAlignmentCheck::check(
32     const MatchFinder::MatchResult &Result) {
33   // Get the found 'new' expression.
34   const auto *NewExpr = Result.Nodes.getNodeAs<CXXNewExpr>("new");
35 
36   QualType T = NewExpr->getAllocatedType();
37   // Dependent types do not have fixed alignment.
38   if (T->isDependentType())
39     return;
40   const TagDecl *D = T->getAsTagDecl();
41   // Alignment can not be obtained for undefined type.
42   if (!D || !D->getDefinition() || !D->isCompleteDefinition())
43     return;
44 
45   ASTContext &Context = D->getASTContext();
46 
47   // Check if no alignment was specified for the type.
48   if (!Context.isAlignmentRequired(T))
49     return;
50 
51   // The user-specified alignment (in bits).
52   unsigned SpecifiedAlignment = D->getMaxAlignment();
53   // Double-check if no alignment was specified.
54   if (!SpecifiedAlignment)
55     return;
56   // The alignment used by default 'operator new' (in bits).
57   unsigned DefaultNewAlignment = Context.getTargetInfo().getNewAlign();
58 
59   bool OverAligned = SpecifiedAlignment > DefaultNewAlignment;
60   bool HasDefaultOperatorNew =
61       !NewExpr->getOperatorNew() || NewExpr->getOperatorNew()->isImplicit();
62 
63   unsigned CharWidth = Context.getTargetInfo().getCharWidth();
64   if (HasDefaultOperatorNew && OverAligned)
65     diag(NewExpr->getBeginLoc(),
66          "allocation function returns a pointer with alignment %0 but the "
67          "over-aligned type being allocated requires alignment %1")
68         << (DefaultNewAlignment / CharWidth)
69         << (SpecifiedAlignment / CharWidth);
70 }
71 
72 } // namespace cert
73 } // namespace tidy
74 } // namespace clang
75