From 324f918438715b4a0d024af5930628c1674f4fcd Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sat, 19 Jan 2019 08:50:56 +0000 Subject: Update the file headers across all of the LLVM projects in the monorepo to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@351636 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/Analysis/CFGTest.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'unittests/Analysis/CFGTest.cpp') diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp index 768705f46f..7137454f3b 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 // //===----------------------------------------------------------------------===// -- cgit v1.2.3 From c208eda5d902a10fcbc85024a06a60f72fbed767 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Tue, 30 Apr 2019 03:01:02 +0000 Subject: [analyzer] Treat functions without run-time branches as "small". Currently we always inline functions that have no branches, i.e. have exactly three CFG blocks: ENTRY, some code, EXIT. This makes sense because when there are no branches, it means that there's no exponential complexity introduced by inlining such function. Such functions also don't trigger various fundamental problems with our inlining mechanism, such as the problem of inlined defensive checks. Sometimes the CFG may contain more blocks, but in practice it still has linear structure because all directions (except, at most, one) of all branches turned out to be unreachable. When this happens, still treat the function as "small". This is useful, in particular, for dealing with C++17 if constexpr. Differential Revision: https://reviews.llvm.org/D61051 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359531 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/Analysis/CFGTest.cpp | 59 ++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 14 deletions(-) (limited to 'unittests/Analysis/CFGTest.cpp') diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp index 7137454f3b..2c2522d262 100644 --- a/unittests/Analysis/CFGTest.cpp +++ b/unittests/Analysis/CFGTest.cpp @@ -17,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 = 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; }; 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("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::buildCFG(nullptr, Body, Result.Context, Options)) + TheBuildResult = {BuildResult::BuiltCFG, std::move(Cfg)}; } }; @@ -50,8 +64,8 @@ BuildResult BuildCFG(const char *Code) { tooling::newFrontendActionFactory(&Finder)); std::vector 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 @@ -63,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 @@ -73,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 @@ -83,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 -- cgit v1.2.3