brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · fed2d25 Raw
198 lines · cpp
1//===- unittests/Frontend/NoAlterCodeGenActionTest.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// Unit tests for CodeGenAction may not alter the AST.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTConsumer.h"14#include "clang/AST/RecursiveASTVisitor.h"15#include "clang/Basic/LangStandard.h"16#include "clang/CodeGen/BackendUtil.h"17#include "clang/CodeGen/CodeGenAction.h"18#include "clang/Frontend/CompilerInstance.h"19#include "clang/Frontend/MultiplexConsumer.h"20#include "clang/Lex/PreprocessorOptions.h"21#include "clang/Tooling/Tooling.h"22#include "llvm/Support/FormatVariadic.h"23#include "llvm/Support/VirtualFileSystem.h"24#include "gtest/gtest.h"25 26using namespace llvm;27using namespace clang;28using namespace clang::frontend;29using namespace clang::tooling;30 31namespace {32 33class ASTChecker : public RecursiveASTVisitor<ASTChecker> {34public:35  ASTContext &Ctx;36  ASTChecker(ASTContext &Ctx) : Ctx(Ctx) {}37  bool VisitReturnStmt(ReturnStmt *RS) {38    EXPECT_TRUE(RS->getRetValue());39    return true;40  }41 42  bool VisitCoroutineBodyStmt(CoroutineBodyStmt *CS) {43    return VisitReturnStmt(cast<ReturnStmt>(CS->getReturnStmt()));44  }45};46 47class ASTCheckerConsumer : public ASTConsumer {48public:49  void HandleTranslationUnit(ASTContext &Ctx) override {50    ASTChecker Checker(Ctx);51    Checker.TraverseAST(Ctx);52  }53};54 55class TestCodeGenAction : public EmitLLVMOnlyAction {56public:57  using Base = EmitLLVMOnlyAction;58  using Base::Base;59 60  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,61                                                 StringRef InFile) override {62    std::vector<std::unique_ptr<ASTConsumer>> Consumers;63    Consumers.push_back(std::make_unique<ASTCheckerConsumer>());64    Consumers.push_back(Base::CreateASTConsumer(CI, InFile));65    return std::make_unique<MultiplexConsumer>(std::move(Consumers));66  }67};68 69const char *test_contents = R"cpp(70 71namespace std {72 73template <typename R, typename...> struct coroutine_traits {74  using promise_type = typename R::promise_type;75};76 77template <typename Promise = void> struct coroutine_handle;78 79template <> struct coroutine_handle<void> {80  static coroutine_handle from_address(void *addr) noexcept;81  void operator()() { resume(); }82  void *address() const noexcept;83  void resume() const { __builtin_coro_resume(ptr); }84  void destroy() const { __builtin_coro_destroy(ptr); }85  bool done() const;86  coroutine_handle &operator=(decltype(nullptr));87  coroutine_handle(decltype(nullptr)) : ptr(nullptr) {}88  coroutine_handle() : ptr(nullptr) {}89//  void reset() { ptr = nullptr; } // add to P0057?90  explicit operator bool() const;91 92protected:93  void *ptr;94};95 96template <typename Promise> struct coroutine_handle : coroutine_handle<> {97  using coroutine_handle<>::operator=;98 99  static coroutine_handle from_address(void *addr) noexcept;100 101  Promise &promise() const;102  static coroutine_handle from_promise(Promise &promise);103};104 105template <typename _PromiseT>106bool operator==(coroutine_handle<_PromiseT> const &_Left,107                coroutine_handle<_PromiseT> const &_Right) noexcept {108  return _Left.address() == _Right.address();109}110 111template <typename _PromiseT>112bool operator!=(coroutine_handle<_PromiseT> const &_Left,113                coroutine_handle<_PromiseT> const &_Right) noexcept {114  return !(_Left == _Right);115}116 117struct noop_coroutine_promise {};118 119template <>120struct coroutine_handle<noop_coroutine_promise> {121  operator coroutine_handle<>() const noexcept;122 123  constexpr explicit operator bool() const noexcept { return true; }124  constexpr bool done() const noexcept { return false; }125 126  constexpr void operator()() const noexcept {}127  constexpr void resume() const noexcept {}128  constexpr void destroy() const noexcept {}129 130  noop_coroutine_promise &promise() const noexcept {131    return *static_cast<noop_coroutine_promise *>(132        __builtin_coro_promise(this->__handle_, alignof(noop_coroutine_promise), false));133  }134 135  constexpr void *address() const noexcept { return __handle_; }136 137private:138  friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;139 140  coroutine_handle() noexcept {141    this->__handle_ = __builtin_coro_noop();142  }143 144  void *__handle_ = nullptr;145};146 147using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;148 149inline noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); }150 151struct suspend_always {152  bool await_ready() noexcept { return false; }153  void await_suspend(coroutine_handle<>) noexcept {}154  void await_resume() noexcept {}155};156struct suspend_never {157  bool await_ready() noexcept { return true; }158  void await_suspend(coroutine_handle<>) noexcept {}159  void await_resume() noexcept {}160};161 162} // namespace std163 164using namespace std;165 166class invoker {167public:168  class invoker_promise {169  public:170    invoker get_return_object() { return invoker{}; }171    auto initial_suspend() { return suspend_always{}; }172    auto final_suspend() noexcept { return suspend_always{}; }173    void return_void() {}174    void unhandled_exception() {}175  };176  using promise_type = invoker_promise;177  invoker() {}178  invoker(const invoker &) = delete;179  invoker &operator=(const invoker &) = delete;180  invoker(invoker &&) = delete;181  invoker &operator=(invoker &&) = delete;182};183 184invoker g() {185  co_return;186}187 188)cpp";189 190TEST(CodeGenTest, TestNonAlterTest) {191  EXPECT_TRUE(runToolOnCodeWithArgs(std::make_unique<TestCodeGenAction>(),192                                    test_contents,193                                    {194                                        "-std=c++20",195                                    }));196}197} // namespace198