brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · e086ea3 Raw
152 lines · cpp
1//===- unittests/Analysis/FlowSensitive/ASTOpsTest.cpp --------------------===//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 "clang/Analysis/FlowSensitive/ASTOps.h"10#include "TestingSupport.h"11#include "clang/AST/Decl.h"12#include "clang/AST/DeclCXX.h"13#include "clang/ASTMatchers/ASTMatchers.h"14#include "clang/Basic/LLVM.h"15#include "clang/Frontend/ASTUnit.h"16#include "clang/Tooling/Tooling.h"17#include "gmock/gmock.h"18#include "gtest/gtest.h"19#include <memory>20#include <string>21 22namespace {23 24using namespace clang;25using namespace dataflow;26 27using ast_matchers::cxxMethodDecl;28using ast_matchers::cxxRecordDecl;29using ast_matchers::hasName;30using ast_matchers::hasType;31using ast_matchers::initListExpr;32using ast_matchers::match;33using ast_matchers::selectFirst;34using test::findValueDecl;35using testing::IsEmpty;36using testing::UnorderedElementsAre;37 38TEST(ASTOpsTest, RecordInitListHelperOnEmptyUnionInitList) {39  // This is a regression test: The `RecordInitListHelper` used to assert-fail40  // when called for the `InitListExpr` of an empty union.41  std::string Code = R"cc(42    struct S {43      S() : UField{} {};44 45      union U {} UField;46    };47  )cc";48  std::unique_ptr<ASTUnit> Unit =49      tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"});50  auto &ASTCtx = Unit->getASTContext();51 52  ASSERT_EQ(ASTCtx.getDiagnostics().getClient()->getNumErrors(), 0U);53 54  auto *InitList = selectFirst<InitListExpr>(55      "init",56      match(initListExpr(hasType(cxxRecordDecl(hasName("U")))).bind("init"),57            ASTCtx));58  ASSERT_NE(InitList, nullptr);59 60  RecordInitListHelper Helper(InitList);61  EXPECT_THAT(Helper.base_inits(), IsEmpty());62  EXPECT_THAT(Helper.field_inits(), IsEmpty());63}64 65TEST(ASTOpsTest, ReferencedDeclsOnUnionInitList) {66  // This is a regression test: `getReferencedDecls()` used to return a null67  // `FieldDecl` in this case (in addition to the correct non-null `FieldDecl`)68  // because `getInitializedFieldInUnion()` returns null for the syntactic form69  // of the `InitListExpr`.70  std::string Code = R"cc(71    struct S {72      S() : UField{0} {};73 74      union U {75        int I;76      } UField;77    };78  )cc";79  std::unique_ptr<ASTUnit> Unit =80      tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"});81  auto &ASTCtx = Unit->getASTContext();82 83  ASSERT_EQ(ASTCtx.getDiagnostics().getClient()->getNumErrors(), 0U);84 85  auto *InitList = selectFirst<InitListExpr>(86      "init",87      match(initListExpr(hasType(cxxRecordDecl(hasName("U")))).bind("init"),88            ASTCtx));89  ASSERT_NE(InitList, nullptr);90  auto *IDecl = cast<FieldDecl>(findValueDecl(ASTCtx, "I"));91 92  EXPECT_THAT(getReferencedDecls(*InitList).Fields,93              UnorderedElementsAre(IDecl));94}95 96TEST(ASTOpsTest, ReferencedDeclsLocalsNotParamsOrStatics) {97  std::string Code = R"cc(98    void func(int Param) {99      static int Static = 0;100      int Local = Param;101      Local = Static;102    }103  )cc";104  std::unique_ptr<ASTUnit> Unit =105      tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"});106  auto &ASTCtx = Unit->getASTContext();107 108  ASSERT_EQ(ASTCtx.getDiagnostics().getClient()->getNumErrors(), 0U);109 110  auto *Func = cast<FunctionDecl>(findValueDecl(ASTCtx, "func"));111  ASSERT_NE(Func, nullptr);112  auto *LocalDecl = cast<VarDecl>(findValueDecl(ASTCtx, "Local"));113 114  EXPECT_THAT(getReferencedDecls(*Func).Locals,115              UnorderedElementsAre(LocalDecl));116}117 118TEST(ASTOpsTest, LambdaCaptures) {119  std::string Code = R"cc(120    void func(int CapturedByRef, int CapturedByValue, int NotCaptured) {121    int Local;122      auto Lambda = [&CapturedByRef, CapturedByValue, &Local](int LambdaParam) {123      };124    }125  )cc";126  std::unique_ptr<ASTUnit> Unit =127      tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"});128  auto &ASTCtx = Unit->getASTContext();129 130  ASSERT_EQ(ASTCtx.getDiagnostics().getClient()->getNumErrors(), 0U);131 132  auto *LambdaCallOp = selectFirst<CXXMethodDecl>(133      "l", match(cxxMethodDecl(hasName("operator()")).bind("l"), ASTCtx));134  ASSERT_NE(LambdaCallOp, nullptr);135  auto *Func = cast<FunctionDecl>(findValueDecl(ASTCtx, "func"));136  ASSERT_NE(Func, nullptr);137  auto *CapturedByRefDecl = Func->getParamDecl(0);138  ASSERT_NE(CapturedByRefDecl, nullptr);139  auto *CapturedByValueDecl = Func->getParamDecl(1);140  ASSERT_NE(CapturedByValueDecl, nullptr);141 142  EXPECT_THAT(getReferencedDecls(*Func).LambdaCapturedParams, IsEmpty());143  ReferencedDecls ForLambda = getReferencedDecls(*LambdaCallOp);144  EXPECT_THAT(ForLambda.LambdaCapturedParams,145              UnorderedElementsAre(CapturedByRefDecl, CapturedByValueDecl));146  // Captured locals must be seen in the body for them to appear in147  // ReferencedDecls.148  EXPECT_THAT(ForLambda.Locals, IsEmpty());149}150 151} // namespace152