brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.9 KiB · d6dfcaa Raw
85 lines · cpp
1#include "clang/ASTMatchers/ASTMatchFinder.h"2#include "clang/ASTMatchers/ASTMatchers.h"3#include "clang/Analysis/AnalysisDeclContext.h"4#include "clang/Frontend/ASTUnit.h"5#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"6#include "clang/Tooling/Tooling.h"7#include "gtest/gtest.h"8 9#include <memory>10 11using namespace clang;12using namespace ento;13using namespace ast_matchers;14 15class IsCLibraryFunctionTest : public testing::Test {16  std::unique_ptr<ASTUnit> ASTUnitP;17  const FunctionDecl *Result = nullptr;18 19public:20  const FunctionDecl *getFunctionDecl() const { return Result; }21 22  testing::AssertionResult buildAST(StringRef Code) {23    ASTUnitP = tooling::buildASTFromCode(Code);24    if (!ASTUnitP)25      return testing::AssertionFailure() << "AST construction failed";26 27    ASTContext &Context = ASTUnitP->getASTContext();28    if (Context.getDiagnostics().hasErrorOccurred())29      return testing::AssertionFailure() << "Compilation error";30 31    auto Matches = ast_matchers::match(functionDecl().bind("fn"), Context);32    if (Matches.empty())33      return testing::AssertionFailure() << "No function declaration found";34 35    if (Matches.size() > 1)36      return testing::AssertionFailure()37             << "Multiple function declarations found";38 39    Result = Matches[0].getNodeAs<FunctionDecl>("fn");40    return testing::AssertionSuccess();41  }42};43 44TEST_F(IsCLibraryFunctionTest, AcceptsGlobal) {45  ASSERT_TRUE(buildAST(R"cpp(void fun();)cpp"));46  EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl()));47}48 49TEST_F(IsCLibraryFunctionTest, AcceptsExternCGlobal) {50  ASSERT_TRUE(buildAST(R"cpp(extern "C" { void fun(); })cpp"));51  EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl()));52}53 54TEST_F(IsCLibraryFunctionTest, RejectsNoInlineNoExternalLinkage) {55  // Functions that are neither inlined nor externally visible cannot be C56  // library functions.57  ASSERT_TRUE(buildAST(R"cpp(static void fun();)cpp"));58  EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl()));59}60 61TEST_F(IsCLibraryFunctionTest, RejectsAnonymousNamespace) {62  ASSERT_TRUE(buildAST(R"cpp(namespace { void fun(); })cpp"));63  EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl()));64}65 66TEST_F(IsCLibraryFunctionTest, AcceptsStdNamespace) {67  ASSERT_TRUE(buildAST(R"cpp(namespace std { void fun(); })cpp"));68  EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl()));69}70 71TEST_F(IsCLibraryFunctionTest, RejectsOtherNamespaces) {72  ASSERT_TRUE(buildAST(R"cpp(namespace stdx { void fun(); })cpp"));73  EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl()));74}75 76TEST_F(IsCLibraryFunctionTest, RejectsClassStatic) {77  ASSERT_TRUE(buildAST(R"cpp(class A { static void fun(); };)cpp"));78  EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl()));79}80 81TEST_F(IsCLibraryFunctionTest, RejectsClassMember) {82  ASSERT_TRUE(buildAST(R"cpp(class A { void fun(); };)cpp"));83  EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl()));84}85