brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.5 KiB · 567ade5 Raw
66 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "ImplementationInNamespaceCheck.h"10#include "NamespaceConstants.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::llvm_libc {16 17void ImplementationInNamespaceCheck::registerMatchers(MatchFinder *Finder) {18  Finder->addMatcher(19      translationUnitDecl(20          forEach(decl(isExpansionInMainFile(), unless(linkageSpecDecl()),21                       // anonymous namespaces generate usingDirective22                       unless(usingDirectiveDecl(isImplicit())))23                      .bind("child_of_translation_unit"))),24      this);25}26 27void ImplementationInNamespaceCheck::check(28    const MatchFinder::MatchResult &Result) {29  const auto *MatchedDecl =30      Result.Nodes.getNodeAs<Decl>("child_of_translation_unit");31  const auto *NS = dyn_cast<NamespaceDecl>(MatchedDecl);32 33  // LLVM libc declarations should be inside of a non-anonymous namespace.34  if (NS == nullptr || NS->isAnonymousNamespace()) {35    diag(MatchedDecl->getLocation(),36         "declaration must be enclosed within the '%0' namespace")37        << RequiredNamespaceDeclMacroName;38    return;39  }40 41  // Enforce that the namespace is the result of macro expansion42  if (Result.SourceManager->isMacroBodyExpansion(NS->getLocation()) == false) {43    diag(NS->getLocation(), "the outermost namespace should be the '%0' macro")44        << RequiredNamespaceDeclMacroName;45    return;46  }47 48  // We want the macro to have [[gnu::visibility("hidden")]] as a prefix, but49  // visibility is just an attribute in the AST construct, so we check that50  // instead.51  if (NS->getVisibility() != Visibility::HiddenVisibility) {52    diag(NS->getLocation(), "the '%0' macro should start with '%1'")53        << RequiredNamespaceDeclMacroName << RequiredNamespaceDeclStart;54    return;55  }56 57  // Lastly, make sure the namespace name actually has the __llvm_libc prefix58  if (NS->getName().starts_with(RequiredNamespaceRefStart) == false) {59    diag(NS->getLocation(), "the '%0' macro expansion should start with '%1'")60        << RequiredNamespaceDeclMacroName << RequiredNamespaceRefStart;61    return;62  }63}64 65} // namespace clang::tidy::llvm_libc66