1e8a4c74fSBalázs Kéri //===--- DefaultOperatorNewCheck.cpp - clang-tidy --------------------===// 2e8a4c74fSBalázs Kéri // 3e8a4c74fSBalázs Kéri // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8a4c74fSBalázs Kéri // See https://llvm.org/LICENSE.txt for license information. 5e8a4c74fSBalázs Kéri // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8a4c74fSBalázs Kéri // 7e8a4c74fSBalázs Kéri //===----------------------------------------------------------------------===// 8e8a4c74fSBalázs Kéri 9e8a4c74fSBalázs Kéri #include "DefaultOperatorNewAlignmentCheck.h" 10e8a4c74fSBalázs Kéri #include "clang/AST/ASTContext.h" 11e8a4c74fSBalázs Kéri #include "clang/ASTMatchers/ASTMatchFinder.h" 12d7c5037eSReid Kleckner #include "clang/Basic/TargetInfo.h" 13e8a4c74fSBalázs Kéri 14e8a4c74fSBalázs Kéri using namespace clang::ast_matchers; 15e8a4c74fSBalázs Kéri 16*7d2ea6c4SCarlos Galvez namespace clang::tidy::cert { 17e8a4c74fSBalázs Kéri registerMatchers(MatchFinder * Finder)18e8a4c74fSBalázs Kérivoid DefaultOperatorNewAlignmentCheck::registerMatchers(MatchFinder *Finder) { 19a156a0e2SNathan James Finder->addMatcher( 20a156a0e2SNathan James cxxNewExpr(unless(hasAnyPlacementArg(anything()))).bind("new"), this); 21e8a4c74fSBalázs Kéri } 22e8a4c74fSBalázs Kéri check(const MatchFinder::MatchResult & Result)23e8a4c74fSBalázs Kérivoid DefaultOperatorNewAlignmentCheck::check( 24e8a4c74fSBalázs Kéri const MatchFinder::MatchResult &Result) { 25e8a4c74fSBalázs Kéri // Get the found 'new' expression. 26e8a4c74fSBalázs Kéri const auto *NewExpr = Result.Nodes.getNodeAs<CXXNewExpr>("new"); 27e8a4c74fSBalázs Kéri 28e8a4c74fSBalázs Kéri QualType T = NewExpr->getAllocatedType(); 29e8a4c74fSBalázs Kéri // Dependent types do not have fixed alignment. 30e8a4c74fSBalázs Kéri if (T->isDependentType()) 31e8a4c74fSBalázs Kéri return; 32e8a4c74fSBalázs Kéri const TagDecl *D = T->getAsTagDecl(); 33e8a4c74fSBalázs Kéri // Alignment can not be obtained for undefined type. 34e8a4c74fSBalázs Kéri if (!D || !D->getDefinition() || !D->isCompleteDefinition()) 35e8a4c74fSBalázs Kéri return; 36e8a4c74fSBalázs Kéri 37e8a4c74fSBalázs Kéri ASTContext &Context = D->getASTContext(); 38e8a4c74fSBalázs Kéri 39e8a4c74fSBalázs Kéri // Check if no alignment was specified for the type. 40e8a4c74fSBalázs Kéri if (!Context.isAlignmentRequired(T)) 41e8a4c74fSBalázs Kéri return; 42e8a4c74fSBalázs Kéri 43e8a4c74fSBalázs Kéri // The user-specified alignment (in bits). 44e8a4c74fSBalázs Kéri unsigned SpecifiedAlignment = D->getMaxAlignment(); 45e8a4c74fSBalázs Kéri // Double-check if no alignment was specified. 46e8a4c74fSBalázs Kéri if (!SpecifiedAlignment) 47e8a4c74fSBalázs Kéri return; 48e8a4c74fSBalázs Kéri // The alignment used by default 'operator new' (in bits). 49e8a4c74fSBalázs Kéri unsigned DefaultNewAlignment = Context.getTargetInfo().getNewAlign(); 50e8a4c74fSBalázs Kéri 51e8a4c74fSBalázs Kéri bool OverAligned = SpecifiedAlignment > DefaultNewAlignment; 52e8a4c74fSBalázs Kéri bool HasDefaultOperatorNew = 53e8a4c74fSBalázs Kéri !NewExpr->getOperatorNew() || NewExpr->getOperatorNew()->isImplicit(); 54e8a4c74fSBalázs Kéri 55e8a4c74fSBalázs Kéri unsigned CharWidth = Context.getTargetInfo().getCharWidth(); 56e8a4c74fSBalázs Kéri if (HasDefaultOperatorNew && OverAligned) 57e8a4c74fSBalázs Kéri diag(NewExpr->getBeginLoc(), 58e8a4c74fSBalázs Kéri "allocation function returns a pointer with alignment %0 but the " 59e8a4c74fSBalázs Kéri "over-aligned type being allocated requires alignment %1") 60e8a4c74fSBalázs Kéri << (DefaultNewAlignment / CharWidth) 61e8a4c74fSBalázs Kéri << (SpecifiedAlignment / CharWidth); 62e8a4c74fSBalázs Kéri } 63e8a4c74fSBalázs Kéri 64*7d2ea6c4SCarlos Galvez } // namespace clang::tidy::cert 65