diff options
author | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
---|---|---|
committer | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
commit | b35a2aa71f76a334a9c98c0a3c3995b5d902d2b9 (patch) | |
tree | cdff4a5d1a715d4ad622fd8f190128b54bebe440 /unittests/Analysis | |
parent | 3748d41833787fcbf59cc5624e8d2b042a8991bc (diff) | |
parent | 741e05796da92b46d4f7bcbee00702ff37df6489 (diff) |
Creating branches/google/stable and tags/google/stable/2019-05-14 from r360103upstream/google/stable
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/google/stable@360714 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/Analysis')
-rw-r--r-- | unittests/Analysis/CFGTest.cpp | 66 | ||||
-rw-r--r-- | unittests/Analysis/CloneDetectionTest.cpp | 7 | ||||
-rw-r--r-- | unittests/Analysis/ExprMutationAnalyzerTest.cpp | 157 |
3 files changed, 204 insertions, 26 deletions
diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp index 768705f46f..2c2522d262 100644 --- a/unittests/Analysis/CFGTest.cpp +++ b/unittests/Analysis/CFGTest.cpp @@ -1,9 +1,8 @@ //===- unittests/Analysis/CFGTest.cpp - CFG tests -------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -18,27 +17,41 @@ namespace clang { namespace analysis { namespace { -enum BuildResult { - ToolFailed, - ToolRan, - SawFunctionBody, - BuiltCFG, +class BuildResult { +public: + enum Status { + ToolFailed, + ToolRan, + SawFunctionBody, + BuiltCFG, + }; + + BuildResult(Status S, std::unique_ptr<CFG> Cfg = nullptr) + : S(S), Cfg(std::move(Cfg)) {} + + Status getStatus() const { return S; } + CFG *getCFG() const { return Cfg.get(); } + +private: + Status S; + std::unique_ptr<CFG> Cfg; }; class CFGCallback : public ast_matchers::MatchFinder::MatchCallback { public: - BuildResult TheBuildResult = ToolRan; + BuildResult TheBuildResult = BuildResult::ToolRan; void run(const ast_matchers::MatchFinder::MatchResult &Result) override { const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func"); Stmt *Body = Func->getBody(); if (!Body) return; - TheBuildResult = SawFunctionBody; + TheBuildResult = BuildResult::SawFunctionBody; CFG::BuildOptions Options; Options.AddImplicitDtors = true; - if (CFG::buildCFG(nullptr, Body, Result.Context, Options)) - TheBuildResult = BuiltCFG; + if (std::unique_ptr<CFG> Cfg = + CFG::buildCFG(nullptr, Body, Result.Context, Options)) + TheBuildResult = {BuildResult::BuiltCFG, std::move(Cfg)}; } }; @@ -51,8 +64,8 @@ BuildResult BuildCFG(const char *Code) { tooling::newFrontendActionFactory(&Finder)); std::vector<std::string> Args = {"-std=c++11", "-fno-delayed-template-parsing"}; if (!tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args)) - return ToolFailed; - return Callback.TheBuildResult; + return BuildResult::ToolFailed; + return std::move(Callback.TheBuildResult); } // Constructing a CFG for a range-based for over a dependent type fails (but @@ -64,7 +77,7 @@ TEST(CFG, RangeBasedForOverDependentType) { " for (const Foo *TheFoo : Range) {\n" " }\n" "}\n"; - EXPECT_EQ(SawFunctionBody, BuildCFG(Code)); + EXPECT_EQ(BuildResult::SawFunctionBody, BuildCFG(Code).getStatus()); } // Constructing a CFG containing a delete expression on a dependent type should @@ -74,7 +87,7 @@ TEST(CFG, DeleteExpressionOnDependentType) { "void f(T t) {\n" " delete t;\n" "}\n"; - EXPECT_EQ(BuiltCFG, BuildCFG(Code)); + EXPECT_EQ(BuildResult::BuiltCFG, BuildCFG(Code).getStatus()); } // Constructing a CFG on a function template with a variable of incomplete type @@ -84,7 +97,24 @@ TEST(CFG, VariableOfIncompleteType) { " class Undefined;\n" " Undefined u;\n" "}\n"; - EXPECT_EQ(BuiltCFG, BuildCFG(Code)); + EXPECT_EQ(BuildResult::BuiltCFG, BuildCFG(Code).getStatus()); +} + +TEST(CFG, IsLinear) { + auto expectLinear = [](bool IsLinear, const char *Code) { + BuildResult B = BuildCFG(Code); + EXPECT_EQ(BuildResult::BuiltCFG, B.getStatus()); + EXPECT_EQ(IsLinear, B.getCFG()->isLinear()); + }; + + expectLinear(true, "void foo() {}"); + expectLinear(true, "void foo() { if (true) return; }"); + expectLinear(true, "void foo() { if constexpr (false); }"); + expectLinear(false, "void foo(bool coin) { if (coin) return; }"); + expectLinear(false, "void foo() { for(;;); }"); + expectLinear(false, "void foo() { do {} while (true); }"); + expectLinear(true, "void foo() { do {} while (false); }"); + expectLinear(true, "void foo() { foo(); }"); // Recursion is not our problem. } } // namespace diff --git a/unittests/Analysis/CloneDetectionTest.cpp b/unittests/Analysis/CloneDetectionTest.cpp index 965a4bc308..03b63c4004 100644 --- a/unittests/Analysis/CloneDetectionTest.cpp +++ b/unittests/Analysis/CloneDetectionTest.cpp @@ -1,9 +1,8 @@ //===- unittests/Analysis/CloneDetectionTest.cpp - Clone detection tests --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/unittests/Analysis/ExprMutationAnalyzerTest.cpp b/unittests/Analysis/ExprMutationAnalyzerTest.cpp index 68c921e439..2c22a5cf9e 100644 --- a/unittests/Analysis/ExprMutationAnalyzerTest.cpp +++ b/unittests/Analysis/ExprMutationAnalyzerTest.cpp @@ -1,9 +1,8 @@ //===---------- ExprMutationAnalyzerTest.cpp ------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -882,6 +881,137 @@ TEST(ExprMutationAnalyzerTest, CastToConstRef) { EXPECT_FALSE(isMutated(Results, AST.get())); } +TEST(ExprMutationAnalyzerTest, CommaExprWithAnAssigment) { + const auto AST = + buildASTFromCodeWithArgs("void f() { int x; int y; (x, y) = 5; }", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("y")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprWithDecOp) { + const auto AST = + buildASTFromCodeWithArgs("void f() { int x; int y; (x, y)++; }", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("y")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprWithNonConstMemberCall) { + const auto AST = + buildASTFromCodeWithArgs("class A { public: int mem; void f() { mem ++; } };" + "void fn() { A o1, o2; (o1, o2).f(); }", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("o2")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprWithConstMemberCall) { + const auto AST = + buildASTFromCodeWithArgs("class A { public: int mem; void f() const { } };" + "void fn() { A o1, o2; (o1, o2).f(); }", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("o2")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprWithCallExpr) { + const auto AST = + buildASTFromCodeWithArgs("class A { public: int mem; void f(A &O1) {} };" + "void fn() { A o1, o2; o2.f((o2, o1)); }", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("o1")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprWithCallUnresolved) { + auto AST = buildASTFromCodeWithArgs( + "template <class T> struct S;" + "template <class T> void f() { S<T> s; int x, y; s.mf((y, x)); }", + {"-fno-delayed-template-parsing", "-Wno-unused-value"}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); + + AST = buildASTFromCodeWithArgs( + "template <class T> void f(T t) { int x, y; g(t, (y, x)); }", + {"-fno-delayed-template-parsing", "-Wno-unused-value"}); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprParmRef) { + const auto AST = + buildASTFromCodeWithArgs("class A { public: int mem;};" + "extern void fn(A &o1);" + "void fn2 () { A o1, o2; fn((o2, o1)); } ", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("o1")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprWithAmpersandOp) { + const auto AST = + buildASTFromCodeWithArgs("class A { public: int mem;};" + "void fn () { A o1, o2;" + "void *addr = &(o2, o1); } ", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("o1")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprAsReturnAsValue) { + auto AST = buildASTFromCodeWithArgs("int f() { int x, y; return (x, y); }", + {"-Wno-unused-value"}); + auto Results = + match(withEnclosingCompound(declRefTo("y")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaEpxrAsReturnAsNonConstRef) { + const auto AST = + buildASTFromCodeWithArgs("int& f() { int x, y; return (y, x); }", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprAsArrayToPointerDecay) { + const auto AST = + buildASTFromCodeWithArgs("void g(int*); " + "void f() { int x[2], y[2]; g((y, x)); }", + {"-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + +TEST(ExprMutationAnalyzerTest, CommaExprAsUniquePtr) { + const std::string UniquePtrDef = + "template <class T> struct UniquePtr {" + " UniquePtr();" + " UniquePtr(const UniquePtr&) = delete;" + " T& operator*() const;" + " T* operator->() const;" + "};"; + const auto AST = buildASTFromCodeWithArgs( + UniquePtrDef + "template <class T> void f() " + "{ UniquePtr<T> x; UniquePtr<T> y;" + " (y, x)->mf(); }", + {"-fno-delayed-template-parsing", "-Wno-unused-value"}); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isMutated(Results, AST.get())); +} + TEST(ExprMutationAnalyzerTest, LambdaDefaultCaptureByValue) { const auto AST = buildASTFromCode("void f() { int x; [=]() { x; }; }"); const auto Results = @@ -1109,4 +1239,23 @@ TEST(ExprMutationAnalyzerTest, UniquePtr) { EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x->mf()")); } +TEST(ExprMutationAnalyzerTest, ReproduceFailureMinimal) { + const std::string Reproducer = + "namespace std {" + "template <class T> T forward(T & A) { return static_cast<T&&>(A); }" + "template <class T> struct __bind {" + " T f;" + " template <class V> __bind(T v, V &&) : f(forward(v)) {}" + "};" + "}" + "void f() {" + " int x = 42;" + " auto Lambda = [] {};" + " std::__bind<decltype(Lambda)>(Lambda, x);" + "}"; + auto AST11 = buildASTFromCodeWithArgs(Reproducer, {"-std=c++11"}); + auto Results11 = + match(withEnclosingCompound(declRefTo("x")), AST11->getASTContext()); + EXPECT_FALSE(isMutated(Results11, AST11.get())); +} } // namespace clang |