[𝘀𝗽𝗿] changes introduced through rebase

Created using spr 1.3.6

[skip ci]
This commit is contained in:
Aiden Grossman 2025-08-18 14:05:53 +00:00
commit 95edd82041
1201 changed files with 15856 additions and 7770 deletions

View File

@ -2517,7 +2517,7 @@ BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) {
// Clean-up the effect of the code emission.
for (const MCSymbol &Symbol : Assembler.symbols()) {
MCSymbol *MutableSymbol = const_cast<MCSymbol *>(&Symbol);
MutableSymbol->setUndefined();
MutableSymbol->setFragment(nullptr);
MutableSymbol->setIsRegistered(false);
}

View File

@ -662,7 +662,7 @@ Error CleanMCState::runOnFunctions(BinaryContext &BC) {
if (S->isDefined()) {
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName()
<< "\" is already defined\n");
const_cast<MCSymbol *>(S)->setUndefined();
const_cast<MCSymbol *>(S)->setFragment(nullptr);
}
if (S->isRegistered()) {
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName()

View File

@ -424,6 +424,10 @@ ClangTidyASTConsumerFactory::createASTConsumer(
FinderOptions.CheckProfiling.emplace(Profiling->Records);
}
// Avoid processing system headers, unless the user explicitly requests it
if (!Context.getOptions().SystemHeaders.value_or(false))
FinderOptions.IgnoreSystemHeaders = true;
std::unique_ptr<ast_matchers::MatchFinder> Finder(
new ast_matchers::MatchFinder(std::move(FinderOptions)));

View File

@ -191,6 +191,9 @@ void PreferMemberInitializerCheck::check(
if (!AssignmentToMember)
continue;
const FieldDecl *Field = AssignmentToMember->Field;
// Skip if the field is inherited from a base class.
if (Field->getParent() != Class)
continue;
const Expr *InitValue = AssignmentToMember->Init;
updateAssignmentLevel(Field, InitValue, Ctor, AssignedFields);
if (!canAdvanceAssignment(AssignedFields[Field]))

View File

@ -32,6 +32,7 @@ add_clang_library(clangTidyMiscModule STATIC
NoRecursionCheck.cpp
NonCopyableObjects.cpp
NonPrivateMemberVariablesInClassesCheck.cpp
OverrideWithDifferentVisibilityCheck.cpp
RedundantExpressionCheck.cpp
StaticAssertCheck.cpp
ThrowByValueCatchByReferenceCheck.cpp

View File

@ -22,6 +22,7 @@
#include "NoRecursionCheck.h"
#include "NonCopyableObjects.h"
#include "NonPrivateMemberVariablesInClassesCheck.h"
#include "OverrideWithDifferentVisibilityCheck.h"
#include "RedundantExpressionCheck.h"
#include "StaticAssertCheck.h"
#include "ThrowByValueCatchByReferenceCheck.h"
@ -81,6 +82,8 @@ public:
"misc-use-anonymous-namespace");
CheckFactories.registerCheck<UseInternalLinkageCheck>(
"misc-use-internal-linkage");
CheckFactories.registerCheck<OverrideWithDifferentVisibilityCheck>(
"misc-override-with-different-visibility");
}
};

View File

@ -0,0 +1,150 @@
//===--- OverrideWithDifferentVisibilityCheck.cpp - clang-tidy ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "OverrideWithDifferentVisibilityCheck.h"
#include "../utils/Matchers.h"
#include "../utils/OptionsUtils.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
using namespace clang;
namespace {
AST_MATCHER(NamedDecl, isOperatorDecl) {
DeclarationName::NameKind const NK = Node.getDeclName().getNameKind();
return NK != DeclarationName::Identifier &&
NK != DeclarationName::CXXConstructorName &&
NK != DeclarationName::CXXDestructorName;
}
} // namespace
namespace clang::tidy {
template <>
struct OptionEnumMapping<
misc::OverrideWithDifferentVisibilityCheck::ChangeKind> {
static llvm::ArrayRef<std::pair<
misc::OverrideWithDifferentVisibilityCheck::ChangeKind, StringRef>>
getEnumMapping() {
static constexpr std::pair<
misc::OverrideWithDifferentVisibilityCheck::ChangeKind, StringRef>
Mapping[] = {
{misc::OverrideWithDifferentVisibilityCheck::ChangeKind::Any,
"any"},
{misc::OverrideWithDifferentVisibilityCheck::ChangeKind::Widening,
"widening"},
{misc::OverrideWithDifferentVisibilityCheck::ChangeKind::Narrowing,
"narrowing"},
};
return {Mapping};
}
};
namespace misc {
OverrideWithDifferentVisibilityCheck::OverrideWithDifferentVisibilityCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
DetectVisibilityChange(
Options.get("DisallowedVisibilityChange", ChangeKind::Any)),
CheckDestructors(Options.get("CheckDestructors", false)),
CheckOperators(Options.get("CheckOperators", false)),
IgnoredFunctions(utils::options::parseStringList(
Options.get("IgnoredFunctions", ""))) {}
void OverrideWithDifferentVisibilityCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "DisallowedVisibilityChange", DetectVisibilityChange);
Options.store(Opts, "CheckDestructors", CheckDestructors);
Options.store(Opts, "CheckOperators", CheckOperators);
Options.store(Opts, "IgnoredFunctions",
utils::options::serializeStringList(IgnoredFunctions));
}
void OverrideWithDifferentVisibilityCheck::registerMatchers(
MatchFinder *Finder) {
const auto IgnoredDecl =
namedDecl(matchers::matchesAnyListedName(IgnoredFunctions));
const auto FilterDestructors =
CheckDestructors ? decl() : decl(unless(cxxDestructorDecl()));
const auto FilterOperators =
CheckOperators ? namedDecl() : namedDecl(unless(isOperatorDecl()));
Finder->addMatcher(
cxxMethodDecl(
isVirtual(), FilterDestructors, FilterOperators,
ofClass(
cxxRecordDecl(unless(isExpansionInSystemHeader())).bind("class")),
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")),
unless(IgnoredDecl))
.bind("base_func")))
.bind("func"),
this);
}
void OverrideWithDifferentVisibilityCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *const MatchedFunction =
Result.Nodes.getNodeAs<FunctionDecl>("func");
if (!MatchedFunction->isCanonicalDecl())
return;
const auto *const ParentClass =
Result.Nodes.getNodeAs<CXXRecordDecl>("class");
const auto *const BaseClass = Result.Nodes.getNodeAs<CXXRecordDecl>("base");
CXXBasePaths Paths;
if (!ParentClass->isDerivedFrom(BaseClass, Paths))
return;
const auto *const OverriddenFunction =
Result.Nodes.getNodeAs<FunctionDecl>("base_func");
AccessSpecifier const ActualAccess = MatchedFunction->getAccess();
AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
for (const CXXBasePath &Path : Paths) {
for (const CXXBasePathElement &Elem : Path) {
if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
OverriddenAccess = Elem.Base->getAccessSpecifier();
InheritanceWithStrictVisibility = Elem.Base;
}
}
}
if (ActualAccess != OverriddenAccess) {
if (DetectVisibilityChange == ChangeKind::Widening &&
ActualAccess > OverriddenAccess)
return;
if (DetectVisibilityChange == ChangeKind::Narrowing &&
ActualAccess < OverriddenAccess)
return;
if (InheritanceWithStrictVisibility) {
diag(MatchedFunction->getLocation(),
"visibility of function %0 is changed from %1 (through %1 "
"inheritance of class %2) to %3")
<< MatchedFunction << OverriddenAccess
<< InheritanceWithStrictVisibility->getType() << ActualAccess;
diag(InheritanceWithStrictVisibility->getBeginLoc(),
"%0 is inherited as %1 here", DiagnosticIDs::Note)
<< InheritanceWithStrictVisibility->getType() << OverriddenAccess;
} else {
diag(MatchedFunction->getLocation(),
"visibility of function %0 is changed from %1 in class %2 to %3")
<< MatchedFunction << OverriddenAccess << BaseClass << ActualAccess;
}
diag(OverriddenFunction->getLocation(), "function declared here as %0",
DiagnosticIDs::Note)
<< OverriddenFunction->getAccess();
}
}
} // namespace misc
} // namespace clang::tidy

View File

@ -0,0 +1,43 @@
//===--- OverrideWithDifferentVisibilityCheck.h - clang-tidy --*- C++ -*---===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OVERRIDEWITHDIFFERENTVISIBILITYCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OVERRIDEWITHDIFFERENTVISIBILITYCHECK_H
#include "../ClangTidyCheck.h"
namespace clang::tidy::misc {
/// Finds virtual function overrides with different visibility than the function
/// in the base class.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/misc/override-with-different-visibility.html
class OverrideWithDifferentVisibilityCheck : public ClangTidyCheck {
public:
enum class ChangeKind { Any, Widening, Narrowing };
OverrideWithDifferentVisibilityCheck(StringRef Name,
ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}
private:
ChangeKind DetectVisibilityChange;
bool CheckDestructors;
bool CheckOperators;
std::vector<llvm::StringRef> IgnoredFunctions;
};
} // namespace clang::tidy::misc
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OVERRIDEWITHDIFFERENTVISIBILITYCHECK_H

View File

@ -28,6 +28,7 @@ import glob
import json
import multiprocessing
import os
import queue
import re
import shutil
import subprocess
@ -42,13 +43,6 @@ try:
except ImportError:
yaml = None
is_py2 = sys.version[0] == "2"
if is_py2:
import Queue as queue
else:
import queue as queue
def run_tidy(task_queue, lock, timeout, failed_files):
watchdog = None

View File

@ -104,6 +104,10 @@ Improvements to clang-query
Improvements to clang-tidy
--------------------------
- :program:`clang-tidy` no longer attemps to analyze code from system headers
by default, greatly improving performance. This behavior is disabled if the
`SystemHeaders` option is enabled.
- The :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` scripts
now run checks in parallel by default using all available hardware threads.
Both scripts display the number of threads being used in their output.
@ -130,6 +134,12 @@ New checks
Checks for uses of MLIR's old/to be deprecated ``OpBuilder::create<T>`` form
and suggests using ``T::create`` instead.
- New :doc:`misc-override-with-different-visibility
<clang-tidy/checks/misc/override-with-different-visibility>` check.
Finds virtual function overrides with different visibility than the function
in the base class.
New check aliases
^^^^^^^^^^^^^^^^^
@ -163,6 +173,10 @@ Changes in existing checks
an additional matcher that generalizes the copy-and-swap idiom pattern
detection.
- Improved :doc:`cppcoreguidelines-prefer-member-initializer
<clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>` check to
avoid false positives on inherited members in class templates.
- Improved :doc:`misc-header-include-cycle
<clang-tidy/checks/misc/header-include-cycle>` check performance.

View File

@ -271,6 +271,7 @@ Clang-Tidy Checks
:doc:`misc-no-recursion <misc/no-recursion>`,
:doc:`misc-non-copyable-objects <misc/non-copyable-objects>`,
:doc:`misc-non-private-member-variables-in-classes <misc/non-private-member-variables-in-classes>`,
:doc:`misc-override-with-different-visibility <misc/override-with-different-visibility>`,
:doc:`misc-redundant-expression <misc/redundant-expression>`, "Yes"
:doc:`misc-static-assert <misc/static-assert>`, "Yes"
:doc:`misc-throw-by-value-catch-by-reference <misc/throw-by-value-catch-by-reference>`,

View File

@ -0,0 +1,87 @@
.. title:: clang-tidy - misc-override-with-different-visibility
misc-override-with-different-visibility
=======================================
Finds virtual function overrides with different visibility than the function
in the base class. This includes for example if a virtual function declared as
``private`` is overridden and declared as ``public`` in a subclass. The detected
change is the modification of visibility resulting from keywords ``public``,
``protected``, ``private`` at overridden virtual functions. The check applies to
any normal virtual function and optionally to destructors or operators. Use of
the ``using`` keyword is not considered as visibility change by this check.
.. code-block:: c++
class A {
public:
virtual void f_pub();
private:
virtual void f_priv();
};
class B: public A {
public:
void f_priv(); // warning: changed visibility from private to public
private:
void f_pub(); // warning: changed visibility from public to private
};
class C: private A {
// no warning: f_pub becomes private in this case but this is from the
// private inheritance
};
class D: private A {
public:
void f_pub(); // warning: changed visibility from private to public
// 'f_pub' would have private access but is forced to be
// public
};
If the visibility is changed in this way, it can indicate bad design or
programming error.
If a virtual function is private in a subclass but public in the base class, it
can still be accessed from a pointer to the subclass if the pointer is converted
to the base type. Probably private inheritance can be used instead.
A protected virtual function that is made public in a subclass may have valid
use cases but similar (not exactly same) effect can be achieved with the
``using`` keyword.
Options
-------
.. option:: DisallowedVisibilityChange
Controls what kind of change to the visibility will be detected by the check.
Possible values are `any`, `widening`, `narrowing`. For example the
`widening` option will produce warning only if the visibility is changed
from more restrictive (``private``) to less restrictive (``public``).
Default value is `any`.
.. option:: CheckDestructors
If `true`, the check does apply to destructors too. Otherwise destructors
are ignored by the check.
Default value is `false`.
.. option:: CheckOperators
If `true`, the check does apply to overloaded C++ operators (as virtual
member functions) too. This includes other special member functions (like
conversions) too. This option is probably useful only in rare cases because
operators and conversions are not often virtual functions.
Default value is `false`.
.. option:: IgnoredFunctions
This option can be used to ignore the check at specific functions.
To configure this option, a semicolon-separated list of function names
should be provided. The list can contain regular expressions, in this way it
is possible to select all functions of a specific class (like `MyClass::.*`)
or a specific function of any class (like `my_function` or
`::.*::my_function`). The function names are matched at the base class.
Default value is empty string.

View File

@ -111,6 +111,13 @@ Diagnostics which have a corresponding warning option, are named
``-Wliteral-conversion`` will be reported with check name
``clang-diagnostic-literal-conversion``.
Clang compiler errors (such as syntax errors, semantic errors, or other failures
that prevent Clang from compiling the code) are reported with the check name
``clang-diagnostic-error``. These represent fundamental compilation failures that
must be fixed before :program:`clang-tidy` can perform its analysis. Unlike other
diagnostics, ``clang-diagnostic-error`` cannot be disabled, as :program:`clang-tidy`
requires valid code to function.
The ``-fix`` flag instructs :program:`clang-tidy` to fix found errors if
supported by corresponding checks.

View File

@ -650,3 +650,16 @@ struct InitFromBindingDecl {
}
};
} // namespace GH82970
struct A {
int m;
};
struct B : A {
B() { m = 0; }
};
template <class T>
struct C : A {
C() { m = 0; }
};

View File

@ -0,0 +1,14 @@
#pragma clang system_header
namespace sys {
struct Base {
virtual void publicF();
};
struct Derived: public Base {
private:
void publicF() override;
};
}

View File

@ -0,0 +1,60 @@
// RUN: %check_clang_tidy %s misc-override-with-different-visibility %t -- \
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.IgnoredFunctions: 'IgnoreAlways::.*;::a::IgnoreSelected::.*;IgnoreFunctions::f1;ignored_f'}}"
class IgnoreAlways {
virtual void f();
};
class IgnoreSelected {
virtual void f();
};
namespace a {
class IgnoreAlways {
virtual void f();
};
class IgnoreSelected {
virtual void f();
};
}
namespace ignore_always {
class Test1: public IgnoreAlways {
public:
void f();
void ignored_f(int);
};
class Test2: public a::IgnoreAlways {
public:
void f();
};
}
namespace ignore_selected {
class Test1: public IgnoreSelected {
public:
void f();
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'f'
// CHECK-MESSAGES: :9:16: note: function declared here
void ignored_f(int);
};
class Test2: public a::IgnoreSelected {
public:
void f();
};
}
class IgnoreFunctions {
virtual void f1();
virtual void f2();
virtual void ignored_f();
};
class IgnoreFunctionsTest: public IgnoreFunctions {
public:
void f1();
void f2();
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'f2'
// CHECK-MESSAGES: :[[@LINE-9]]:16: note: function declared here
void ignored_f();
};

View File

@ -0,0 +1,75 @@
// RUN: %check_clang_tidy -check-suffixes=DTORS,WIDENING,NARROWING %s misc-override-with-different-visibility %t -- \
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.CheckDestructors: true}}"
// RUN: %check_clang_tidy -check-suffixes=OPS,WIDENING,NARROWING %s misc-override-with-different-visibility %t -- \
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.CheckOperators: true}}"
// RUN: %check_clang_tidy -check-suffixes=WIDENING %s misc-override-with-different-visibility %t -- \
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.DisallowedVisibilityChange: 'widening'}}"
// RUN: %check_clang_tidy -check-suffixes=NARROWING %s misc-override-with-different-visibility %t -- \
// RUN: -config="{CheckOptions: {misc-override-with-different-visibility.DisallowedVisibilityChange: 'narrowing'}}"
namespace test_change {
class A {
protected:
virtual void f1();
virtual void f2();
};
class B: public A {
public:
void f1();
// CHECK-MESSAGES-WIDENING: :[[@LINE-1]]:8: warning: visibility of function 'f1'
// CHECK-MESSAGES-WIDENING: :[[@LINE-8]]:16: note: function declared here
private:
void f2();
// CHECK-MESSAGES-NARROWING: :[[@LINE-1]]:8: warning: visibility of function 'f2'
// CHECK-MESSAGES-NARROWING: :[[@LINE-11]]:16: note: function declared here
};
}
namespace test_destructor {
class A {
public:
virtual ~A();
};
class B: public A {
protected:
~B();
// CHECK-MESSAGES-DTORS: :[[@LINE-1]]:3: warning: visibility of function '~B'
// CHECK-MESSAGES-DTORS: :[[@LINE-7]]:11: note: function declared here
};
}
namespace test_operator {
class A {
virtual A& operator=(const A&);
virtual A& operator++();
virtual int operator()(int);
virtual operator double() const;
};
class B: public A {
protected:
A& operator=(const A&);
// CHECK-MESSAGES-OPS: :[[@LINE-1]]:6: warning: visibility of function 'operator='
// CHECK-MESSAGES-OPS: :[[@LINE-10]]:14: note: function declared here
A& operator++();
// CHECK-MESSAGES-OPS: :[[@LINE-1]]:6: warning: visibility of function 'operator++'
// CHECK-MESSAGES-OPS: :[[@LINE-12]]:14: note: function declared here
int operator()(int);
// CHECK-MESSAGES-OPS: :[[@LINE-1]]:7: warning: visibility of function 'operator()'
// CHECK-MESSAGES-OPS: :[[@LINE-14]]:15: note: function declared here
operator double() const;
// CHECK-MESSAGES-OPS: :[[@LINE-1]]:3: warning: visibility of function 'operator double'
// CHECK-MESSAGES-OPS: :[[@LINE-16]]:11: note: function declared here
};
}

View File

@ -0,0 +1,289 @@
// RUN: %check_clang_tidy %s misc-override-with-different-visibility %t -- -config="{CheckOptions: {misc-override-with-different-visibility.CheckDestructors: true,misc-override-with-different-visibility.CheckOperators: true}}" -- -I %S/Inputs/override-with-different-visibility
#include <test-system-header.h>
class A {
public:
virtual void pub_foo1() {}
virtual void pub_foo2() {}
virtual void pub_foo3() {}
protected:
virtual void prot_foo1();
virtual void prot_foo2();
virtual void prot_foo3();
private:
virtual void priv_foo1() {}
virtual void priv_foo2() {}
virtual void priv_foo3() {}
};
void A::prot_foo1() {}
void A::prot_foo2() {}
void A::prot_foo3() {}
namespace test1 {
class B: public A {
public:
void pub_foo1() override {}
void prot_foo1() override {}
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo1' is changed from protected in class 'A' to public [misc-override-with-different-visibility]
// CHECK-MESSAGES: :9:16: note: function declared here as protected
void priv_foo1() override {}
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo1' is changed from private in class 'A' to public [misc-override-with-different-visibility]
// CHECK-MESSAGES: :13:16: note: function declared here as private
protected:
void pub_foo2() override {}
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo2' is changed from public in class 'A' to protected [misc-override-with-different-visibility]
// CHECK-MESSAGES: :6:16: note: function declared here as public
void prot_foo2() override {}
void priv_foo2() override {}
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo2' is changed from private in class 'A' to protected [misc-override-with-different-visibility]
// CHECK-MESSAGES: :14:16: note: function declared here as private
private:
void pub_foo3() override {}
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo3' is changed from public in class 'A' to private [misc-override-with-different-visibility]
// CHECK-MESSAGES: :7:16: note: function declared here as public
void prot_foo3() override {}
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo3' is changed from protected in class 'A' to private [misc-override-with-different-visibility]
// CHECK-MESSAGES: :11:16: note: function declared here as protected
void priv_foo3() override {}
};
class C: public B {
public:
void pub_foo1() override;
protected:
void prot_foo1() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo1' is changed from public in class 'B' to protected [misc-override-with-different-visibility]
// CHECK-MESSAGES: :27:8: note: function declared here as public
private:
void priv_foo1() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo1' is changed from public in class 'B' to private [misc-override-with-different-visibility]
// CHECK-MESSAGES: :30:8: note: function declared here as public
};
void C::prot_foo1() {}
void C::priv_foo1() {}
}
namespace test2 {
class B: public A {
public:
void pub_foo1() override;
protected:
void prot_foo1() override;
private:
void priv_foo1() override;
};
class C: public B {
public:
void pub_foo1() override;
void prot_foo1() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo1' is changed from protected in class 'B' to public
// CHECK-MESSAGES: :75:8: note: function declared here as protected
void priv_foo1() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo1' is changed from private in class 'B' to public
// CHECK-MESSAGES: :77:8: note: function declared here as private
void pub_foo2() override;
void prot_foo2() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo2' is changed from protected in class 'A' to public
// CHECK-MESSAGES: :10:16: note: function declared here as protected
void priv_foo2() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo2' is changed from private in class 'A' to public
// CHECK-MESSAGES: :14:16: note: function declared here as private
};
}
namespace test3 {
class B: private A {
public:
void pub_foo1() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo1' is changed from private (through private inheritance of class 'A') to public
// CHECK-MESSAGES: :103:10: note: 'A' is inherited as private here
// CHECK-MESSAGES: :5:16: note: function declared here as public
protected:
void prot_foo1() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo1' is changed from private (through private inheritance of class 'A') to protected
// CHECK-MESSAGES: :103:10: note: 'A' is inherited as private here
// CHECK-MESSAGES: :9:16: note: function declared here as protected
private:
void priv_foo1() override;
public:
void prot_foo2() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'prot_foo2' is changed from private (through private inheritance of class 'A') to public
// CHECK-MESSAGES: :103:10: note: 'A' is inherited as private here
// CHECK-MESSAGES: :10:16: note: function declared here as protected
void priv_foo2() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'priv_foo2' is changed from private in class 'A' to public
// CHECK-MESSAGES: :14:16: note: function declared here as private
private:
void pub_foo3() override;
void prot_foo3() override;
};
class C: private A {
};
class D: public C {
public:
void pub_foo1() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo1' is changed from private (through private inheritance of class 'A') to public
// CHECK-MESSAGES: :131:10: note: 'A' is inherited as private here
// CHECK-MESSAGES: :5:16: note: function declared here as public
};
}
namespace test4 {
struct Base1 {
public:
virtual void foo1();
private:
virtual void foo2();
};
struct Base2 {
public:
virtual void foo2();
private:
virtual void foo1();
};
struct A : public Base1, public Base2 {
protected:
void foo1() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'foo1' is changed from private in class 'Base2' to protected
// CHECK-MESSAGES: :158:16: note: function declared here as private
// CHECK-MESSAGES: :[[@LINE-3]]:8: warning: visibility of function 'foo1' is changed from public in class 'Base1' to protected
// CHECK-MESSAGES: :149:16: note: function declared here as public
private:
void foo2() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'foo2' is changed from public in class 'Base2' to private
// CHECK-MESSAGES: :156:16: note: function declared here as public
};
}
namespace test5 {
struct B1: virtual public A {};
struct B2: virtual private A {};
struct B: public B1, public B2 {
public:
void pub_foo1() override;
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'pub_foo1' is changed from private (through private inheritance of class 'A') to public
// CHECK-MESSAGES: :179:12: note: 'A' is inherited as private here
// CHECK-MESSAGES: :5:16: note: function declared here as public
};
}
namespace test_using {
class A {
private:
A(int);
protected:
virtual void f();
};
class B: public A {
public:
using A::A;
using A::f;
};
}
namespace test_template {
template <typename T>
class A {
protected:
virtual T foo();
};
template <typename T>
class B: public A<T> {
private:
T foo() override;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: visibility of function 'foo' is changed from protected in class 'A<int>' to private
// CHECK-MESSAGES: :[[@LINE-8]]:13: note: function declared here as protected
};
template <typename T>
class C: private A<T> {
public:
T foo() override;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: visibility of function 'foo' is changed from private (through private inheritance of class 'A<int>') to public
// CHECK-MESSAGES: :[[@LINE-4]]:10: note: 'A<int>' is inherited as private here
// CHECK-MESSAGES: :[[@LINE-17]]:13: note: function declared here as protected
};
B<int> fB() {
return B<int>{};
}
C<int> fC() {
return C<int>{};
}
}
namespace test_system_header {
struct SysDerived: public sys::Base {
private:
void publicF();
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'publicF' is changed from public in class 'Base' to private
};
}
namespace test_destructor {
class A {
public:
virtual ~A();
};
class B: public A {
protected:
~B();
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: visibility of function '~B'
// CHECK-MESSAGES: :[[@LINE-7]]:11: note: function declared here
};
}
namespace test_operator {
class A {
virtual int operator()(int);
virtual A& operator++();
virtual operator double() const;
};
class B: public A {
protected:
int operator()(int);
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: visibility of function 'operator()'
// CHECK-MESSAGES: :[[@LINE-9]]:15: note: function declared here
A& operator++();
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: visibility of function 'operator++'
// CHECK-MESSAGES: :[[@LINE-11]]:14: note: function declared here
operator double() const;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: visibility of function 'operator double'
// CHECK-MESSAGES: :[[@LINE-13]]:11: note: function declared here
};
}

View File

@ -66,19 +66,14 @@ class A { A(int); };
// CHECK4-NOT: warning:
// CHECK4-QUIET-NOT: warning:
// CHECK: Suppressed 3 warnings (3 in non-user code)
// CHECK: Use -header-filter=.* to display errors from all non-system headers.
// CHECK-QUIET-NOT: Suppressed
// CHECK2: Suppressed 1 warnings (1 in non-user code)
// CHECK2: Use -header-filter=.* {{.*}}
// CHECK2-QUIET-NOT: Suppressed
// CHECK3: Suppressed 2 warnings (2 in non-user code)
// CHECK3: Use -header-filter=.* {{.*}}
// CHECK3-QUIET-NOT: Suppressed
// CHECK4-NOT: Suppressed {{.*}} warnings
// CHECK4-NOT: Use -header-filter=.* {{.*}}
// CHECK4-QUIET-NOT: Suppressed
// CHECK6: Suppressed 2 warnings (2 in non-user code)
// CHECK6: Use -header-filter=.* {{.*}}
int x = 123;

View File

@ -11,9 +11,9 @@
// RUN: clang-tidy -help | FileCheck -check-prefix=CHECK-OPT-PRESENT %s
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers=true %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-SYSTEM-HEADERS %s
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers=false %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-NO-SYSTEM-HEADERS %s
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers=false %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-NO-SYSTEM-HEADERS --allow-empty %s
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -config='SystemHeaders: true' %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-SYSTEM-HEADERS %s
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -config='SystemHeaders: false' %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-NO-SYSTEM-HEADERS %s
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -config='SystemHeaders: false' %s -- -isystem %S/Inputs/system-headers 2>&1 | FileCheck -check-prefix=CHECK-NO-SYSTEM-HEADERS --allow-empty %s
#include <system_header.h>
// CHECK-SYSTEM-HEADERS: system_header.h:1:13: warning: single-argument constructors must be marked explicit

View File

@ -126,6 +126,9 @@ clang-format is turned off or back on.
// clang-format on
void formatted_code_again;
In addition, the ``OneLineFormatOffRegex`` option gives you a concise way to
disable formatting for all of the lines that match the regular expression.
Configuring Style in Code
=========================
@ -6483,13 +6486,51 @@ the configuration (without a prefix: ``Auto``).
.. _SpaceInEmptyBlock:
**SpaceInEmptyBlock** (``Boolean``) :versionbadge:`clang-format 10` :ref:`¶ <SpaceInEmptyBlock>`
If ``true``, spaces will be inserted into ``{}``.
This option is **deprecated**. See ``Block`` of ``SpaceInEmptyBraces``.
.. _SpaceInEmptyBraces:
**SpaceInEmptyBraces** (``SpaceInEmptyBracesStyle``) :versionbadge:`clang-format 22` :ref:`¶ <SpaceInEmptyBraces>`
Specifies when to insert a space in empty braces.
.. note::
This option doesn't apply to initializer braces if
``Cpp11BracedListStyle`` is set to ``true``.
Possible values:
* ``SIEB_Always`` (in configuration: ``Always``)
Always insert a space in empty braces.
.. code-block:: c++
void f() { }
class Unit { };
auto a = [] { };
int x{ };
* ``SIEB_Block`` (in configuration: ``Block``)
Only insert a space in empty blocks.
.. code-block:: c++
void f() { }
class Unit { };
auto a = [] { };
int x{};
* ``SIEB_Never`` (in configuration: ``Never``)
Never insert a space in empty braces.
.. code-block:: c++
void f() {}
class Unit {};
auto a = [] {};
int x{};
.. code-block:: c++
true: false:
void f() { } vs. void f() {}
while (true) { } while (true) {}
.. _SpaceInEmptyParentheses:

View File

@ -230,6 +230,7 @@ Bug Fixes to AST Handling
- Fix incorrect name qualifiers applied to alias CTAD. (#GH136624)
- Fixed ElaboratedTypes appearing within NestedNameSpecifier, which was not a
legal representation. This is fixed because ElaboratedTypes don't exist anymore. (#GH43179) (#GH68670) (#GH92757)
- Fix unrecognized html tag causing undesirable comment lexing (#GH152944)
- Fix comment lexing of special command names (#GH152943)
Miscellaneous Bug Fixes
@ -308,8 +309,12 @@ AST Matchers
- Ensure ``hasBitWidth`` doesn't crash on bit widths that are dependent on template
parameters.
- Add a boolean member ``IgnoreSystemHeaders`` to ``MatchFinderOptions``. This
allows it to ignore nodes in system headers when traversing the AST.
clang-format
------------
- Add ``SpaceInEmptyBraces`` option and set it to ``Always`` for WebKit style.
libclang
--------

View File

@ -66,17 +66,17 @@ supported. Uninstrumented code simply won't be accounted for in reports.
To compile code with Modified Condition/Decision Coverage (MC/DC) enabled,
pass ``-fcoverage-mcdc`` in addition to the clang options specified above.
MC/DC is an advanced form of code coverage most applicable in the embedded
MC/DC is an advanced form of code coverage most applicable to the embedded
space.
Running the instrumented program
================================
The next step is to run the instrumented program. When the program exits it
The next step is to run the instrumented program. When the program exits, it
will write a **raw profile** to the path specified by the ``LLVM_PROFILE_FILE``
environment variable. If that variable does not exist, the profile is written
to ``default.profraw`` in the current directory of the program. If
``LLVM_PROFILE_FILE`` contains a path to a non-existent directory, the missing
``LLVM_PROFILE_FILE`` specifies a path to a non-existent directory, the missing
directory structure will be created. Additionally, the following special
**pattern strings** are rewritten:
@ -97,7 +97,7 @@ directory structure will be created. Additionally, the following special
* "%b" expands out to the binary ID (build ID). It can be used with "%Nm" to
avoid binary signature collisions. To use it, the program should be compiled
with the build ID linker option (``--build-id`` for GNU ld or LLD,
``/build-id`` for lld-link on Windows). Linux, Windows and AIX are supported.
``/build-id`` for lld-link on Windows). Linux, Windows, and AIX are supported.
* "%c" expands out to nothing, but enables a mode in which profile counter
updates are continuously synced to a file. This means that if the
@ -128,7 +128,7 @@ and set bias to the offset between the original and the new counter location,
at which point every subsequent counter access will be to the new location,
which allows updating profile directly akin to the continuous mode.
The advantage of this approach is that doesn't require any special OS support.
The advantage of this approach is that it doesn't require any special OS support.
The disadvantage is the extra overhead due to additional instructions required
for each counter access (overhead both in terms of binary size and performance)
plus duplication of counters (i.e. one copy in the binary itself and another
@ -137,7 +137,7 @@ other platforms by passing the ``-runtime-counter-relocation`` option to the
backend during compilation.
For a program such as the `Lit <https://llvm.org/docs/CommandGuide/lit.html>`_
testing tool which invokes other programs, it may be necessary to set
testing tool, which invokes other programs, it may be necessary to set
``LLVM_PROFILE_FILE`` for each invocation. The pattern strings "%p" or "%Nm"
may help to avoid corruption due to concurrency. Note that "%p" is also a Lit
token and needs to be escaped as "%%p".
@ -149,7 +149,7 @@ token and needs to be escaped as "%%p".
Creating coverage reports
=========================
Raw profiles have to be **indexed** before they can be used to generate
Raw profiles must be **indexed** before they can be used to generate
coverage reports. This is done using the "merge" tool in ``llvm-profdata``
(which can combine multiple raw profiles and index them at the same time):
@ -240,13 +240,13 @@ line-oriented report, try:
TOTAL 13 0 100.00% 3 0 100.00% 13 0 100.00% 12 2 83.33%
The ``llvm-cov`` tool supports specifying a custom demangler, writing out
reports in a directory structure, and generating html reports. For the full
reports in a directory structure, and generating HTML reports. For the full
list of options, please refer to the `command guide
<https://llvm.org/docs/CommandGuide/llvm-cov.html>`_.
A few final notes:
* The ``-sparse`` flag is optional but can result in dramatically smaller
* The ``-sparse`` flag is optional but can produce dramatically smaller
indexed profiles. This option should not be used if the indexed profile will
be reused for PGO.
@ -255,7 +255,7 @@ A few final notes:
information directly into an existing raw profile on disk. The details are
out of scope.
* The ``llvm-profdata`` tool can be used to merge together multiple raw or
* The ``llvm-profdata`` tool can be used to merge multiple raw or
indexed profiles. To combine profiling data from multiple runs of a program,
try e.g:
@ -299,7 +299,7 @@ There are six statistics tracked in a coverage summary:
source code that may each evaluate to either "true" or "false". These
conditions may comprise larger boolean expressions linked by boolean logical
operators. For example, "x = (y == 2) || (z < 10)" is a boolean expression
that is comprised of two individual conditions, each of which evaluates to
comprised of two individual conditions, each of which evaluates to
either true or false, producing four total branch outcomes.
* Modified Condition/Decision Coverage (MC/DC) is the percentage of individual
@ -316,7 +316,7 @@ There are six statistics tracked in a coverage summary:
``-show-mcdc-summary`` option as long as code was also compiled using the
clang option ``-fcoverage-mcdc``.
* Boolean expressions that are only comprised of one condition (and therefore
* Boolean expressions comprised of only one condition (and therefore
have no logical operators) are not included in MC/DC analysis and are
trivially deducible using branch coverage.
@ -366,7 +366,7 @@ By default the compiler runtime uses a static initializer to determine the
profile output path and to register a writer function. To collect profiles
without using static initializers, do this manually:
* Export a ``int __llvm_profile_runtime`` symbol from each instrumented shared
* Export an ``int __llvm_profile_runtime`` symbol from each instrumented shared
library and executable. When the linker finds a definition of this symbol, it
knows to skip loading the object which contains the profiling runtime's
static initializer.
@ -380,7 +380,7 @@ without using static initializers, do this manually:
to ``__llvm_profile_write_file``.
* Forward-declare ``int __llvm_profile_write_file(void)`` and call it to write
out a profile. This function returns 0 when it succeeds, and a non-zero value
out a profile. This function returns 0 on success, and a non-zero value
otherwise. Calling this function multiple times appends profile data to an
existing on-disk raw profile.
@ -418,7 +418,7 @@ Collecting coverage reports for the llvm project
================================================
To prepare a coverage report for llvm (and any of its sub-projects), add
``-DLLVM_BUILD_INSTRUMENTED_COVERAGE=On`` to the cmake configuration. Raw
``-DLLVM_BUILD_INSTRUMENTED_COVERAGE=On`` to the CMake configuration. Raw
profiles will be written to ``$BUILD_DIR/profiles/``. To prepare an html
report, run ``llvm/utils/prepare-code-coverage-artifact.py``.
@ -429,7 +429,7 @@ To specify an alternate directory for raw profiles, use
Drawbacks and limitations
=========================
* Prior to version 2.26, the GNU binutils BFD linker is not able link programs
* Prior to version 2.26, the GNU binutils BFD linker cannot link programs
compiled with ``-fcoverage-mapping`` in its ``--gc-sections`` mode. Possible
workarounds include disabling ``--gc-sections``, upgrading to a newer version
of BFD, or using the Gold linker.

View File

@ -51,6 +51,11 @@ def Col : Tag<"col"> { let EndTagForbidden = 1; }
def Tr : Tag<"tr"> { let EndTagOptional = 1; }
def Th : Tag<"th"> { let EndTagOptional = 1; }
def Td : Tag<"td"> { let EndTagOptional = 1; }
def Summary : Tag<"summary">;
def Details : Tag<"details">;
def Mark : Tag<"mark">;
def Figure : Tag<"figure">;
def FigCaption : Tag<"figcaption">;
// Define a list of attributes that are not safe to pass through to HTML
// output if the input is untrusted.

View File

@ -135,10 +135,15 @@ public:
llvm::StringMap<llvm::TimeRecord> &Records;
};
MatchFinderOptions() {}
/// Enables per-check timers.
///
/// It prints a report after match.
std::optional<Profiling> CheckProfiling;
/// Avoids matching declarations in system headers.
bool IgnoreSystemHeaders{false};
};
MatchFinder(MatchFinderOptions Options = MatchFinderOptions());

View File

@ -19,14 +19,35 @@
#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/ADT/StringMap.h"
#include <memory>
namespace clang::lifetimes {
/// Enum to track the confidence level of a potential error.
enum class Confidence {
None,
Maybe, // Reported as a potential error (-Wlifetime-safety-strict)
Definite // Reported as a definite error (-Wlifetime-safety-permissive)
};
class LifetimeSafetyReporter {
public:
LifetimeSafetyReporter() = default;
virtual ~LifetimeSafetyReporter() = default;
virtual void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
SourceLocation FreeLoc,
Confidence Confidence) {}
};
/// The main entry point for the analysis.
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC);
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
LifetimeSafetyReporter *Reporter);
namespace internal {
// Forward declarations of internal types.
@ -53,6 +74,7 @@ template <typename Tag> struct ID {
IDBuilder.AddInteger(Value);
}
};
template <typename Tag>
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID<Tag> ID) {
return OS << ID.Value;
@ -78,7 +100,8 @@ using ProgramPoint = const Fact *;
/// encapsulates the various dataflow analyses.
class LifetimeSafetyAnalysis {
public:
LifetimeSafetyAnalysis(AnalysisDeclContext &AC);
LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
LifetimeSafetyReporter *Reporter);
~LifetimeSafetyAnalysis();
void run();
@ -87,7 +110,7 @@ public:
LoanSet getLoansAtPoint(OriginID OID, ProgramPoint PP) const;
/// Returns the set of loans that have expired at a specific program point.
LoanSet getExpiredLoansAtPoint(ProgramPoint PP) const;
std::vector<LoanID> getExpiredLoansAtPoint(ProgramPoint PP) const;
/// Finds the OriginID for a given declaration.
/// Returns a null optional if not found.
@ -110,6 +133,7 @@ public:
private:
AnalysisDeclContext &AC;
LifetimeSafetyReporter *Reporter;
std::unique_ptr<LifetimeFactory> Factory;
std::unique_ptr<FactManager> FactMgr;
std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
@ -118,4 +142,25 @@ private:
} // namespace internal
} // namespace clang::lifetimes
namespace llvm {
template <typename Tag>
struct DenseMapInfo<clang::lifetimes::internal::ID<Tag>> {
using ID = clang::lifetimes::internal::ID<Tag>;
static inline ID getEmptyKey() {
return {DenseMapInfo<uint32_t>::getEmptyKey()};
}
static inline ID getTombstoneKey() {
return {DenseMapInfo<uint32_t>::getTombstoneKey()};
}
static unsigned getHashValue(const ID &Val) {
return DenseMapInfo<uint32_t>::getHashValue(Val.Value);
}
static bool isEqual(const ID &LHS, const ID &RHS) { return LHS == RHS; }
};
} // namespace llvm
#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H

View File

@ -268,7 +268,6 @@ let Header = "emmintrin.h", Attributes = [NoThrow, RequireDeclaration] in {
}
let Features = "sse2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def pmuludq128 : X86Builtin<"_Vector<2, long long int>(_Vector<4, int>, _Vector<4, int>)">;
def psraw128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">;
def psrad128 : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
def psrlw128 : X86Builtin<"_Vector<8, short>(_Vector<8, short>, _Vector<8, short>)">;
@ -290,6 +289,10 @@ let Features = "sse2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] i
def psrldqi128_byteshift : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Constant int)">;
}
let Features = "sse2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def pmuludq128 : X86Builtin<"_Vector<2, long long int>(_Vector<4, int>, _Vector<4, int>)">;
}
let Features = "sse3", Attributes = [NoThrow] in {
def monitor : X86Builtin<"void(void const *, unsigned int, unsigned int)">;
def mwait : X86Builtin<"void(unsigned int, unsigned int)">;
@ -312,7 +315,6 @@ let Features = "sse4.1", Attributes = [NoThrow, Const, RequiredVectorWidth<128>]
def blendvpd : X86Builtin<"_Vector<2, double>(_Vector<2, double>, _Vector<2, double>, _Vector<2, double>)">;
def blendvps : X86Builtin<"_Vector<4, float>(_Vector<4, float>, _Vector<4, float>, _Vector<4, float>)">;
def packusdw128 : X86Builtin<"_Vector<8, short>(_Vector<4, int>, _Vector<4, int>)">;
def pmuldq128 : X86Builtin<"_Vector<2, long long int>(_Vector<4, int>, _Vector<4, int>)">;
def roundps : X86Builtin<"_Vector<4, float>(_Vector<4, float>, _Constant int)">;
def roundss : X86Builtin<"_Vector<4, float>(_Vector<4, float>, _Vector<4, float>, _Constant int)">;
def roundsd : X86Builtin<"_Vector<2, double>(_Vector<2, double>, _Vector<2, double>, _Constant int)">;
@ -329,6 +331,10 @@ let Features = "sse4.1", Attributes = [NoThrow, Const, RequiredVectorWidth<128>]
def vec_set_v4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, int, _Constant int)">;
}
let Features = "sse4.1", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def pmuldq128 : X86Builtin<"_Vector<2, long long int>(_Vector<4, int>, _Vector<4, int>)">;
}
let Features = "sse4.2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def pcmpistrm128 : X86Builtin<"_Vector<16, char>(_Vector<16, char>, _Vector<16, char>, _Constant char)">;
def pcmpistri128 : X86Builtin<"int(_Vector<16, char>, _Vector<16, char>, _Constant char)">;
@ -580,9 +586,7 @@ let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] i
def pmaddubsw256 : X86Builtin<"_Vector<16, short>(_Vector<32, char>, _Vector<32, char>)">;
def pmaddwd256 : X86Builtin<"_Vector<8, int>(_Vector<16, short>, _Vector<16, short>)">;
def pmovmskb256 : X86Builtin<"int(_Vector<32, char>)">;
def pmuldq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
def pmulhrsw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">;
def pmuludq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
def psadbw256 : X86Builtin<"_Vector<4, long long int>(_Vector<32, char>, _Vector<32, char>)">;
def pshufb256 : X86Builtin<"_Vector<32, char>(_Vector<32, char>, _Vector<32, char>)">;
def pshufd256 : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Constant int)">;
@ -620,6 +624,11 @@ let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] i
def insert128i256 : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<2, long long int>, _Constant int)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def pmuldq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
def pmuludq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def pmulhuw256 : X86Builtin<"_Vector<16, unsigned short>(_Vector<16, unsigned short>, _Vector<16, unsigned short>)">;
def pmulhw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">;
@ -1078,6 +1087,9 @@ let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWi
def cvtpd2ps512_mask : X86Builtin<"_Vector<8, float>(_Vector<8, double>, _Vector<8, float>, unsigned char, _Constant int)">;
def vcvtps2ph512_mask : X86Builtin<"_Vector<16, short>(_Vector<16, float>, _Constant int, _Vector<16, short>, unsigned short)">;
def vcvtph2ps512_mask : X86Builtin<"_Vector<16, float>(_Vector<16, short>, _Vector<16, float>, unsigned short, _Constant int)">;
}
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
def pmuldq512 : X86Builtin<"_Vector<8, long long int>(_Vector<16, int>, _Vector<16, int>)">;
def pmuludq512 : X86Builtin<"_Vector<8, long long int>(_Vector<16, int>, _Vector<16, int>)">;
}
@ -4118,99 +4130,99 @@ let Features = "avx512fp16,evex512", Attributes = [NoThrow, Const, RequiredVecto
def vfcmulcph512_mask : X86Builtin<"_Vector<16, float>(_Vector<16, float>, _Vector<16, float>, _Vector<16, float>, unsigned short, _Constant int)">;
}
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def selectb_128 : X86Builtin<"_Vector<16, char>(unsigned short, _Vector<16, char>, _Vector<16, char>)">;
}
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def selectb_256 : X86Builtin<"_Vector<32, char>(unsigned int, _Vector<32, char>, _Vector<32, char>)">;
}
let Features = "avx512bw,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
let Features = "avx512bw,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
def selectb_512 : X86Builtin<"_Vector<64, char>(unsigned long long int, _Vector<64, char>, _Vector<64, char>)">;
}
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def selectw_128 : X86Builtin<"_Vector<8, short>(unsigned char, _Vector<8, short>, _Vector<8, short>)">;
}
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
let Features = "avx512bw,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def selectw_256 : X86Builtin<"_Vector<16, short>(unsigned short, _Vector<16, short>, _Vector<16, short>)">;
}
let Features = "avx512bw,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
let Features = "avx512bw,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
def selectw_512 : X86Builtin<"_Vector<32, short>(unsigned int, _Vector<32, short>, _Vector<32, short>)">;
}
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def selectd_128 : X86Builtin<"_Vector<4, int>(unsigned char, _Vector<4, int>, _Vector<4, int>)">;
}
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def selectd_256 : X86Builtin<"_Vector<8, int>(unsigned char, _Vector<8, int>, _Vector<8, int>)">;
}
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
def selectd_512 : X86Builtin<"_Vector<16, int>(unsigned short, _Vector<16, int>, _Vector<16, int>)">;
}
let Features = "avx512fp16,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
let Features = "avx512fp16,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def selectph_128 : X86Builtin<"_Vector<8, _Float16>(unsigned char, _Vector<8, _Float16>, _Vector<8, _Float16>)">;
}
let Features = "avx512fp16,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
let Features = "avx512fp16,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def selectph_256 : X86Builtin<"_Vector<16, _Float16>(unsigned short, _Vector<16, _Float16>, _Vector<16, _Float16>)">;
}
let Features = "avx512fp16,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
let Features = "avx512fp16,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
def selectph_512 : X86Builtin<"_Vector<32, _Float16>(unsigned int, _Vector<32, _Float16>, _Vector<32, _Float16>)">;
}
let Features = "avx512bf16,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
let Features = "avx512bf16,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def selectpbf_128 : X86Builtin<"_Vector<8, __bf16>(unsigned char, _Vector<8, __bf16>, _Vector<8, __bf16>)">;
}
let Features = "avx512bf16,avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
let Features = "avx512bf16,avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def selectpbf_256 : X86Builtin<"_Vector<16, __bf16>(unsigned short, _Vector<16, __bf16>, _Vector<16, __bf16>)">;
}
let Features = "avx512bf16,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
let Features = "avx512bf16,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
def selectpbf_512 : X86Builtin<"_Vector<32, __bf16>(unsigned int, _Vector<32, __bf16>, _Vector<32, __bf16>)">;
}
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def selectq_128 : X86Builtin<"_Vector<2, long long int>(unsigned char, _Vector<2, long long int>, _Vector<2, long long int>)">;
}
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def selectq_256 : X86Builtin<"_Vector<4, long long int>(unsigned char, _Vector<4, long long int>, _Vector<4, long long int>)">;
}
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
def selectq_512 : X86Builtin<"_Vector<8, long long int>(unsigned char, _Vector<8, long long int>, _Vector<8, long long int>)">;
}
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def selectps_128 : X86Builtin<"_Vector<4, float>(unsigned char, _Vector<4, float>, _Vector<4, float>)">;
}
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def selectps_256 : X86Builtin<"_Vector<8, float>(unsigned char, _Vector<8, float>, _Vector<8, float>)">;
}
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
def selectps_512 : X86Builtin<"_Vector<16, float>(unsigned short, _Vector<16, float>, _Vector<16, float>)">;
}
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def selectpd_128 : X86Builtin<"_Vector<2, double>(unsigned char, _Vector<2, double>, _Vector<2, double>)">;
}
let Features = "avx512vl", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
let Features = "avx512vl", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def selectpd_256 : X86Builtin<"_Vector<4, double>(unsigned char, _Vector<4, double>, _Vector<4, double>)">;
}
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
let Features = "avx512f,evex512", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
def selectpd_512 : X86Builtin<"_Vector<8, double>(unsigned char, _Vector<8, double>, _Vector<8, double>)">;
}

View File

@ -533,7 +533,14 @@ def Dangling : DiagGroup<"dangling", [DanglingAssignment,
DanglingGsl,
ReturnStackAddress]>;
def LifetimeSafety : DiagGroup<"experimental-lifetime-safety">;
def LifetimeSafetyPermissive : DiagGroup<"experimental-lifetime-safety-permissive">;
def LifetimeSafetyStrict : DiagGroup<"experimental-lifetime-safety-strict">;
def LifetimeSafety : DiagGroup<"experimental-lifetime-safety",
[LifetimeSafetyPermissive, LifetimeSafetyStrict]> {
code Documentation = [{
Experimental warnings to detect use-after-free and related temporal safety bugs based on lifetime safety analysis.
}];
}
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
def DllexportExplicitInstantiationDecl : DiagGroup<"dllexport-explicit-instantiation-decl">;

View File

@ -10671,9 +10671,15 @@ def warn_dangling_reference_captured_by_unknown : Warning<
"object whose reference is captured will be destroyed at the end of "
"the full-expression">, InGroup<DanglingCapture>;
def warn_experimental_lifetime_safety_dummy_warning : Warning<
"todo: remove this warning after we have atleast one warning based on the lifetime analysis">,
InGroup<LifetimeSafety>, DefaultIgnore;
// Diagnostics based on the Lifetime safety analysis.
def warn_lifetime_safety_loan_expires_permissive : Warning<
"object whose reference is captured does not live long enough">,
InGroup<LifetimeSafetyPermissive>, DefaultIgnore;
def warn_lifetime_safety_loan_expires_strict : Warning<
"object whose reference is captured may not live long enough">,
InGroup<LifetimeSafetyStrict>, DefaultIgnore;
def note_lifetime_safety_used_here : Note<"later used here">;
def note_lifetime_safety_destroyed_here : Note<"destroyed here">;
// For non-floating point, expressions of the form x == x or x != x
// should result in a warning, since these always evaluate to a constant.

View File

@ -233,8 +233,9 @@ protected:
bool TLSSupported;
bool VLASupported;
bool NoAsmVariants; // True if {|} are normal characters.
bool HasLegalHalfType; // True if the backend supports operations on the half
// LLVM IR type.
bool HasFastHalfType; // True if the backend has native half float support,
// and performing calculations in float instead does
// not have a performance advantage.
bool HalfArgsAndReturns; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) type.
bool HasFloat128;
bool HasFloat16;
@ -700,8 +701,9 @@ public:
return 128;
}
/// Determine whether _Float16 is supported on this target.
virtual bool hasLegalHalfType() const { return HasLegalHalfType; }
/// Determine whether the target has fast native support for operations
/// on half types.
virtual bool hasFastHalfType() const { return HasFastHalfType; }
/// Whether half args and returns are supported.
virtual bool allowHalfArgsAndReturns() const { return HalfArgsAndReturns; }

View File

@ -4813,14 +4813,45 @@ struct FormatStyle {
/// \version 7
bool SpaceBeforeRangeBasedForLoopColon;
/// If ``true``, spaces will be inserted into ``{}``.
/// \code
/// true: false:
/// void f() { } vs. void f() {}
/// while (true) { } while (true) {}
/// \endcode
/// This option is **deprecated**. See ``Block`` of ``SpaceInEmptyBraces``.
/// \version 10
bool SpaceInEmptyBlock;
// bool SpaceInEmptyBlock;
/// Style of when to insert a space in empty braces.
enum SpaceInEmptyBracesStyle : int8_t {
/// Always insert a space in empty braces.
/// \code
/// void f() { }
/// class Unit { };
/// auto a = [] { };
/// int x{ };
/// \endcode
SIEB_Always,
/// Only insert a space in empty blocks.
/// \code
/// void f() { }
/// class Unit { };
/// auto a = [] { };
/// int x{};
/// \endcode
SIEB_Block,
/// Never insert a space in empty braces.
/// \code
/// void f() {}
/// class Unit {};
/// auto a = [] {};
/// int x{};
/// \endcode
SIEB_Never
};
/// Specifies when to insert a space in empty braces.
/// \note
/// This option doesn't apply to initializer braces if
/// ``Cpp11BracedListStyle`` is set to ``true``.
/// \endnote
/// \version 22
SpaceInEmptyBracesStyle SpaceInEmptyBraces;
/// If ``true``, spaces may be inserted into ``()``.
/// This option is **deprecated**. See ``InEmptyParentheses`` of
@ -5494,7 +5525,7 @@ struct FormatStyle {
SpaceBeforeRangeBasedForLoopColon ==
R.SpaceBeforeRangeBasedForLoopColon &&
SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets &&
SpaceInEmptyBlock == R.SpaceInEmptyBlock &&
SpaceInEmptyBraces == R.SpaceInEmptyBraces &&
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
SpacesInAngles == R.SpacesInAngles &&
SpacesInContainerLiterals == R.SpacesInContainerLiterals &&

View File

@ -143,9 +143,6 @@ class Lexer : public PreprocessorLexer {
/// True if this is the first time we're lexing the input file.
bool IsFirstTimeLexingFile;
/// True if current lexing token is the first pp-token.
bool IsFirstPPToken;
// NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n',
// it also points to '\n.'
const char *NewLinePtr;

View File

@ -0,0 +1,310 @@
//===--- NoTrivialPPDirectiveTracer.h ---------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the NoTrivialPPDirectiveTracer interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
#define LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
#include "clang/Lex/PPCallbacks.h"
namespace clang {
class Preprocessor;
/// Consider the following code:
///
/// # 1 __FILE__ 1 3
/// export module a;
///
/// According to the wording in
/// [P1857R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1857r3.html):
///
/// A module directive may only appear as the first preprocessing tokens in a
/// file (excluding the global module fragment.)
///
/// and the wording in
/// [[cpp.pre]](https://eel.is/c++draft/cpp.pre#nt:module-file):
/// module-file:
/// pp-global-module-fragment[opt] pp-module group[opt]
/// pp-private-module-fragment[opt]
///
/// `#` is the first pp-token in the translation unit, and it was rejected by
/// clang, but they really should be exempted from this rule. The goal is to not
/// allow any preprocessor conditionals or most state changes, but these don't
/// fit that.
///
/// State change would mean most semantically observable preprocessor state,
/// particularly anything that is order dependent. Global flags like being a
/// system header/module shouldn't matter.
///
/// We should exempt a brunch of directives, even though it violates the current
/// standard wording.
///
/// This class used to trace 'no-trivial' pp-directives in main file, which may
/// change the preprocessing state.
///
/// FIXME: Once the wording of the standard is revised, we need to follow the
/// wording of the standard. Currently this is just a workaround
class NoTrivialPPDirectiveTracer : public PPCallbacks {
Preprocessor &PP;
/// Whether preprocessing main file. We only focus on the main file.
bool InMainFile = true;
/// Whether one or more conditional, include or other 'no-trivial'
/// pp-directives has seen before.
bool SeenNoTrivialPPDirective = false;
void setSeenNoTrivialPPDirective();
public:
NoTrivialPPDirectiveTracer(Preprocessor &P) : PP(P) {}
bool hasSeenNoTrivialPPDirective() const;
/// Callback invoked whenever the \p Lexer moves to a different file for
/// lexing. Unlike \p FileChanged line number directives and other related
/// pragmas do not trigger callbacks to \p LexedFileChanged.
///
/// \param FID The \p FileID that the \p Lexer moved to.
///
/// \param Reason Whether the \p Lexer entered a new file or exited one.
///
/// \param FileType The \p CharacteristicKind of the file the \p Lexer moved
/// to.
///
/// \param PrevFID The \p FileID the \p Lexer was using before the change.
///
/// \param Loc The location where the \p Lexer entered a new file from or the
/// location that the \p Lexer moved into after exiting a file.
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
SourceLocation Loc) override;
/// Callback invoked whenever an embed directive has been processed,
/// regardless of whether the embed will actually find a file.
///
/// \param HashLoc The location of the '#' that starts the embed directive.
///
/// \param FileName The name of the file being included, as written in the
/// source code.
///
/// \param IsAngled Whether the file name was enclosed in angle brackets;
/// otherwise, it was enclosed in quotes.
///
/// \param File The actual file that may be included by this embed directive.
///
/// \param Params The parameters used by the directive.
void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled,
OptionalFileEntryRef File,
const LexEmbedParametersResult &Params) override {
setSeenNoTrivialPPDirective();
}
/// Callback invoked whenever an inclusion directive of
/// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
/// of whether the inclusion will actually result in an inclusion.
///
/// \param HashLoc The location of the '#' that starts the inclusion
/// directive.
///
/// \param IncludeTok The token that indicates the kind of inclusion
/// directive, e.g., 'include' or 'import'.
///
/// \param FileName The name of the file being included, as written in the
/// source code.
///
/// \param IsAngled Whether the file name was enclosed in angle brackets;
/// otherwise, it was enclosed in quotes.
///
/// \param FilenameRange The character range of the quotes or angle brackets
/// for the written file name.
///
/// \param File The actual file that may be included by this inclusion
/// directive.
///
/// \param SearchPath Contains the search path which was used to find the file
/// in the file system. If the file was found via an absolute include path,
/// SearchPath will be empty. For framework includes, the SearchPath and
/// RelativePath will be split up. For example, if an include of "Some/Some.h"
/// is found via the framework path
/// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
/// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
/// "Some.h".
///
/// \param RelativePath The path relative to SearchPath, at which the include
/// file was found. This is equal to FileName except for framework includes.
///
/// \param SuggestedModule The module suggested for this header, if any.
///
/// \param ModuleImported Whether this include was translated into import of
/// \p SuggestedModule.
///
/// \param FileType The characteristic kind, indicates whether a file or
/// directory holds normal user code, system code, or system code which is
/// implicitly 'extern "C"' in C++ mode.
///
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange,
OptionalFileEntryRef File, StringRef SearchPath,
StringRef RelativePath, const Module *SuggestedModule,
bool ModuleImported,
SrcMgr::CharacteristicKind FileType) override {
setSeenNoTrivialPPDirective();
}
/// Callback invoked whenever there was an explicit module-import
/// syntax.
///
/// \param ImportLoc The location of import directive token.
///
/// \param Path The identifiers (and their locations) of the module
/// "path", e.g., "std.vector" would be split into "std" and "vector".
///
/// \param Imported The imported module; can be null if importing failed.
///
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
const Module *Imported) override {
setSeenNoTrivialPPDirective();
}
/// Callback invoked when the end of the main file is reached.
///
/// No subsequent callbacks will be made.
void EndOfMainFile() override { setSeenNoTrivialPPDirective(); }
/// Callback invoked when start reading any pragma directive.
void PragmaDirective(SourceLocation Loc,
PragmaIntroducerKind Introducer) override {}
/// Called by Preprocessor::HandleMacroExpandedIdentifier when a
/// macro invocation is found.
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range, const MacroArgs *Args) override;
/// Hook called whenever a macro definition is seen.
void MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever a macro \#undef is seen.
/// \param MacroNameTok The active Token
/// \param MD A MacroDefinition for the named macro.
/// \param Undef New MacroDirective if the macro was defined, null otherwise.
///
/// MD is released immediately following this callback.
void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
const MacroDirective *Undef) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever the 'defined' operator is seen.
/// \param MD The MacroDirective if the name was a macro, null otherwise.
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#if is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param ConditionValue The evaluated value of the condition.
///
// FIXME: better to pass in a list (or tree!) of Tokens.
void If(SourceLocation Loc, SourceRange ConditionRange,
ConditionValueKind ConditionValue) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elif is seen.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param ConditionValue The evaluated value of the condition.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
// FIXME: better to pass in a list (or tree!) of Tokens.
void Elif(SourceLocation Loc, SourceRange ConditionRange,
ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#ifdef is seen.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elifdef branch is taken.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elifdef is skipped.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
// FIXME: better to pass in a list (or tree!) of Tokens.
void Elifdef(SourceLocation Loc, SourceRange ConditionRange,
SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#ifndef is seen.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefiniton if the name was a macro, null otherwise.
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elifndef branch is taken.
/// \param Loc the source location of the directive.
/// \param MacroNameTok Information on the token being tested.
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#elifndef is skipped.
/// \param Loc the source location of the directive.
/// \param ConditionRange The SourceRange of the expression being tested.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
// FIXME: better to pass in a list (or tree!) of Tokens.
void Elifndef(SourceLocation Loc, SourceRange ConditionRange,
SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#else is seen.
/// \param Loc the source location of the directive.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
void Else(SourceLocation Loc, SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
/// Hook called whenever an \#endif is seen.
/// \param Loc the source location of the directive.
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
setSeenNoTrivialPPDirective();
}
};
} // namespace clang
#endif // LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H

View File

@ -82,6 +82,7 @@ class PreprocessorLexer;
class PreprocessorOptions;
class ScratchBuffer;
class TargetInfo;
class NoTrivialPPDirectiveTracer;
namespace Builtin {
class Context;
@ -353,6 +354,11 @@ private:
/// First pp-token source location in current translation unit.
SourceLocation FirstPPTokenLoc;
/// A preprocessor directive tracer to trace whether the preprocessing
/// state changed. These changes would mean most semantically observable
/// preprocessor state, particularly anything that is order dependent.
NoTrivialPPDirectiveTracer *DirTracer = nullptr;
/// A position within a C++20 import-seq.
class StdCXXImportSeq {
public:
@ -609,6 +615,8 @@ private:
return State == NamedModuleImplementation && !getName().contains(':');
}
bool isNotAModuleDecl() const { return State == NotAModuleDecl; }
StringRef getName() const {
assert(isNamedModule() && "Can't get name from a non named module");
return Name;
@ -3091,6 +3099,10 @@ public:
bool setDeserializedSafeBufferOptOutMap(
const SmallVectorImpl<SourceLocation> &SrcLocSeqs);
/// Whether we've seen pp-directives which may have changed the preprocessing
/// state.
bool hasSeenNoTrivialPPDirective() const;
private:
/// Helper functions to forward lexing to the actual lexer. They all share the
/// same signature.

View File

@ -86,12 +86,12 @@ public:
// macro stringizing or charizing operator.
CommaAfterElided = 0x200, // The comma following this token was elided (MS).
IsEditorPlaceholder = 0x400, // This identifier is a placeholder.
IsReinjected = 0x800, // A phase 4 token that was produced before and
// re-added, e.g. via EnterTokenStream. Annotation
// tokens are *not* reinjected.
FirstPPToken = 0x1000, // This token is the first pp token in the
// translation unit.
IsReinjected = 0x800, // A phase 4 token that was produced before and
// re-added, e.g. via EnterTokenStream. Annotation
// tokens are *not* reinjected.
HasSeenNoTrivialPPDirective =
0x1000, // Whether we've seen any 'no-trivial' pp-directives before
// current position.
};
tok::TokenKind getKind() const { return Kind; }
@ -321,8 +321,9 @@ public:
/// lexer uses identifier tokens to represent placeholders.
bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
/// Returns true if this token is the first pp-token.
bool isFirstPPToken() const { return getFlag(FirstPPToken); }
bool hasSeenNoTrivialPPDirective() const {
return getFlag(HasSeenNoTrivialPPDirective);
}
};
/// Information about the conditional stack (\#if directives)

View File

@ -9837,7 +9837,7 @@ public:
SourceLocation ModuleLoc, ModuleDeclKind MDK,
ModuleIdPath Path, ModuleIdPath Partition,
ModuleImportState &ImportState,
bool IntroducerIsFirstPPToken);
bool SeenNoTrivialPPDirective);
/// The parser has processed a global-module-fragment declaration that begins
/// the definition of the global module fragment of the current module unit.

View File

@ -60,16 +60,18 @@ template <class Emitter> class OptionScope final {
public:
/// Root constructor, compiling or discarding primitives.
OptionScope(Compiler<Emitter> *Ctx, bool NewDiscardResult,
bool NewInitializing)
bool NewInitializing, bool NewToLValue)
: Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
OldInitializing(Ctx->Initializing) {
OldInitializing(Ctx->Initializing), OldToLValue(NewToLValue) {
Ctx->DiscardResult = NewDiscardResult;
Ctx->Initializing = NewInitializing;
Ctx->ToLValue = NewToLValue;
}
~OptionScope() {
Ctx->DiscardResult = OldDiscardResult;
Ctx->Initializing = OldInitializing;
Ctx->ToLValue = OldToLValue;
}
private:
@ -78,6 +80,7 @@ private:
/// Old discard flag to restore.
bool OldDiscardResult;
bool OldInitializing;
bool OldToLValue;
};
template <class Emitter>
@ -222,6 +225,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
switch (CE->getCastKind()) {
case CK_LValueToRValue: {
if (ToLValue && CE->getType()->isPointerType())
return this->delegate(SubExpr);
if (SubExpr->getType().isVolatileQualified())
return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);
@ -4140,13 +4146,13 @@ bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {
template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) {
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,
/*NewInitializing=*/false);
/*NewInitializing=*/false, /*ToLValue=*/false);
return this->Visit(E);
}
template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {
// We're basically doing:
// OptionScope<Emitter> Scope(this, DicardResult, Initializing);
// OptionScope<Emitter> Scope(this, DicardResult, Initializing, ToLValue);
// but that's unnecessary of course.
return this->Visit(E);
}
@ -4174,7 +4180,7 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
// Otherwise,we have a primitive return value, produce the value directly
// and push it on the stack.
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
/*NewInitializing=*/false);
/*NewInitializing=*/false, /*ToLValue=*/ToLValue);
return this->Visit(E);
}
@ -4183,7 +4189,13 @@ bool Compiler<Emitter>::visitInitializer(const Expr *E) {
assert(!canClassify(E->getType()));
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
/*NewInitializing=*/true);
/*NewInitializing=*/true, /*ToLValue=*/false);
return this->Visit(E);
}
template <class Emitter> bool Compiler<Emitter>::visitAsLValue(const Expr *E) {
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
/*NewInitializing=*/false, /*ToLValue=*/true);
return this->Visit(E);
}
@ -4944,7 +4956,6 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
template <class Emitter>
bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
unsigned BuiltinID) {
if (BuiltinID == Builtin::BI__builtin_constant_p) {
// Void argument is always invalid and harder to handle later.
if (E->getArg(0)->getType()->isVoidType()) {
@ -4989,11 +5000,31 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
return false;
}
if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
// Put arguments on the stack.
for (const auto *Arg : E->arguments()) {
if (!this->visit(Arg))
// Prepare function arguments including special cases.
switch (BuiltinID) {
case Builtin::BI__builtin_object_size:
case Builtin::BI__builtin_dynamic_object_size: {
assert(E->getNumArgs() == 2);
const Expr *Arg0 = E->getArg(0);
if (Arg0->isGLValue()) {
if (!this->visit(Arg0))
return false;
} else {
if (!this->visitAsLValue(Arg0))
return false;
}
if (!this->visit(E->getArg(1)))
return false;
} break;
default:
if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
// Put arguments on the stack.
for (const auto *Arg : E->arguments()) {
if (!this->visit(Arg))
return false;
}
}
}
@ -5146,7 +5177,8 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
if (!this->emitCheckPseudoDtor(E))
return false;
const Expr *Base = PD->getBase();
if (!Base->isGLValue())
// E.g. `using T = int; 0.~T();`.
if (OptPrimType BaseT = classify(Base); !BaseT || BaseT != PT_Ptr)
return this->discard(Base);
if (!this->visit(Base))
return false;

View File

@ -282,6 +282,7 @@ protected:
/// been created. visitInitializer() then relies on a pointer to this
/// variable being on top of the stack.
bool visitInitializer(const Expr *E);
bool visitAsLValue(const Expr *E);
/// Evaluates an expression for side effects and discards the result.
bool discard(const Expr *E);
/// Just pass evaluation on to \p E. This leaves all the parsing flags
@ -426,6 +427,7 @@ protected:
bool DiscardResult = false;
bool InStmtExpr = false;
bool ToLValue = false;
/// Flag inidicating if we're initializing an already created
/// variable. This is set in visitInitializer().

View File

@ -50,9 +50,9 @@ private:
public:
/// Creates a new block.
Block(unsigned EvalID, const std::optional<unsigned> &DeclID,
const Descriptor *Desc, bool IsStatic = false, bool IsExtern = false,
bool IsWeak = false, bool IsDummy = false)
Block(unsigned EvalID, UnsignedOrNone DeclID, const Descriptor *Desc,
bool IsStatic = false, bool IsExtern = false, bool IsWeak = false,
bool IsDummy = false)
: Desc(Desc), DeclID(DeclID), EvalID(EvalID), IsStatic(IsStatic) {
assert(Desc);
AccessFlags |= (ExternFlag * IsExtern);
@ -62,8 +62,7 @@ public:
Block(unsigned EvalID, const Descriptor *Desc, bool IsStatic = false,
bool IsExtern = false, bool IsWeak = false, bool IsDummy = false)
: Desc(Desc), DeclID((unsigned)-1), EvalID(EvalID), IsStatic(IsStatic),
IsDynamic(false) {
: Desc(Desc), EvalID(EvalID), IsStatic(IsStatic), IsDynamic(false) {
assert(Desc);
AccessFlags |= (ExternFlag * IsExtern);
AccessFlags |= (WeakFlag * IsWeak);
@ -87,7 +86,7 @@ public:
/// Returns the size of the block.
unsigned getSize() const { return Desc->getAllocSize(); }
/// Returns the declaration ID.
std::optional<unsigned> getDeclID() const { return DeclID; }
UnsignedOrNone getDeclID() const { return DeclID; }
/// Returns whether the data of this block has been initialized via
/// invoking the Ctor func.
bool isInitialized() const { return IsInitialized; }
@ -177,7 +176,7 @@ private:
/// Start of the chain of pointers.
Pointer *Pointers = nullptr;
/// Unique identifier of the declaration.
std::optional<unsigned> DeclID;
UnsignedOrNone DeclID = std::nullopt;
const unsigned EvalID = ~0u;
/// Flag indicating if the block has static storage duration.
bool IsStatic = false;

View File

@ -2170,29 +2170,32 @@ static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,
return true;
}
static unsigned computeFullDescSize(const ASTContext &ASTCtx,
const Descriptor *Desc) {
static std::optional<unsigned> computeFullDescSize(const ASTContext &ASTCtx,
const Descriptor *Desc) {
if (Desc->isPrimitive())
return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
if (Desc->isArray())
return ASTCtx.getTypeSizeInChars(Desc->getElemQualType()).getQuantity() *
Desc->getNumElems();
if (Desc->isRecord()) {
// Can't use Descriptor::getType() as that may return a pointer type. Look
// at the decl directly.
return ASTCtx
.getTypeSizeInChars(
ASTCtx.getCanonicalTagType(Desc->ElemRecord->getDecl()))
.getQuantity();
}
if (Desc->isRecord())
return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
llvm_unreachable("Unhandled descriptor type");
return 0;
return std::nullopt;
}
/// Compute the byte offset of \p Ptr in the full declaration.
static unsigned computePointerOffset(const ASTContext &ASTCtx,
const Pointer &Ptr) {
unsigned Result = 0;
Pointer P = Ptr;
while (P.isArrayElement() || P.isField()) {
while (P.isField() || P.isArrayElement()) {
P = P.expand();
const Descriptor *D = P.getFieldDesc();
@ -2205,7 +2208,6 @@ static unsigned computePointerOffset(const ASTContext &ASTCtx,
Result += ElemSize * P.getIndex();
P = P.expand().getArray();
} else if (P.isBaseClass()) {
const auto *RD = cast<CXXRecordDecl>(D->asDecl());
bool IsVirtual = Ptr.isVirtualBaseClass();
P = P.getBase();
@ -2234,30 +2236,136 @@ static unsigned computePointerOffset(const ASTContext &ASTCtx,
return Result;
}
/// Does Ptr point to the last subobject?
static bool pointsToLastObject(const Pointer &Ptr) {
Pointer P = Ptr;
while (!P.isRoot()) {
if (P.isArrayElement()) {
P = P.expand().getArray();
continue;
}
if (P.isBaseClass()) {
if (P.getRecord()->getNumFields() > 0)
return false;
P = P.getBase();
continue;
}
Pointer Base = P.getBase();
if (const Record *R = Base.getRecord()) {
assert(P.getField());
if (P.getField()->getFieldIndex() != R->getNumFields() - 1)
return false;
}
P = Base;
}
return true;
}
/// Does Ptr point to the last object AND to a flexible array member?
static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const Pointer &Ptr) {
auto isFlexibleArrayMember = [&](const Descriptor *FieldDesc) {
using FAMKind = LangOptions::StrictFlexArraysLevelKind;
FAMKind StrictFlexArraysLevel =
Ctx.getLangOpts().getStrictFlexArraysLevel();
if (StrictFlexArraysLevel == FAMKind::Default)
return true;
unsigned NumElems = FieldDesc->getNumElems();
if (NumElems == 0 && StrictFlexArraysLevel != FAMKind::IncompleteOnly)
return true;
if (NumElems == 1 && StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
return true;
return false;
};
const Descriptor *FieldDesc = Ptr.getFieldDesc();
if (!FieldDesc->isArray())
return false;
return Ptr.isDummy() && pointsToLastObject(Ptr) &&
isFlexibleArrayMember(FieldDesc);
}
static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
const ASTContext &ASTCtx = S.getASTContext();
PrimType KindT = *S.getContext().classify(Call->getArg(1));
[[maybe_unused]] unsigned Kind = popToAPSInt(S.Stk, KindT).getZExtValue();
// From the GCC docs:
// Kind is an integer constant from 0 to 3. If the least significant bit is
// clear, objects are whole variables. If it is set, a closest surrounding
// subobject is considered the object a pointer points to. The second bit
// determines if maximum or minimum of remaining bytes is computed.
unsigned Kind = popToAPSInt(S.Stk, KindT).getZExtValue();
assert(Kind <= 3 && "unexpected kind");
bool UseFieldDesc = (Kind & 1u);
bool ReportMinimum = (Kind & 2u);
const Pointer &Ptr = S.Stk.pop<Pointer>();
if (Ptr.isZero())
if (Call->getArg(0)->HasSideEffects(ASTCtx)) {
// "If there are any side effects in them, it returns (size_t) -1
// for type 0 or 1 and (size_t) 0 for type 2 or 3."
pushInteger(S, Kind <= 1 ? -1 : 0, Call->getType());
return true;
}
if (Ptr.isZero() || !Ptr.isBlockPointer())
return false;
// We can't load through pointers.
if (Ptr.isDummy() && Ptr.getType()->isPointerType())
return false;
bool DetermineForCompleteObject = Ptr.getFieldDesc() == Ptr.getDeclDesc();
const Descriptor *DeclDesc = Ptr.getDeclDesc();
if (!DeclDesc)
assert(DeclDesc);
if (!UseFieldDesc || DetermineForCompleteObject) {
// Lower bound, so we can't fall back to this.
if (ReportMinimum && !DetermineForCompleteObject)
return false;
// Can't read beyond the pointer decl desc.
if (!UseFieldDesc && !ReportMinimum && DeclDesc->getType()->isPointerType())
return false;
} else {
if (isUserWritingOffTheEnd(ASTCtx, Ptr.expand())) {
// If we cannot determine the size of the initial allocation, then we
// can't given an accurate upper-bound. However, we are still able to give
// conservative lower-bounds for Type=3.
if (Kind == 1)
return false;
}
}
const Descriptor *Desc = UseFieldDesc ? Ptr.getFieldDesc() : DeclDesc;
assert(Desc);
std::optional<unsigned> FullSize = computeFullDescSize(ASTCtx, Desc);
if (!FullSize)
return false;
const ASTContext &ASTCtx = S.getASTContext();
unsigned ByteOffset;
if (UseFieldDesc) {
if (Ptr.isBaseClass())
ByteOffset = computePointerOffset(ASTCtx, Ptr.getBase()) -
computePointerOffset(ASTCtx, Ptr);
else
ByteOffset =
computePointerOffset(ASTCtx, Ptr) -
computePointerOffset(ASTCtx, Ptr.expand().atIndex(0).narrow());
} else
ByteOffset = computePointerOffset(ASTCtx, Ptr);
unsigned ByteOffset = computePointerOffset(ASTCtx, Ptr);
unsigned FullSize = computeFullDescSize(ASTCtx, DeclDesc);
pushInteger(S, FullSize - ByteOffset, Call->getType());
assert(ByteOffset <= *FullSize);
unsigned Result = *FullSize - ByteOffset;
pushInteger(S, Result, Call->getType());
return true;
}

View File

@ -593,7 +593,7 @@ public:
}
/// Returns the declaration ID.
std::optional<unsigned> getDeclID() const {
UnsignedOrNone getDeclID() const {
if (isBlockPointer()) {
assert(asBlockPointer().Pointee);
return asBlockPointer().Pointee->getDeclID();

View File

@ -164,8 +164,8 @@ unsigned Program::getOrCreateDummy(const DeclTy &D) {
const auto *VD = cast<ValueDecl>(cast<const Decl *>(D));
IsWeak = VD->isWeak();
QT = VD->getType();
if (const auto *RT = QT->getAs<ReferenceType>())
QT = RT->getPointeeType();
if (QT->isPointerOrReferenceType())
QT = QT->getPointeeType();
}
assert(!QT.isNull());

View File

@ -152,7 +152,7 @@ public:
};
/// Returns the current declaration ID.
std::optional<unsigned> getCurrentDecl() const {
UnsignedOrNone getCurrentDecl() const {
if (CurrentDeclaration == NoDeclaration)
return std::nullopt;
return CurrentDeclaration;

View File

@ -2805,32 +2805,20 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
case CXXTemporaryObjectExprClass:
case CXXConstructExprClass: {
if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) {
const auto *WarnURAttr = Type->getAttr<WarnUnusedResultAttr>();
if (Type->hasAttr<WarnUnusedAttr>() ||
(WarnURAttr && WarnURAttr->IsCXX11NoDiscard())) {
WarnE = this;
Loc = getBeginLoc();
R1 = getSourceRange();
return true;
}
}
const auto *CE = cast<CXXConstructExpr>(this);
if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
const auto *WarnURAttr = Ctor->getAttr<WarnUnusedResultAttr>();
if (WarnURAttr && WarnURAttr->IsCXX11NoDiscard()) {
WarnE = this;
Loc = getBeginLoc();
R1 = getSourceRange();
const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl();
if (unsigned NumArgs = CE->getNumArgs())
R2 = SourceRange(CE->getArg(0)->getBeginLoc(),
CE->getArg(NumArgs - 1)->getEndLoc());
return true;
}
if ((Type && Type->hasAttr<WarnUnusedAttr>()) ||
CE->hasUnusedResultAttr(Ctx)) {
WarnE = this;
Loc = getBeginLoc();
R1 = getSourceRange();
if (unsigned NumArgs = CE->getNumArgs())
R2 = SourceRange(CE->getArg(0)->getBeginLoc(),
CE->getArg(NumArgs - 1)->getEndLoc());
return true;
}
return false;
}

View File

@ -11711,6 +11711,43 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
case clang::X86::BI__builtin_ia32_pmuldq128:
case clang::X86::BI__builtin_ia32_pmuldq256:
case clang::X86::BI__builtin_ia32_pmuldq512:
case clang::X86::BI__builtin_ia32_pmuludq128:
case clang::X86::BI__builtin_ia32_pmuludq256:
case clang::X86::BI__builtin_ia32_pmuludq512: {
APValue SourceLHS, SourceRHS;
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
return false;
unsigned SourceLen = SourceLHS.getVectorLength();
SmallVector<APValue, 4> ResultElements;
ResultElements.reserve(SourceLen / 2);
for (unsigned EltNum = 0; EltNum < SourceLen; EltNum += 2) {
APSInt LHS = SourceLHS.getVectorElt(EltNum).getInt();
APSInt RHS = SourceRHS.getVectorElt(EltNum).getInt();
switch (E->getBuiltinCallee()) {
case clang::X86::BI__builtin_ia32_pmuludq128:
case clang::X86::BI__builtin_ia32_pmuludq256:
case clang::X86::BI__builtin_ia32_pmuludq512:
ResultElements.push_back(
APValue(APSInt(llvm::APIntOps::muluExtended(LHS, RHS), true)));
break;
case clang::X86::BI__builtin_ia32_pmuldq128:
case clang::X86::BI__builtin_ia32_pmuldq256:
case clang::X86::BI__builtin_ia32_pmuldq512:
ResultElements.push_back(
APValue(APSInt(llvm::APIntOps::mulsExtended(LHS, RHS), false)));
break;
}
}
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
case Builtin::BI__builtin_elementwise_max:
case Builtin::BI__builtin_elementwise_min: {
APValue SourceLHS, SourceRHS;
@ -11746,6 +11783,50 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
case X86::BI__builtin_ia32_selectb_128:
case X86::BI__builtin_ia32_selectb_256:
case X86::BI__builtin_ia32_selectb_512:
case X86::BI__builtin_ia32_selectw_128:
case X86::BI__builtin_ia32_selectw_256:
case X86::BI__builtin_ia32_selectw_512:
case X86::BI__builtin_ia32_selectd_128:
case X86::BI__builtin_ia32_selectd_256:
case X86::BI__builtin_ia32_selectd_512:
case X86::BI__builtin_ia32_selectq_128:
case X86::BI__builtin_ia32_selectq_256:
case X86::BI__builtin_ia32_selectq_512:
case X86::BI__builtin_ia32_selectph_128:
case X86::BI__builtin_ia32_selectph_256:
case X86::BI__builtin_ia32_selectph_512:
case X86::BI__builtin_ia32_selectpbf_128:
case X86::BI__builtin_ia32_selectpbf_256:
case X86::BI__builtin_ia32_selectpbf_512:
case X86::BI__builtin_ia32_selectps_128:
case X86::BI__builtin_ia32_selectps_256:
case X86::BI__builtin_ia32_selectps_512:
case X86::BI__builtin_ia32_selectpd_128:
case X86::BI__builtin_ia32_selectpd_256:
case X86::BI__builtin_ia32_selectpd_512: {
// AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".
APValue SourceMask, SourceLHS, SourceRHS;
if (!EvaluateAsRValue(Info, E->getArg(0), SourceMask) ||
!EvaluateAsRValue(Info, E->getArg(1), SourceLHS) ||
!EvaluateAsRValue(Info, E->getArg(2), SourceRHS))
return false;
APSInt Mask = SourceMask.getInt();
unsigned SourceLen = SourceLHS.getVectorLength();
SmallVector<APValue, 4> ResultElements;
ResultElements.reserve(SourceLen);
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
const APValue &LHS = SourceLHS.getVectorElt(EltNum);
const APValue &RHS = SourceRHS.getVectorElt(EltNum);
ResultElements.push_back(Mask[EltNum] ? LHS : RHS);
}
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
}
}

View File

@ -440,37 +440,37 @@ public:
#define GEN_CLANG_CLAUSE_CLASS
#define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(const Class *C);
#include "llvm/Frontend/OpenMP/OMP.inc"
void VistOMPClauseWithPreInit(const OMPClauseWithPreInit *C);
void VistOMPClauseWithPostUpdate(const OMPClauseWithPostUpdate *C);
void VisitOMPClauseWithPreInit(const OMPClauseWithPreInit *C);
void VisitOMPClauseWithPostUpdate(const OMPClauseWithPostUpdate *C);
};
void OMPClauseProfiler::VistOMPClauseWithPreInit(
void OMPClauseProfiler::VisitOMPClauseWithPreInit(
const OMPClauseWithPreInit *C) {
if (auto *S = C->getPreInitStmt())
Profiler->VisitStmt(S);
}
void OMPClauseProfiler::VistOMPClauseWithPostUpdate(
void OMPClauseProfiler::VisitOMPClauseWithPostUpdate(
const OMPClauseWithPostUpdate *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (auto *E = C->getPostUpdateExpr())
Profiler->VisitStmt(E);
}
void OMPClauseProfiler::VisitOMPIfClause(const OMPIfClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (C->getCondition())
Profiler->VisitStmt(C->getCondition());
}
void OMPClauseProfiler::VisitOMPFinalClause(const OMPFinalClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (C->getCondition())
Profiler->VisitStmt(C->getCondition());
}
void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (C->getNumThreads())
Profiler->VisitStmt(C->getNumThreads());
}
@ -526,13 +526,13 @@ void OMPClauseProfiler::VisitOMPDetachClause(const OMPDetachClause *C) {
}
void OMPClauseProfiler::VisitOMPNovariantsClause(const OMPNovariantsClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (C->getCondition())
Profiler->VisitStmt(C->getCondition());
}
void OMPClauseProfiler::VisitOMPNocontextClause(const OMPNocontextClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (C->getCondition())
Profiler->VisitStmt(C->getCondition());
}
@ -568,7 +568,7 @@ void OMPClauseProfiler::VisitOMPMessageClause(const OMPMessageClause *C) {
}
void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (auto *S = C->getChunkSize())
Profiler->VisitStmt(S);
}
@ -646,7 +646,7 @@ void OMPClauseProfiler::VisitOMPDestroyClause(const OMPDestroyClause *C) {
}
void OMPClauseProfiler::VisitOMPFilterClause(const OMPFilterClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (C->getThreadID())
Profiler->VisitStmt(C->getThreadID());
}
@ -669,7 +669,7 @@ void OMPClauseProfiler::VisitOMPPrivateClause(const OMPPrivateClause *C) {
void
OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) {
VisitOMPClauseList(C);
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
for (auto *E : C->private_copies()) {
if (E)
Profiler->VisitStmt(E);
@ -682,7 +682,7 @@ OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) {
void
OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) {
VisitOMPClauseList(C);
VistOMPClauseWithPostUpdate(C);
VisitOMPClauseWithPostUpdate(C);
for (auto *E : C->source_exprs()) {
if (E)
Profiler->VisitStmt(E);
@ -705,7 +705,7 @@ void OMPClauseProfiler::VisitOMPReductionClause(
C->getQualifierLoc().getNestedNameSpecifier());
Profiler->VisitName(C->getNameInfo().getName());
VisitOMPClauseList(C);
VistOMPClauseWithPostUpdate(C);
VisitOMPClauseWithPostUpdate(C);
for (auto *E : C->privates()) {
if (E)
Profiler->VisitStmt(E);
@ -743,7 +743,7 @@ void OMPClauseProfiler::VisitOMPTaskReductionClause(
C->getQualifierLoc().getNestedNameSpecifier());
Profiler->VisitName(C->getNameInfo().getName());
VisitOMPClauseList(C);
VistOMPClauseWithPostUpdate(C);
VisitOMPClauseWithPostUpdate(C);
for (auto *E : C->privates()) {
if (E)
Profiler->VisitStmt(E);
@ -767,7 +767,7 @@ void OMPClauseProfiler::VisitOMPInReductionClause(
C->getQualifierLoc().getNestedNameSpecifier());
Profiler->VisitName(C->getNameInfo().getName());
VisitOMPClauseList(C);
VistOMPClauseWithPostUpdate(C);
VisitOMPClauseWithPostUpdate(C);
for (auto *E : C->privates()) {
if (E)
Profiler->VisitStmt(E);
@ -791,7 +791,7 @@ void OMPClauseProfiler::VisitOMPInReductionClause(
}
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
VistOMPClauseWithPostUpdate(C);
VisitOMPClauseWithPostUpdate(C);
for (auto *E : C->privates()) {
if (E)
Profiler->VisitStmt(E);
@ -873,25 +873,25 @@ void OMPClauseProfiler::VisitOMPAllocateClause(const OMPAllocateClause *C) {
}
void OMPClauseProfiler::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) {
VisitOMPClauseList(C);
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
}
void OMPClauseProfiler::VisitOMPThreadLimitClause(
const OMPThreadLimitClause *C) {
VisitOMPClauseList(C);
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
}
void OMPClauseProfiler::VisitOMPPriorityClause(const OMPPriorityClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (C->getPriority())
Profiler->VisitStmt(C->getPriority());
}
void OMPClauseProfiler::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (C->getGrainsize())
Profiler->VisitStmt(C->getGrainsize());
}
void OMPClauseProfiler::VisitOMPNumTasksClause(const OMPNumTasksClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (C->getNumTasks())
Profiler->VisitStmt(C->getNumTasks());
}
@ -952,7 +952,7 @@ void OMPClauseProfiler::VisitOMPOrderClause(const OMPOrderClause *C) {}
void OMPClauseProfiler::VisitOMPBindClause(const OMPBindClause *C) {}
void OMPClauseProfiler::VisitOMPXDynCGroupMemClause(
const OMPXDynCGroupMemClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (Expr *Size = C->getSize())
Profiler->VisitStmt(Size);
}
@ -1229,7 +1229,7 @@ void StmtProfiler::VisitOMPDistributeDirective(
void OMPClauseProfiler::VisitOMPDistScheduleClause(
const OMPDistScheduleClause *C) {
VistOMPClauseWithPreInit(C);
VisitOMPClauseWithPreInit(C);
if (auto *S = C->getChunkSize())
Profiler->VisitStmt(S);
}

View File

@ -1627,7 +1627,7 @@ bool QualType::UseExcessPrecision(const ASTContext &Ctx) {
switch (BT->getKind()) {
case BuiltinType::Kind::Float16: {
const TargetInfo &TI = Ctx.getTargetInfo();
if (TI.hasFloat16Type() && !TI.hasLegalHalfType() &&
if (TI.hasFloat16Type() && !TI.hasFastHalfType() &&
Ctx.getLangOpts().getFloat16ExcessPrecision() !=
Ctx.getLangOpts().ExcessPrecisionKind::FPP_None)
return true;

View File

@ -1344,6 +1344,41 @@ private:
return false;
}
template <typename T> static SourceLocation getNodeLocation(const T &Node) {
return Node.getBeginLoc();
}
static SourceLocation getNodeLocation(const CXXCtorInitializer &Node) {
return Node.getSourceLocation();
}
static SourceLocation getNodeLocation(const TemplateArgumentLoc &Node) {
return Node.getLocation();
}
static SourceLocation getNodeLocation(const Attr &Node) {
return Node.getLocation();
}
bool isInSystemHeader(SourceLocation Loc) {
const SourceManager &SM = getASTContext().getSourceManager();
return SM.isInSystemHeader(Loc);
}
template <typename T> bool shouldSkipNode(T &Node) {
if (Options.IgnoreSystemHeaders && isInSystemHeader(getNodeLocation(Node)))
return true;
return false;
}
template <typename T> bool shouldSkipNode(T *Node) {
return (Node == nullptr) || shouldSkipNode(*Node);
}
bool shouldSkipNode(QualType &) { return false; }
bool shouldSkipNode(NestedNameSpecifier &) { return false; }
/// Bucket to record map.
///
/// Used to get the appropriate bucket for each matcher.
@ -1473,9 +1508,8 @@ bool MatchASTVisitor::objcClassIsDerivedFrom(
}
bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
if (!DeclNode) {
if (shouldSkipNode(DeclNode))
return true;
}
bool ScopedTraversal =
TraversingASTNodeNotSpelledInSource || DeclNode->isImplicit();
@ -1503,9 +1537,9 @@ bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
}
bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
if (!StmtNode) {
if (shouldSkipNode(StmtNode))
return true;
}
bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
TraversingASTChildrenNotSpelledInSource;
@ -1515,6 +1549,9 @@ bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) {
}
bool MatchASTVisitor::TraverseType(QualType TypeNode, bool TraverseQualifier) {
if (shouldSkipNode(TypeNode))
return true;
match(TypeNode);
return RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode,
TraverseQualifier);
@ -1522,6 +1559,8 @@ bool MatchASTVisitor::TraverseType(QualType TypeNode, bool TraverseQualifier) {
bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode,
bool TraverseQualifier) {
if (shouldSkipNode(TypeLocNode))
return true;
// The RecursiveASTVisitor only visits types if they're not within TypeLocs.
// We still want to find those types via matchers, so we match them here. Note
// that the TypeLocs are structurally a shadow-hierarchy to the expressed
@ -1534,6 +1573,9 @@ bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode,
}
bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier NNS) {
if (shouldSkipNode(NNS))
return true;
match(NNS);
return RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifier(NNS);
}
@ -1543,6 +1585,9 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
if (!NNS)
return true;
if (shouldSkipNode(NNS))
return true;
match(NNS);
// We only match the nested name specifier here (as opposed to traversing it)
@ -1555,7 +1600,7 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
bool MatchASTVisitor::TraverseConstructorInitializer(
CXXCtorInitializer *CtorInit) {
if (!CtorInit)
if (shouldSkipNode(CtorInit))
return true;
bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
@ -1573,11 +1618,17 @@ bool MatchASTVisitor::TraverseConstructorInitializer(
}
bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
if (shouldSkipNode(Loc))
return true;
match(Loc);
return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc);
}
bool MatchASTVisitor::TraverseAttr(Attr *AttrNode) {
if (shouldSkipNode(AttrNode))
return true;
match(*AttrNode);
return RecursiveASTVisitor<MatchASTVisitor>::TraverseAttr(AttrNode);
}

View File

@ -45,10 +45,11 @@ struct Loan {
/// is represented as empty LoanSet
LoanID ID;
AccessPath Path;
SourceLocation IssueLoc;
/// The expression that creates the loan, e.g., &x.
const Expr *IssueExpr;
Loan(LoanID id, AccessPath path, SourceLocation loc)
: ID(id), Path(path), IssueLoc(loc) {}
Loan(LoanID id, AccessPath path, const Expr *IssueExpr)
: ID(id), Path(path), IssueExpr(IssueExpr) {}
};
/// An Origin is a symbolic identifier that represents the set of possible
@ -82,8 +83,8 @@ class LoanManager {
public:
LoanManager() = default;
Loan &addLoan(AccessPath Path, SourceLocation Loc) {
AllLoans.emplace_back(getNextLoanID(), Path, Loc);
Loan &addLoan(AccessPath Path, const Expr *IssueExpr) {
AllLoans.emplace_back(getNextLoanID(), Path, IssueExpr);
return AllLoans.back();
}
@ -199,6 +200,8 @@ public:
AssignOrigin,
/// An origin escapes the function by flowing into the return value.
ReturnOfOrigin,
/// An origin is used (eg. dereferencing a pointer).
Use,
/// A marker for a specific point in the code, for testing.
TestPoint,
};
@ -242,12 +245,17 @@ public:
class ExpireFact : public Fact {
LoanID LID;
SourceLocation ExpiryLoc;
public:
static bool classof(const Fact *F) { return F->getKind() == Kind::Expire; }
ExpireFact(LoanID LID) : Fact(Kind::Expire), LID(LID) {}
ExpireFact(LoanID LID, SourceLocation ExpiryLoc)
: Fact(Kind::Expire), LID(LID), ExpiryLoc(ExpiryLoc) {}
LoanID getLoanID() const { return LID; }
SourceLocation getExpiryLoc() const { return ExpiryLoc; }
void dump(llvm::raw_ostream &OS) const override {
OS << "Expire (LoanID: " << getLoanID() << ")\n";
}
@ -287,6 +295,24 @@ public:
}
};
class UseFact : public Fact {
OriginID UsedOrigin;
const Expr *UseExpr;
public:
static bool classof(const Fact *F) { return F->getKind() == Kind::Use; }
UseFact(OriginID UsedOrigin, const Expr *UseExpr)
: Fact(Kind::Use), UsedOrigin(UsedOrigin), UseExpr(UseExpr) {}
OriginID getUsedOrigin() const { return UsedOrigin; }
const Expr *getUseExpr() const { return UseExpr; }
void dump(llvm::raw_ostream &OS) const override {
OS << "Use (OriginID: " << UsedOrigin << ")\n";
}
};
/// A dummy-fact used to mark a specific point in the code for testing.
/// It is generated by recognizing a `void("__lifetime_test_point_...")` cast.
class TestPointFact : public Fact {
@ -417,13 +443,17 @@ public:
if (VD->hasLocalStorage()) {
OriginID OID = FactMgr.getOriginMgr().getOrCreate(*UO);
AccessPath AddrOfLocalVarPath(VD);
const Loan &L = FactMgr.getLoanMgr().addLoan(AddrOfLocalVarPath,
UO->getOperatorLoc());
const Loan &L =
FactMgr.getLoanMgr().addLoan(AddrOfLocalVarPath, UO);
CurrentBlockFacts.push_back(
FactMgr.createFact<IssueFact>(L.ID, OID));
}
}
}
} else if (UO->getOpcode() == UO_Deref) {
// This is a pointer use, like '*p'.
OriginID OID = FactMgr.getOriginMgr().get(*UO->getSubExpr());
CurrentBlockFacts.push_back(FactMgr.createFact<UseFact>(OID, UO));
}
}
@ -492,7 +522,8 @@ private:
// Check if the loan is for a stack variable and if that variable
// is the one being destructed.
if (LoanPath.D == DestructedVD)
CurrentBlockFacts.push_back(FactMgr.createFact<ExpireFact>(L.ID));
CurrentBlockFacts.push_back(FactMgr.createFact<ExpireFact>(
L.ID, DtorOpt.getTriggerStmt()->getEndLoc()));
}
}
@ -618,6 +649,7 @@ public:
}
}
protected:
Lattice getState(ProgramPoint P) const { return PerPointStates.lookup(P); }
Lattice getInState(const CFGBlock *B) const { return InStates.lookup(B); }
@ -665,6 +697,8 @@ private:
return D->transfer(In, *F->getAs<AssignOriginFact>());
case Fact::Kind::ReturnOfOrigin:
return D->transfer(In, *F->getAs<ReturnOfOriginFact>());
case Fact::Kind::Use:
return D->transfer(In, *F->getAs<UseFact>());
case Fact::Kind::TestPoint:
return D->transfer(In, *F->getAs<TestPointFact>());
}
@ -676,6 +710,7 @@ public:
Lattice transfer(Lattice In, const ExpireFact &) { return In; }
Lattice transfer(Lattice In, const AssignOriginFact &) { return In; }
Lattice transfer(Lattice In, const ReturnOfOriginFact &) { return In; }
Lattice transfer(Lattice In, const UseFact &) { return In; }
Lattice transfer(Lattice In, const TestPointFact &) { return In; }
};
@ -693,6 +728,20 @@ static llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A,
return A;
}
/// Checks if set A is a subset of set B.
template <typename T>
static bool isSubsetOf(const llvm::ImmutableSet<T> &A,
const llvm::ImmutableSet<T> &B) {
// Empty set is a subset of all sets.
if (A.isEmpty())
return true;
for (const T &Elem : A)
if (!B.contains(Elem))
return false;
return true;
}
/// Computes the key-wise union of two ImmutableMaps.
// TODO(opt): This key-wise join is a performance bottleneck. A more
// efficient merge could be implemented using a Patricia Trie or HAMT
@ -700,7 +749,7 @@ static llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A,
template <typename K, typename V, typename Joiner>
static llvm::ImmutableMap<K, V>
join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
typename llvm::ImmutableMap<K, V>::Factory &F, Joiner joinValues) {
typename llvm::ImmutableMap<K, V>::Factory &F, Joiner JoinValues) {
if (A.getHeight() < B.getHeight())
std::swap(A, B);
@ -710,7 +759,7 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
const K &Key = Entry.first;
const V &ValB = Entry.second;
if (const V *ValA = A.lookup(Key))
A = F.add(A, Key, joinValues(*ValA, ValB));
A = F.add(A, Key, JoinValues(*ValA, ValB));
else
A = F.add(A, Key, ValB);
}
@ -723,17 +772,14 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
// ========================================================================= //
using OriginLoanMap = llvm::ImmutableMap<OriginID, LoanSet>;
using ExpiredLoanMap = llvm::ImmutableMap<LoanID, const ExpireFact *>;
/// An object to hold the factories for immutable collections, ensuring
/// that all created states share the same underlying memory management.
struct LifetimeFactory {
OriginLoanMap::Factory OriginMapFactory;
LoanSet::Factory LoanSetFactory;
/// Creates a singleton set containing only the given loan ID.
LoanSet createLoanSet(LoanID LID) {
return LoanSetFactory.add(LoanSetFactory.getEmptySet(), LID);
}
ExpiredLoanMap::Factory ExpiredLoanMapFactory;
};
/// Represents the dataflow lattice for loan propagation.
@ -774,13 +820,15 @@ struct LoanPropagationLattice {
class LoanPropagationAnalysis
: public DataflowAnalysis<LoanPropagationAnalysis, LoanPropagationLattice,
Direction::Forward> {
LifetimeFactory &Factory;
OriginLoanMap::Factory &OriginLoanMapFactory;
LoanSet::Factory &LoanSetFactory;
public:
LoanPropagationAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
LifetimeFactory &Factory)
: DataflowAnalysis(C, AC, F), Factory(Factory) {}
LifetimeFactory &LFactory)
: DataflowAnalysis(C, AC, F),
OriginLoanMapFactory(LFactory.OriginMapFactory),
LoanSetFactory(LFactory.LoanSetFactory) {}
using Base::transfer;
@ -792,9 +840,9 @@ public:
// TODO(opt): Keep the state small by removing origins which become dead.
Lattice join(Lattice A, Lattice B) {
OriginLoanMap JoinedOrigins =
utils::join(A.Origins, B.Origins, Factory.OriginMapFactory,
[this](LoanSet S1, LoanSet S2) {
return utils::join(S1, S2, Factory.LoanSetFactory);
utils::join(A.Origins, B.Origins, OriginLoanMapFactory,
[&](LoanSet S1, LoanSet S2) {
return utils::join(S1, S2, LoanSetFactory);
});
return Lattice(JoinedOrigins);
}
@ -803,8 +851,9 @@ public:
Lattice transfer(Lattice In, const IssueFact &F) {
OriginID OID = F.getOriginID();
LoanID LID = F.getLoanID();
return LoanPropagationLattice(Factory.OriginMapFactory.add(
In.Origins, OID, Factory.createLoanSet(LID)));
return LoanPropagationLattice(OriginLoanMapFactory.add(
In.Origins, OID,
LoanSetFactory.add(LoanSetFactory.getEmptySet(), LID)));
}
/// The destination origin's loan set is replaced by the source's.
@ -814,7 +863,7 @@ public:
OriginID SrcOID = F.getSrcOriginID();
LoanSet SrcLoans = getLoans(In, SrcOID);
return LoanPropagationLattice(
Factory.OriginMapFactory.add(In.Origins, DestOID, SrcLoans));
OriginLoanMapFactory.add(In.Origins, DestOID, SrcLoans));
}
LoanSet getLoans(OriginID OID, ProgramPoint P) {
@ -825,7 +874,7 @@ private:
LoanSet getLoans(Lattice L, OriginID OID) {
if (auto *Loans = L.Origins.lookup(OID))
return *Loans;
return Factory.LoanSetFactory.getEmptySet();
return LoanSetFactory.getEmptySet();
}
};
@ -835,10 +884,11 @@ private:
/// The dataflow lattice for tracking the set of expired loans.
struct ExpiredLattice {
LoanSet Expired;
/// Map from an expired `LoanID` to the `ExpireFact` that made it expire.
ExpiredLoanMap Expired;
ExpiredLattice() : Expired(nullptr) {};
explicit ExpiredLattice(LoanSet S) : Expired(S) {}
explicit ExpiredLattice(ExpiredLoanMap M) : Expired(M) {}
bool operator==(const ExpiredLattice &Other) const {
return Expired == Other.Expired;
@ -851,8 +901,8 @@ struct ExpiredLattice {
OS << "ExpiredLattice State:\n";
if (Expired.isEmpty())
OS << " <empty>\n";
for (const LoanID &LID : Expired)
OS << " Loan " << LID << " is expired\n";
for (const auto &[ID, _] : Expired)
OS << " Loan " << ID << " is expired\n";
}
};
@ -861,26 +911,31 @@ class ExpiredLoansAnalysis
: public DataflowAnalysis<ExpiredLoansAnalysis, ExpiredLattice,
Direction::Forward> {
LoanSet::Factory &Factory;
ExpiredLoanMap::Factory &Factory;
public:
ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
LifetimeFactory &Factory)
: DataflowAnalysis(C, AC, F), Factory(Factory.LoanSetFactory) {}
: DataflowAnalysis(C, AC, F), Factory(Factory.ExpiredLoanMapFactory) {}
using Base::transfer;
StringRef getAnalysisName() const { return "ExpiredLoans"; }
Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
Lattice getInitialState() { return Lattice(Factory.getEmptyMap()); }
/// Merges two lattices by taking the union of the expired loan sets.
Lattice join(Lattice L1, Lattice L2) const {
return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
/// Merges two lattices by taking the union of the two expired loans.
Lattice join(Lattice L1, Lattice L2) {
return Lattice(
utils::join(L1.Expired, L2.Expired, Factory,
// Take the last expiry fact to make this hermetic.
[](const ExpireFact *F1, const ExpireFact *F2) {
return F1->getExpiryLoc() > F2->getExpiryLoc() ? F1 : F2;
}));
}
Lattice transfer(Lattice In, const ExpireFact &F) {
return Lattice(Factory.add(In.Expired, F.getLoanID()));
return Lattice(Factory.add(In.Expired, F.getLoanID(), &F));
}
// Removes the loan from the set of expired loans.
@ -912,15 +967,116 @@ public:
Lattice transfer(Lattice In, const IssueFact &F) {
return Lattice(Factory.remove(In.Expired, F.getLoanID()));
}
ExpiredLoanMap getExpiredLoans(ProgramPoint P) { return getState(P).Expired; }
};
// ========================================================================= //
// TODO:
// - Modify loan expiry analysis to answer `bool isExpired(Loan L, Point P)`
// - Modify origin liveness analysis to answer `bool isLive(Origin O, Point P)`
// - Using the above three to perform the final error reporting.
// Lifetime checker and Error reporter
// ========================================================================= //
/// Struct to store the complete context for a potential lifetime violation.
struct PendingWarning {
SourceLocation ExpiryLoc; // Where the loan expired.
const Expr *UseExpr; // Where the origin holding this loan was used.
Confidence ConfidenceLevel;
};
class LifetimeChecker {
private:
llvm::DenseMap<LoanID, PendingWarning> FinalWarningsMap;
LoanPropagationAnalysis &LoanPropagation;
ExpiredLoansAnalysis &ExpiredLoans;
FactManager &FactMgr;
AnalysisDeclContext &ADC;
LifetimeSafetyReporter *Reporter;
public:
LifetimeChecker(LoanPropagationAnalysis &LPA, ExpiredLoansAnalysis &ELA,
FactManager &FM, AnalysisDeclContext &ADC,
LifetimeSafetyReporter *Reporter)
: LoanPropagation(LPA), ExpiredLoans(ELA), FactMgr(FM), ADC(ADC),
Reporter(Reporter) {}
void run() {
llvm::TimeTraceScope TimeProfile("LifetimeChecker");
for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
for (const Fact *F : FactMgr.getFacts(B))
if (const auto *UF = F->getAs<UseFact>())
checkUse(UF);
issuePendingWarnings();
}
/// Checks for use-after-free errors for a given use of an Origin.
///
/// This method is called for each 'UseFact' identified in the control flow
/// graph. It determines if the loans held by the used origin have expired
/// at the point of use.
void checkUse(const UseFact *UF) {
OriginID O = UF->getUsedOrigin();
// Get the set of loans that the origin might hold at this program point.
LoanSet HeldLoans = LoanPropagation.getLoans(O, UF);
// Get the set of all loans that have expired at this program point.
ExpiredLoanMap AllExpiredLoans = ExpiredLoans.getExpiredLoans(UF);
// If the pointer holds no loans or no loans have expired, there's nothing
// to check.
if (HeldLoans.isEmpty() || AllExpiredLoans.isEmpty())
return;
// Identify loans that which have expired but are held by the pointer. Using
// them is a use-after-free.
llvm::SmallVector<LoanID> DefaultedLoans;
// A definite UaF error occurs if all loans the origin might hold have
// expired.
bool IsDefiniteError = true;
for (LoanID L : HeldLoans) {
if (AllExpiredLoans.contains(L))
DefaultedLoans.push_back(L);
else
// If at least one loan is not expired, this use is not a definite UaF.
IsDefiniteError = false;
}
// If there are no defaulted loans, the use is safe.
if (DefaultedLoans.empty())
return;
// Determine the confidence level of the error (definite or maybe).
Confidence CurrentConfidence =
IsDefiniteError ? Confidence::Definite : Confidence::Maybe;
// For each expired loan, create a pending warning.
for (LoanID DefaultedLoan : DefaultedLoans) {
// If we already have a warning for this loan with a higher or equal
// confidence, skip this one.
if (FinalWarningsMap.count(DefaultedLoan) &&
CurrentConfidence <= FinalWarningsMap[DefaultedLoan].ConfidenceLevel)
continue;
auto *EF = AllExpiredLoans.lookup(DefaultedLoan);
assert(EF && "Could not find ExpireFact for an expired loan.");
FinalWarningsMap[DefaultedLoan] = {/*ExpiryLoc=*/(*EF)->getExpiryLoc(),
/*UseExpr=*/UF->getUseExpr(),
/*ConfidenceLevel=*/CurrentConfidence};
}
}
void issuePendingWarnings() {
if (!Reporter)
return;
for (const auto &[LID, Warning] : FinalWarningsMap) {
const Loan &L = FactMgr.getLoanMgr().getLoan(LID);
const Expr *IssueExpr = L.IssueExpr;
Reporter->reportUseAfterFree(IssueExpr, Warning.UseExpr,
Warning.ExpiryLoc, Warning.ConfidenceLevel);
}
}
};
// ========================================================================= //
// LifetimeSafetyAnalysis Class Implementation
// ========================================================================= //
@ -928,8 +1084,9 @@ public:
// We need this here for unique_ptr with forward declared class.
LifetimeSafetyAnalysis::~LifetimeSafetyAnalysis() = default;
LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC)
: AC(AC), Factory(std::make_unique<LifetimeFactory>()),
LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
LifetimeSafetyReporter *Reporter)
: AC(AC), Reporter(Reporter), Factory(std::make_unique<LifetimeFactory>()),
FactMgr(std::make_unique<FactManager>()) {}
void LifetimeSafetyAnalysis::run() {
@ -952,6 +1109,8 @@ void LifetimeSafetyAnalysis::run() {
/// blocks; only Decls are visible. Therefore, loans in a block that
/// never reach an Origin associated with a Decl can be safely dropped by
/// the analysis.
/// 3. Collapse ExpireFacts belonging to same source location into a single
/// Fact.
LoanPropagation =
std::make_unique<LoanPropagationAnalysis>(Cfg, AC, *FactMgr, *Factory);
LoanPropagation->run();
@ -959,6 +1118,10 @@ void LifetimeSafetyAnalysis::run() {
ExpiredLoans =
std::make_unique<ExpiredLoansAnalysis>(Cfg, AC, *FactMgr, *Factory);
ExpiredLoans->run();
LifetimeChecker Checker(*LoanPropagation, *ExpiredLoans, *FactMgr, AC,
Reporter);
Checker.run();
}
LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID,
@ -967,9 +1130,13 @@ LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID,
return LoanPropagation->getLoans(OID, PP);
}
LoanSet LifetimeSafetyAnalysis::getExpiredLoansAtPoint(ProgramPoint PP) const {
std::vector<LoanID>
LifetimeSafetyAnalysis::getExpiredLoansAtPoint(ProgramPoint PP) const {
assert(ExpiredLoans && "ExpiredLoansAnalysis has not been run.");
return ExpiredLoans->getState(PP).Expired;
std::vector<LoanID> Result;
for (const auto &pair : ExpiredLoans->getExpiredLoans(PP))
Result.push_back(pair.first);
return Result;
}
std::optional<OriginID>
@ -1009,8 +1176,9 @@ llvm::StringMap<ProgramPoint> LifetimeSafetyAnalysis::getTestPoints() const {
}
} // namespace internal
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC) {
internal::LifetimeSafetyAnalysis Analysis(AC);
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
LifetimeSafetyReporter *Reporter) {
internal::LifetimeSafetyAnalysis Analysis(AC, Reporter);
Analysis.run();
}
} // namespace clang::lifetimes

View File

@ -62,7 +62,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
TLSSupported = true;
VLASupported = true;
NoAsmVariants = false;
HasLegalHalfType = false;
HasFastHalfType = false;
HalfArgsAndReturns = false;
HasFloat128 = false;
HasIbm128 = false;

View File

@ -142,7 +142,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
AddrSpaceMap = &ARM64AddrSpaceMap;
// All AArch64 implementations support ARMv8 FP, which makes half a legal type.
HasLegalHalfType = true;
HasFastHalfType = true;
HalfArgsAndReturns = true;
HasFloat16 = true;
HasStrictFP = true;

View File

@ -251,7 +251,7 @@ AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
BFloat16Format = &llvm::APFloat::BFloat();
}
HasLegalHalfType = true;
HasFastHalfType = true;
HasFloat16 = true;
WavefrontSize = (GPUFeatures & llvm::AMDGPU::FEATURE_WAVE32) ? 32 : 64;

View File

@ -585,13 +585,13 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
} else if (Feature == "+fp16") {
HW_FP |= HW_FP_HP;
} else if (Feature == "+fullfp16") {
HasLegalHalfType = true;
HasFastHalfType = true;
} else if (Feature == "+dotprod") {
DotProd = true;
} else if (Feature == "+mve") {
MVE |= MVE_INT;
} else if (Feature == "+mve.fp") {
HasLegalHalfType = true;
HasFastHalfType = true;
FPU |= FPARMV8;
MVE |= MVE_INT | MVE_FP;
HW_FP |= HW_FP_SP | HW_FP_HP;
@ -1014,11 +1014,11 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__ARM_FP_FAST", "1");
// Armv8.2-A FP16 vector intrinsic
if ((FPU & NeonFPU) && HasLegalHalfType)
if ((FPU & NeonFPU) && HasFastHalfType)
Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
// Armv8.2-A FP16 scalar intrinsics
if (HasLegalHalfType)
if (HasFastHalfType)
Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
// Armv8.2-A dot product intrinsics

View File

@ -59,7 +59,7 @@ public:
VLASupported = false;
AddrSpaceMap = &DirectXAddrSpaceMap;
UseAddrSpaceMapMangling = true;
HasLegalHalfType = true;
HasFastHalfType = true;
HasFloat16 = true;
NoAsmVariants = true;
PlatformMinVersion = Triple.getOSVersion();

View File

@ -149,7 +149,7 @@ bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasAudio = true;
}
if (CPU.compare("hexagonv68") >= 0) {
HasLegalHalfType = true;
HasFastHalfType = true;
HasFloat16 = true;
}
return true;

View File

@ -65,7 +65,7 @@ NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
GPU = OffloadArch::UNUSED;
// PTX supports f16 as a fundamental type.
HasLegalHalfType = true;
HasFastHalfType = true;
HasFloat16 = true;
if (TargetPointerWidth == 32)

View File

@ -427,7 +427,7 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
ABI = ISAInfo->computeDefaultABI().str();
if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx"))
HasLegalHalfType = true;
HasFastHalfType = true;
FastScalarUnalignedAccess =
llvm::is_contained(Features, "+unaligned-scalar-mem");

View File

@ -106,7 +106,7 @@ protected:
LongWidth = LongAlign = 64;
AddrSpaceMap = &SPIRDefIsPrivMap;
UseAddrSpaceMapMangling = true;
HasLegalHalfType = true;
HasFastHalfType = true;
HasFloat16 = true;
// Define available target features
// These must be defined in sorted order!
@ -427,7 +427,7 @@ public:
BFloat16Width = BFloat16Align = 16;
BFloat16Format = &llvm::APFloat::BFloat();
HasLegalHalfType = true;
HasFastHalfType = true;
HasFloat16 = true;
HalfArgsAndReturns = true;

View File

@ -104,7 +104,7 @@ public:
// -ffloat16-excess-precision=none is given, no conversions will be made
// and instead the backend will promote each half operation to float
// individually.
HasLegalHalfType = false;
HasFastHalfType = false;
HasStrictFP = true;
}

View File

@ -348,7 +348,7 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasAVX512BF16 = true;
} else if (Feature == "+avx512fp16") {
HasAVX512FP16 = true;
HasLegalHalfType = true;
HasFastHalfType = true;
} else if (Feature == "+avx512dq") {
HasAVX512DQ = true;
} else if (Feature == "+avx512bitalg") {

View File

@ -387,6 +387,20 @@ class OpenACCClauseCIREmitter final
return recipeName;
}
void createFirstprivateRecipeCopy(
mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp,
CIRGenFunction::AutoVarEmission tempDeclEmission,
mlir::acc::FirstprivateRecipeOp recipe, const VarDecl *varRecipe,
const VarDecl *temporary) {
builder.createBlock(&recipe.getCopyRegion(), recipe.getCopyRegion().end(),
{mainOp.getType(), mainOp.getType()}, {loc, loc});
builder.setInsertionPointToEnd(&recipe.getCopyRegion().back());
// TODO: OpenACC: Implement this copy to actually do something.
mlir::acc::YieldOp::create(builder, locEnd);
}
// Create the 'init' section of the recipe, including the 'copy' section for
// 'firstprivate'.
template <typename RecipeTy>
@ -401,12 +415,6 @@ class OpenACCClauseCIREmitter final
cgf.cgm.errorNYI(exprRange, "OpenACC Reduction recipe init");
}
if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
// We haven't implemented the 'init'/copy recipe for firstprivate yet, so
// NYI it.
cgf.cgm.errorNYI(exprRange, "OpenACC firstprivate recipe init");
}
CIRGenFunction::AutoVarEmission tempDeclEmission{
CIRGenFunction::AutoVarEmission::invalid()};
@ -442,17 +450,12 @@ class OpenACCClauseCIREmitter final
mlir::acc::YieldOp::create(builder, locEnd);
if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
if (!varRecipe->getInit()) {
// If we don't have any initialization recipe, we failed during Sema to
// initialize this correctly. If we disable the
// Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
// emit an error to tell us. However, emitting those errors during
// production is a violation of the standard, so we cannot do them.
cgf.cgm.errorNYI(
exprRange, "firstprivate copy-init recipe not properly generated");
}
cgf.cgm.errorNYI(exprRange, "firstprivate copy section generation");
// TODO: OpenACC: we should have a errorNYI call here if
// !varRecipe->getInit(), but as that generation isn't currently
// implemented, it ends up being too noisy. So when we implement copy-init
// generation both in Sema and here, we should have a diagnostic here.
createFirstprivateRecipeCopy(loc, locEnd, mainOp, tempDeclEmission,
recipe, varRecipe, temporary);
}
// Make sure we cleanup after ourselves here.
@ -1155,6 +1158,43 @@ public:
llvm_unreachable("Unknown construct kind in VisitPrivateClause");
}
}
void VisitFirstPrivateClause(const OpenACCFirstPrivateClause &clause) {
if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp,
mlir::acc::SerialOp>) {
for (const auto [varExpr, varRecipe] :
llvm::zip_equal(clause.getVarList(), clause.getInitRecipes())) {
CIRGenFunction::OpenACCDataOperandInfo opInfo =
cgf.getOpenACCDataOperandInfo(varExpr);
auto firstPrivateOp = mlir::acc::FirstprivateOp::create(
builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true,
/*implicit=*/false, opInfo.name, opInfo.bounds);
firstPrivateOp.setDataClause(mlir::acc::DataClause::acc_firstprivate);
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
auto recipe = getOrCreateRecipe<mlir::acc::FirstprivateRecipeOp>(
cgf.getContext(), varExpr, varRecipe.RecipeDecl,
varRecipe.InitFromTemporary,
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
firstPrivateOp.getResult());
// TODO: OpenACC: The dialect is going to change in the near future to
// have these be on a different operation, so when that changes, we
// probably need to change these here.
operation.addFirstPrivatization(builder.getContext(), firstPrivateOp,
recipe);
}
}
} else if constexpr (isCombinedType<OpTy>) {
// Unlike 'private', 'firstprivate' applies to the compute op, not the
// loop op.
applyToComputeOp(clause);
} else {
llvm_unreachable("Unknown construct kind in VisitFirstPrivateClause");
}
}
};
template <typename OpTy>

View File

@ -358,7 +358,7 @@ static Value *emitCallMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
static llvm::FixedVectorType *GetNeonType(CodeGenFunction *CGF,
NeonTypeFlags TypeFlags,
bool HasLegalHalfType = true,
bool HasFastHalfType = true,
bool V1Ty = false,
bool AllowBFloatArgsAndRet = true) {
int IsQuad = TypeFlags.isQuad();
@ -376,7 +376,7 @@ static llvm::FixedVectorType *GetNeonType(CodeGenFunction *CGF,
else
return llvm::FixedVectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
case NeonTypeFlags::Float16:
if (HasLegalHalfType)
if (HasFastHalfType)
return llvm::FixedVectorType::get(CGF->HalfTy, V1Ty ? 1 : (4 << IsQuad));
else
return llvm::FixedVectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
@ -1754,12 +1754,12 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
const bool Usgn = Type.isUnsigned();
const bool Quad = Type.isQuad();
const bool Floating = Type.isFloatingPoint();
const bool HasLegalHalfType = getTarget().hasLegalHalfType();
const bool HasFastHalfType = getTarget().hasFastHalfType();
const bool AllowBFloatArgsAndRet =
getTargetHooks().getABIInfo().allowBFloatArgsAndRet();
llvm::FixedVectorType *VTy =
GetNeonType(this, Type, HasLegalHalfType, false, AllowBFloatArgsAndRet);
GetNeonType(this, Type, HasFastHalfType, false, AllowBFloatArgsAndRet);
llvm::Type *Ty = VTy;
if (!Ty)
return nullptr;
@ -1886,7 +1886,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvtq_f32_v:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, Quad),
HasLegalHalfType);
HasFastHalfType);
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_f16_s16:
@ -1895,7 +1895,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvtq_f16_u16:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float16, false, Quad),
HasLegalHalfType);
HasFastHalfType);
return Usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
: Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
case NEON::BI__builtin_neon_vcvt_n_f16_s16:
@ -3211,7 +3211,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
bool rightShift = false;
llvm::FixedVectorType *VTy =
GetNeonType(this, Type, getTarget().hasLegalHalfType(), false,
GetNeonType(this, Type, getTarget().hasFastHalfType(), false,
getTarget().hasBFloat16Type());
llvm::Type *Ty = VTy;
if (!Ty)

View File

@ -316,7 +316,7 @@ ABIArgInfo ARMABIInfo::classifyHomogeneousAggregate(QualType Ty,
// Base can be a floating-point or a vector.
if (const VectorType *VT = Base->getAs<VectorType>()) {
// FP16 vectors should be converted to integer vectors
if (!getTarget().hasLegalHalfType() && containsAnyFP16Vectors(Ty)) {
if (!getTarget().hasFastHalfType() && containsAnyFP16Vectors(Ty)) {
uint64_t Size = getContext().getTypeSize(VT);
auto *NewVecTy = llvm::FixedVectorType::get(
llvm::Type::getInt32Ty(getVMContext()), Size / 32);
@ -582,7 +582,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic,
getDataLayout().getAllocaAddrSpace());
// TODO: FP16/BF16 vectors should be converted to integer vectors
// This check is similar to isIllegalVectorType - refactor?
if ((!getTarget().hasLegalHalfType() &&
if ((!getTarget().hasFastHalfType() &&
(VT->getElementType()->isFloat16Type() ||
VT->getElementType()->isHalfType())) ||
(IsFloatABISoftFP &&
@ -679,9 +679,9 @@ bool ARMABIInfo::isIllegalVectorType(QualType Ty) const {
// into float, and we don't want the ABI to depend on whether or not they
// are supported in hardware. Thus return false to coerce vectors of these
// types into integer vectors.
// We do not depend on hasLegalHalfType for bfloat as it is a
// We do not depend on hasFastHalfType for bfloat as it is a
// separate IR type.
if ((!getTarget().hasLegalHalfType() &&
if ((!getTarget().hasFastHalfType() &&
(VT->getElementType()->isFloat16Type() ||
VT->getElementType()->isHalfType())) ||
(IsFloatABISoftFP &&

View File

@ -629,9 +629,16 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
// name.
!Style.isJavaScript() && Previous.isNot(tok::kw_template) &&
CurrentState.BreakBeforeParameter) {
for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous)
if (Tok->FirstAfterPPLine || Tok->is(TT_LineComment))
for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous) {
if (Tok->is(TT_LineComment))
return false;
if (Tok->is(TT_TemplateCloser)) {
Tok = Tok->MatchingParen;
assert(Tok);
}
if (Tok->FirstAfterPPLine)
return false;
}
return true;
}

View File

@ -763,6 +763,15 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
}
};
template <>
struct ScalarEnumerationTraits<FormatStyle::SpaceInEmptyBracesStyle> {
static void enumeration(IO &IO, FormatStyle::SpaceInEmptyBracesStyle &Value) {
IO.enumCase(Value, "Always", FormatStyle::SIEB_Always);
IO.enumCase(Value, "Block", FormatStyle::SIEB_Block);
IO.enumCase(Value, "Never", FormatStyle::SIEB_Never);
}
};
template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
@ -931,6 +940,7 @@ template <> struct MappingTraits<FormatStyle> {
bool DeriveLineEnding = true;
bool UseCRLF = false;
bool SpaceInEmptyBlock = false;
bool SpaceInEmptyParentheses = false;
bool SpacesInConditionalStatement = false;
bool SpacesInCStyleCastParentheses = false;
@ -960,6 +970,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
IO.mapOptional("SpaceAfterControlStatementKeyword",
Style.SpaceBeforeParens);
IO.mapOptional("SpaceInEmptyBlock", SpaceInEmptyBlock);
IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses);
IO.mapOptional("SpacesInConditionalStatement",
SpacesInConditionalStatement);
@ -1193,7 +1204,7 @@ template <> struct MappingTraits<FormatStyle> {
Style.SpaceBeforeRangeBasedForLoopColon);
IO.mapOptional("SpaceBeforeSquareBrackets",
Style.SpaceBeforeSquareBrackets);
IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
IO.mapOptional("SpaceInEmptyBraces", Style.SpaceInEmptyBraces);
IO.mapOptional("SpacesBeforeTrailingComments",
Style.SpacesBeforeTrailingComments);
IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
@ -1276,6 +1287,13 @@ template <> struct MappingTraits<FormatStyle> {
Style.LineEnding = FormatStyle::LE_DeriveCRLF;
}
// If SpaceInEmptyBlock was specified but SpaceInEmptyBraces was not,
// initialize the latter from the former for backward compatibility.
if (SpaceInEmptyBlock &&
Style.SpaceInEmptyBraces == FormatStyle::SIEB_Never) {
Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block;
}
if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&
(SpacesInParentheses || SpaceInEmptyParentheses ||
SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
@ -1677,7 +1695,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
LLVMStyle.SpaceBeforeSquareBrackets = false;
LLVMStyle.SpaceInEmptyBlock = false;
LLVMStyle.SpaceInEmptyBraces = FormatStyle::SIEB_Never;
LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
LLVMStyle.SpacesInContainerLiterals = true;
@ -1984,7 +2002,7 @@ FormatStyle getWebKitStyle() {
Style.ObjCSpaceAfterProperty = true;
Style.PointerAlignment = FormatStyle::PAS_Left;
Style.SpaceBeforeCpp11BracedList = true;
Style.SpaceInEmptyBlock = true;
Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;
return Style;
}

View File

@ -2590,6 +2590,9 @@ private:
if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName))
return false;
if (Tok.endsSequence(Keywords.kw_final, TT_ClassHeadName))
return false;
if ((Style.isJavaScript() || Style.isJava()) && Tok.is(Keywords.kw_extends))
return false;
@ -4513,16 +4516,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return Left.is(tok::hash);
if (Left.isOneOf(tok::hashhash, tok::hash))
return Right.is(tok::hash);
if (Left.is(BK_Block) && Right.is(tok::r_brace) &&
Right.MatchingParen == &Left && Line.Children.empty()) {
return Style.SpaceInEmptyBlock;
}
if (Style.SpacesInParens == FormatStyle::SIPO_Custom) {
if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||
(Left.is(tok::l_brace) && Left.isNot(BK_Block) &&
Right.is(tok::r_brace) && Right.isNot(BK_Block))) {
if (Left.is(tok::l_paren) && Right.is(tok::r_paren))
return Style.SpacesInParensOptions.InEmptyParentheses;
}
if (Style.SpacesInParensOptions.ExceptDoubleParentheses &&
Left.is(tok::r_paren) && Right.is(tok::r_paren)) {
auto *InnerLParen = Left.MatchingParen;
@ -4800,8 +4796,6 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Right.is(TT_ArraySubscriptLSquare))) {
return false;
}
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
return !Left.Children.empty(); // No spaces in "{}".
if ((Left.is(tok::l_brace) && Left.isNot(BK_Block)) ||
(Right.is(tok::r_brace) && Right.MatchingParen &&
Right.MatchingParen->isNot(BK_Block))) {
@ -4983,6 +4977,17 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.is(tok::star) && Right.is(tok::comment))
return true;
if (Left.is(tok::l_brace) && Right.is(tok::r_brace) &&
Left.Children.empty()) {
if (Left.is(BK_Block))
return Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never;
if (Style.Cpp11BracedListStyle) {
return Style.SpacesInParens == FormatStyle::SIPO_Custom &&
Style.SpacesInParensOptions.InEmptyParentheses;
}
return Style.SpaceInEmptyBraces == FormatStyle::SIEB_Always;
}
const auto *BeforeLeft = Left.Previous;
if (IsCpp) {
@ -6269,7 +6274,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
}
if (Right.is(tok::colon) &&
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) {
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon,
TT_BitFieldColon)) {
return false;
}
if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {

View File

@ -864,7 +864,8 @@ private:
if (ShouldMerge()) {
// We merge empty blocks even if the line exceeds the column limit.
Tok->SpacesRequiredBefore =
(Style.SpaceInEmptyBlock || Line.Last->is(tok::comment)) ? 1 : 0;
Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never ||
Line.Last->is(tok::comment);
Tok->CanBreakBefore = true;
return 1;
} else if (Limit != 0 && !Line.startsWithNamespace() &&

View File

@ -1667,9 +1667,8 @@ _mm256_cvtepu32_epi64(__m128i __V) {
/// \param __b
/// A 256-bit vector of [8 x i32] containing one of the source operands.
/// \returns A 256-bit vector of [4 x i64] containing the products.
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mul_epi32(__m256i __a, __m256i __b)
{
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_mul_epi32(__m256i __a, __m256i __b) {
return (__m256i)__builtin_ia32_pmuldq256((__v8si)__a, (__v8si)__b);
}
@ -1796,9 +1795,8 @@ _mm256_mullo_epi32 (__m256i __a, __m256i __b)
/// \param __b
/// A 256-bit vector of [8 x i32] containing one of the source operands.
/// \returns A 256-bit vector of [4 x i64] containing the products.
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mul_epu32(__m256i __a, __m256i __b)
{
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_mul_epu32(__m256i __a, __m256i __b) {
return __builtin_ia32_pmuludq256((__v8si)__a, (__v8si)__b);
}

View File

@ -27,47 +27,35 @@
#endif
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm512_popcnt_epi16(__m512i __A)
{
_mm512_popcnt_epi16(__m512i __A) {
return (__m512i)__builtin_elementwise_popcount((__v32hu)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_popcnt_epi16(__m512i __A, __mmask32 __U, __m512i __B)
{
return (__m512i) __builtin_ia32_selectw_512((__mmask32) __U,
(__v32hi) _mm512_popcnt_epi16(__B),
(__v32hi) __A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_popcnt_epi16(__mmask32 __U, __m512i __B)
{
return _mm512_mask_popcnt_epi16((__m512i) _mm512_setzero_si512(),
__U,
__B);
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm512_mask_popcnt_epi16(__m512i __A, __mmask32 __U, __m512i __B) {
return (__m512i)__builtin_ia32_selectw_512(
(__mmask32)__U, (__v32hi)_mm512_popcnt_epi16(__B), (__v32hi)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm512_popcnt_epi8(__m512i __A)
{
_mm512_maskz_popcnt_epi16(__mmask32 __U, __m512i __B) {
return _mm512_mask_popcnt_epi16((__m512i)_mm512_setzero_si512(), __U, __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm512_popcnt_epi8(__m512i __A) {
return (__m512i)__builtin_elementwise_popcount((__v64qu)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_popcnt_epi8(__m512i __A, __mmask64 __U, __m512i __B)
{
return (__m512i) __builtin_ia32_selectb_512((__mmask64) __U,
(__v64qi) _mm512_popcnt_epi8(__B),
(__v64qi) __A);
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm512_mask_popcnt_epi8(__m512i __A, __mmask64 __U, __m512i __B) {
return (__m512i)__builtin_ia32_selectb_512(
(__mmask64)__U, (__v64qi)_mm512_popcnt_epi8(__B), (__v64qi)__A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_popcnt_epi8(__mmask64 __U, __m512i __B)
{
return _mm512_mask_popcnt_epi8((__m512i) _mm512_setzero_si512(),
__U,
__B);
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm512_maskz_popcnt_epi8(__mmask64 __U, __m512i __B) {
return _mm512_mask_popcnt_epi8((__m512i)_mm512_setzero_si512(), __U, __B);
}
static __inline__ __mmask64 __DEFAULT_FN_ATTRS

View File

@ -1413,9 +1413,8 @@ _mm512_maskz_min_epu64 (__mmask8 __M, __m512i __A, __m512i __B)
(__v8di)_mm512_setzero_si512());
}
static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mul_epi32(__m512i __X, __m512i __Y)
{
static __inline __m512i __DEFAULT_FN_ATTRS512_CONSTEXPR
_mm512_mul_epi32(__m512i __X, __m512i __Y) {
return (__m512i)__builtin_ia32_pmuldq512((__v16si)__X, (__v16si) __Y);
}
@ -1435,9 +1434,8 @@ _mm512_maskz_mul_epi32(__mmask8 __M, __m512i __X, __m512i __Y)
(__v8di)_mm512_setzero_si512 ());
}
static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_mul_epu32(__m512i __X, __m512i __Y)
{
static __inline __m512i __DEFAULT_FN_ATTRS512_CONSTEXPR
_mm512_mul_epu32(__m512i __X, __m512i __Y) {
return (__m512i)__builtin_ia32_pmuludq512((__v16si)__X, (__v16si)__Y);
}
@ -8935,36 +8933,28 @@ _mm512_mask_cvtpslo_pd (__m512d __W, __mmask8 __U, __m512 __A)
return (__m512d) _mm512_mask_cvtps_pd(__W, __U, _mm512_castps512_ps256(__A));
}
static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_mask_mov_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U,
(__v8df) __A,
(__v8df) __W);
static __inline__ __m512d __DEFAULT_FN_ATTRS512_CONSTEXPR
_mm512_mask_mov_pd(__m512d __W, __mmask8 __U, __m512d __A) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)__A,
(__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS512
_mm512_maskz_mov_pd (__mmask8 __U, __m512d __A)
{
return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U,
(__v8df) __A,
(__v8df) _mm512_setzero_pd ());
static __inline__ __m512d __DEFAULT_FN_ATTRS512_CONSTEXPR
_mm512_maskz_mov_pd(__mmask8 __U, __m512d __A) {
return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)__A,
(__v8df)_mm512_setzero_pd());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_mask_mov_ps (__m512 __W, __mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U,
(__v16sf) __A,
(__v16sf) __W);
static __inline__ __m512 __DEFAULT_FN_ATTRS512_CONSTEXPR
_mm512_mask_mov_ps(__m512 __W, __mmask16 __U, __m512 __A) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)__A,
(__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS512
_mm512_maskz_mov_ps (__mmask16 __U, __m512 __A)
{
return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U,
(__v16sf) __A,
(__v16sf) _mm512_setzero_ps ());
static __inline__ __m512 __DEFAULT_FN_ATTRS512_CONSTEXPR
_mm512_maskz_mov_ps(__mmask16 __U, __m512 __A) {
return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)__A,
(__v16sf)_mm512_setzero_ps());
}
static __inline__ void __DEFAULT_FN_ATTRS512

View File

@ -33,91 +33,67 @@
#endif
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_popcnt_epi16(__m256i __A)
{
_mm256_popcnt_epi16(__m256i __A) {
return (__m256i)__builtin_elementwise_popcount((__v16hu)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B)
{
return (__m256i) __builtin_ia32_selectw_256((__mmask16) __U,
(__v16hi) _mm256_popcnt_epi16(__B),
(__v16hi) __A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B)
{
return _mm256_mask_popcnt_epi16((__m256i) _mm256_setzero_si256(),
__U,
__B);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_popcnt_epi16(__m128i __A)
{
return (__m128i)__builtin_elementwise_popcount((__v8hu)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B)
{
return (__m128i) __builtin_ia32_selectw_128((__mmask8) __U,
(__v8hi) _mm_popcnt_epi16(__B),
(__v8hi) __A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B)
{
return _mm_mask_popcnt_epi16((__m128i) _mm_setzero_si128(),
__U,
__B);
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B) {
return (__m256i)__builtin_ia32_selectw_256(
(__mmask16)__U, (__v16hi)_mm256_popcnt_epi16(__B), (__v16hi)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_popcnt_epi8(__m256i __A)
{
return (__m256i)__builtin_elementwise_popcount((__v32qu)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B)
{
return (__m256i) __builtin_ia32_selectb_256((__mmask32) __U,
(__v32qi) _mm256_popcnt_epi8(__B),
(__v32qi) __A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B)
{
return _mm256_mask_popcnt_epi8((__m256i) _mm256_setzero_si256(),
__U,
__B);
_mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B) {
return _mm256_mask_popcnt_epi16((__m256i)_mm256_setzero_si256(), __U, __B);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_popcnt_epi8(__m128i __A)
{
_mm_popcnt_epi16(__m128i __A) {
return (__m128i)__builtin_elementwise_popcount((__v8hu)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B) {
return (__m128i)__builtin_ia32_selectw_128(
(__mmask8)__U, (__v8hi)_mm_popcnt_epi16(__B), (__v8hi)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B) {
return _mm_mask_popcnt_epi16((__m128i)_mm_setzero_si128(), __U, __B);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_popcnt_epi8(__m256i __A) {
return (__m256i)__builtin_elementwise_popcount((__v32qu)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B) {
return (__m256i)__builtin_ia32_selectb_256(
(__mmask32)__U, (__v32qi)_mm256_popcnt_epi8(__B), (__v32qi)__A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B) {
return _mm256_mask_popcnt_epi8((__m256i)_mm256_setzero_si256(), __U, __B);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_popcnt_epi8(__m128i __A) {
return (__m128i)__builtin_elementwise_popcount((__v16qu)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B)
{
return (__m128i) __builtin_ia32_selectb_128((__mmask16) __U,
(__v16qi) _mm_popcnt_epi8(__B),
(__v16qi) __A);
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B) {
return (__m128i)__builtin_ia32_selectb_128(
(__mmask16)__U, (__v16qi)_mm_popcnt_epi8(__B), (__v16qi)__A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128
_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B)
{
return _mm_mask_popcnt_epi8((__m128i) _mm_setzero_si128(),
__U,
__B);
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B) {
return _mm_mask_popcnt_epi8((__m128i)_mm_setzero_si128(), __U, __B);
}
static __inline__ __mmask32 __DEFAULT_FN_ATTRS256

View File

@ -8264,68 +8264,52 @@ _mm256_maskz_moveldup_ps (__mmask8 __U, __m256 __A)
(__v4si)_mm_shuffle_epi32((A), (I)), \
(__v4si)_mm_setzero_si128()))
static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_mask_mov_pd (__m128d __W, __mmask8 __U, __m128d __A)
{
return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U,
(__v2df) __A,
(__v2df) __W);
static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_mask_mov_pd(__m128d __W, __mmask8 __U, __m128d __A) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)__A,
(__v2df)__W);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS128
_mm_maskz_mov_pd (__mmask8 __U, __m128d __A)
{
return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U,
(__v2df) __A,
(__v2df) _mm_setzero_pd ());
static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_maskz_mov_pd(__mmask8 __U, __m128d __A) {
return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)__A,
(__v2df)_mm_setzero_pd());
}
static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_mask_mov_pd (__m256d __W, __mmask8 __U, __m256d __A)
{
return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U,
(__v4df) __A,
(__v4df) __W);
static __inline__ __m256d __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_mask_mov_pd(__m256d __W, __mmask8 __U, __m256d __A) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)__A,
(__v4df)__W);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS256
_mm256_maskz_mov_pd (__mmask8 __U, __m256d __A)
{
return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U,
(__v4df) __A,
(__v4df) _mm256_setzero_pd ());
static __inline__ __m256d __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_maskz_mov_pd(__mmask8 __U, __m256d __A) {
return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)__A,
(__v4df)_mm256_setzero_pd());
}
static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_mask_mov_ps (__m128 __W, __mmask8 __U, __m128 __A)
{
return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U,
(__v4sf) __A,
(__v4sf) __W);
static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_mask_mov_ps(__m128 __W, __mmask8 __U, __m128 __A) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)__A,
(__v4sf)__W);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS128
_mm_maskz_mov_ps (__mmask8 __U, __m128 __A)
{
return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U,
(__v4sf) __A,
(__v4sf) _mm_setzero_ps ());
static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_maskz_mov_ps(__mmask8 __U, __m128 __A) {
return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)__A,
(__v4sf)_mm_setzero_ps());
}
static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_mask_mov_ps (__m256 __W, __mmask8 __U, __m256 __A)
{
return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U,
(__v8sf) __A,
(__v8sf) __W);
static __inline__ __m256 __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_mask_mov_ps(__m256 __W, __mmask8 __U, __m256 __A) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)__A,
(__v8sf)__W);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS256
_mm256_maskz_mov_ps (__mmask8 __U, __m256 __A)
{
return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U,
(__v8sf) __A,
(__v8sf) _mm256_setzero_ps ());
static __inline__ __m256 __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_maskz_mov_ps(__mmask8 __U, __m256 __A) {
return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)__A,
(__v8sf)_mm256_setzero_ps());
}
static __inline__ __m128 __DEFAULT_FN_ATTRS128
@ -8388,7 +8372,6 @@ _mm256_maskz_cvtph_ps (__mmask8 __U, __m128i __A)
#define _mm256_mask_cvtps_ph _mm256_mask_cvt_roundps_ph
#define _mm256_maskz_cvtps_ph _mm256_maskz_cvt_roundps_ph
#undef __DEFAULT_FN_ATTRS128
#undef __DEFAULT_FN_ATTRS256
#undef __DEFAULT_FN_ATTRS256_CONSTEXPR

View File

@ -16,19 +16,19 @@
#define __AVX512VPOPCNTDQINTRIN_H
/* Define the default attributes for the functions in this file. */
#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, \
__target__("avx512vpopcntdq,evex512"), \
__min_vector_width__(512))) constexpr
#else
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, \
__target__("avx512vpopcntdq,evex512"), \
__min_vector_width__(512)))
#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
#else
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
#endif
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm512_popcnt_epi64(__m512i __A) {
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_popcnt_epi64(__m512i __A) {
return (__m512i)__builtin_elementwise_popcount((__v8du)__A);
}
@ -43,8 +43,7 @@ _mm512_maskz_popcnt_epi64(__mmask8 __U, __m512i __A) {
return _mm512_mask_popcnt_epi64((__m512i)_mm512_setzero_si512(), __U, __A);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm512_popcnt_epi32(__m512i __A) {
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_popcnt_epi32(__m512i __A) {
return (__m512i)__builtin_elementwise_popcount((__v16su)__A);
}
@ -60,6 +59,5 @@ _mm512_maskz_popcnt_epi32(__mmask16 __U, __m512i __A) {
}
#undef __DEFAULT_FN_ATTRS
#undef __DEFAULT_FN_ATTRS_CONSTEXPR
#endif

View File

@ -16,6 +16,17 @@
#define __AVX512VPOPCNTDQVLINTRIN_H
/* Define the default attributes for the functions in this file. */
#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS128 \
__attribute__((__always_inline__, __nodebug__, \
__target__("avx512vpopcntdq,avx512vl,no-evex512"), \
__min_vector_width__(128))) constexpr
#define __DEFAULT_FN_ATTRS256 \
__attribute__((__always_inline__, __nodebug__, \
__target__("avx512vpopcntdq,avx512vl,no-evex512"), \
__min_vector_width__(256))) constexpr
#else
#define __DEFAULT_FN_ATTRS128 \
__attribute__((__always_inline__, __nodebug__, \
__target__("avx512vpopcntdq,avx512vl,no-evex512"), \
@ -24,17 +35,9 @@
__attribute__((__always_inline__, __nodebug__, \
__target__("avx512vpopcntdq,avx512vl,no-evex512"), \
__min_vector_width__(256)))
#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS128_CONSTEXPR __DEFAULT_FN_ATTRS128 constexpr
#define __DEFAULT_FN_ATTRS256_CONSTEXPR __DEFAULT_FN_ATTRS256 constexpr
#else
#define __DEFAULT_FN_ATTRS128_CONSTEXPR __DEFAULT_FN_ATTRS128
#define __DEFAULT_FN_ATTRS256_CONSTEXPR __DEFAULT_FN_ATTRS256
#endif
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_popcnt_epi64(__m128i __A) {
static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_popcnt_epi64(__m128i __A) {
return (__m128i)__builtin_elementwise_popcount((__v2du)__A);
}
@ -49,8 +52,7 @@ _mm_maskz_popcnt_epi64(__mmask8 __U, __m128i __A) {
return _mm_mask_popcnt_epi64((__m128i)_mm_setzero_si128(), __U, __A);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_popcnt_epi32(__m128i __A) {
static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_popcnt_epi32(__m128i __A) {
return (__m128i)__builtin_elementwise_popcount((__v4su)__A);
}
@ -65,7 +67,7 @@ _mm_maskz_popcnt_epi32(__mmask8 __U, __m128i __A) {
return _mm_mask_popcnt_epi32((__m128i)_mm_setzero_si128(), __U, __A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_popcnt_epi64(__m256i __A) {
return (__m256i)__builtin_elementwise_popcount((__v4du)__A);
}
@ -81,7 +83,7 @@ _mm256_maskz_popcnt_epi64(__mmask8 __U, __m256i __A) {
return _mm256_mask_popcnt_epi64((__m256i)_mm256_setzero_si256(), __U, __A);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
static __inline__ __m256i __DEFAULT_FN_ATTRS256
_mm256_popcnt_epi32(__m256i __A) {
return (__m256i)__builtin_elementwise_popcount((__v8su)__A);
}
@ -99,7 +101,5 @@ _mm256_maskz_popcnt_epi32(__mmask8 __U, __m256i __A) {
#undef __DEFAULT_FN_ATTRS128
#undef __DEFAULT_FN_ATTRS256
#undef __DEFAULT_FN_ATTRS128_CONSTEXPR
#undef __DEFAULT_FN_ATTRS256_CONSTEXPR
#endif

View File

@ -62,6 +62,9 @@ typedef __bf16 __m128bh __attribute__((__vector_size__(16), __aligned__(16)));
#define __trunc64(x) \
(__m64) __builtin_shufflevector((__v2di)(x), __extension__(__v2di){}, 0)
#define __zext128(x) \
(__m128i) __builtin_shufflevector((__v2si)(x), __extension__(__v2si){}, 0, \
1, 2, 3)
#define __anyext128(x) \
(__m128i) __builtin_shufflevector((__v2si)(x), __extension__(__v2si){}, 0, \
1, -1, -1)
@ -2445,9 +2448,10 @@ _mm_mullo_epi16(__m128i __a, __m128i __b) {
/// \param __b
/// A 64-bit integer containing one of the source operands.
/// \returns A 64-bit integer vector containing the product of both operands.
static __inline__ __m64 __DEFAULT_FN_ATTRS _mm_mul_su32(__m64 __a, __m64 __b) {
return __trunc64(__builtin_ia32_pmuludq128((__v4si)__anyext128(__a),
(__v4si)__anyext128(__b)));
static __inline__ __m64 __DEFAULT_FN_ATTRS_CONSTEXPR _mm_mul_su32(__m64 __a,
__m64 __b) {
return __trunc64(__builtin_ia32_pmuludq128((__v4si)__zext128(__a),
(__v4si)__zext128(__b)));
}
/// Multiplies 32-bit unsigned integer values contained in the lower
@ -2463,8 +2467,8 @@ static __inline__ __m64 __DEFAULT_FN_ATTRS _mm_mul_su32(__m64 __a, __m64 __b) {
/// \param __b
/// A [2 x i64] vector containing one of the source operands.
/// \returns A [2 x i64] vector containing the product of both operands.
static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_mul_epu32(__m128i __a,
__m128i __b) {
static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_mul_epu32(__m128i __a, __m128i __b) {
return __builtin_ia32_pmuludq128((__v4si)__a, (__v4si)__b);
}

View File

@ -567,8 +567,8 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_mullo_epi32(__m128i __V1,
/// A 128-bit vector of [4 x i32].
/// \returns A 128-bit vector of [2 x i64] containing the products of both
/// operands.
static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_mul_epi32(__m128i __V1,
__m128i __V2) {
static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_mul_epi32(__m128i __V1, __m128i __V2) {
return (__m128i)__builtin_ia32_pmuldq128((__v4si)__V1, (__v4si)__V2);
}

View File

@ -174,8 +174,6 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
ExtendedTokenMode = 0;
NewLinePtr = nullptr;
IsFirstPPToken = true;
}
/// Lexer constructor - Create a new lexer object for the specified buffer
@ -3225,7 +3223,6 @@ std::optional<Token> Lexer::peekNextPPToken() {
bool atStartOfLine = IsAtStartOfLine;
bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
bool leadingSpace = HasLeadingSpace;
bool isFirstPPToken = IsFirstPPToken;
Token Tok;
Lex(Tok);
@ -3236,7 +3233,6 @@ std::optional<Token> Lexer::peekNextPPToken() {
HasLeadingSpace = leadingSpace;
IsAtStartOfLine = atStartOfLine;
IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
IsFirstPPToken = isFirstPPToken;
// Restore the lexer back to non-skipping mode.
LexingRawMode = false;
@ -3726,11 +3722,6 @@ bool Lexer::Lex(Token &Result) {
HasLeadingEmptyMacro = false;
}
if (IsFirstPPToken) {
Result.setFlag(Token::FirstPPToken);
IsFirstPPToken = false;
}
bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
IsAtPhysicalStartOfLine = false;
bool isRawLex = isLexingRawMode();

View File

@ -43,6 +43,7 @@
#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/NoTrivialPPDirectiveTracer.h"
#include "clang/Lex/Pragma.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/PreprocessorLexer.h"
@ -247,8 +248,6 @@ void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
llvm::errs() << " [LeadingSpace]";
if (Tok.isExpandDisabled())
llvm::errs() << " [ExpandDisabled]";
if (Tok.isFirstPPToken())
llvm::errs() << " [First pp-token]";
if (Tok.needsCleaning()) {
const char *Start = SourceMgr.getCharacterData(Tok.getLocation());
llvm::errs() << " [UnClean='" << StringRef(Start, Tok.getLength())
@ -577,8 +576,11 @@ void Preprocessor::EnterMainSourceFile() {
// export module M; // error: module declaration must occur
// // at the start of the translation unit.
if (getLangOpts().CPlusPlusModules) {
auto Tracer = std::make_unique<NoTrivialPPDirectiveTracer>(*this);
DirTracer = Tracer.get();
addPPCallbacks(std::move(Tracer));
std::optional<Token> FirstPPTok = CurLexer->peekNextPPToken();
if (FirstPPTok && FirstPPTok->isFirstPPToken())
if (FirstPPTok)
FirstPPTokenLoc = FirstPPTok->getLocation();
}
}
@ -940,6 +942,8 @@ void Preprocessor::Lex(Token &Result) {
StdCXXImportSeqState.handleHeaderName();
break;
case tok::kw_export:
if (hasSeenNoTrivialPPDirective())
Result.setFlag(Token::HasSeenNoTrivialPPDirective);
TrackGMFState.handleExport();
StdCXXImportSeqState.handleExport();
ModuleDeclState.handleExport();
@ -968,6 +972,8 @@ void Preprocessor::Lex(Token &Result) {
}
break;
} else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) {
if (hasSeenNoTrivialPPDirective())
Result.setFlag(Token::HasSeenNoTrivialPPDirective);
TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq());
ModuleDeclState.handleModule();
break;
@ -1682,3 +1688,31 @@ const char *Preprocessor::getCheckPoint(FileID FID, const char *Start) const {
return nullptr;
}
bool Preprocessor::hasSeenNoTrivialPPDirective() const {
return DirTracer && DirTracer->hasSeenNoTrivialPPDirective();
}
bool NoTrivialPPDirectiveTracer::hasSeenNoTrivialPPDirective() const {
return SeenNoTrivialPPDirective;
}
void NoTrivialPPDirectiveTracer::setSeenNoTrivialPPDirective() {
if (InMainFile && !SeenNoTrivialPPDirective)
SeenNoTrivialPPDirective = true;
}
void NoTrivialPPDirectiveTracer::LexedFileChanged(
FileID FID, LexedFileChangeReason Reason,
SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc) {
InMainFile = (FID == PP.getSourceManager().getMainFileID());
}
void NoTrivialPPDirectiveTracer::MacroExpands(const Token &MacroNameTok,
const MacroDefinition &MD,
SourceRange Range,
const MacroArgs *Args) {
// FIXME: Does only enable builtin macro expansion make sense?
if (!MD.getMacroInfo()->isBuiltinMacro())
setSeenNoTrivialPPDirective();
}

View File

@ -2363,9 +2363,10 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
// Parse a global-module-fragment, if present.
if (getLangOpts().CPlusPlusModules && Tok.is(tok::semi)) {
SourceLocation SemiLoc = ConsumeToken();
if (!Introducer.isFirstPPToken()) {
if (ImportState != Sema::ModuleImportState::FirstDecl ||
Introducer.hasSeenNoTrivialPPDirective()) {
Diag(StartLoc, diag::err_global_module_introducer_not_at_start)
<< SourceRange(StartLoc, SemiLoc);
<< SourceRange(StartLoc, SemiLoc);
return nullptr;
}
if (MDK == Sema::ModuleDeclKind::Interface) {
@ -2420,7 +2421,8 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
ExpectAndConsumeSemi(diag::err_module_expected_semi);
return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path, Partition,
ImportState, Introducer.isFirstPPToken());
ImportState,
Introducer.hasSeenNoTrivialPPDirective());
}
Decl *Parser::ParseModuleImport(SourceLocation AtLoc,

View File

@ -2780,6 +2780,31 @@ public:
}
};
namespace clang::lifetimes {
namespace {
class LifetimeSafetyReporterImpl : public LifetimeSafetyReporter {
public:
LifetimeSafetyReporterImpl(Sema &S) : S(S) {}
void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
SourceLocation FreeLoc, Confidence C) override {
S.Diag(IssueExpr->getExprLoc(),
C == Confidence::Definite
? diag::warn_lifetime_safety_loan_expires_permissive
: diag::warn_lifetime_safety_loan_expires_strict)
<< IssueExpr->getEndLoc();
S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here);
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getEndLoc();
}
private:
Sema &S;
};
} // namespace
} // namespace clang::lifetimes
void clang::sema::AnalysisBasedWarnings::IssueWarnings(
TranslationUnitDecl *TU) {
if (!TU)
@ -3029,8 +3054,10 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
// TODO: Enable lifetime safety analysis for other languages once it is
// stable.
if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
if (AC.getCFG())
lifetimes::runLifetimeSafetyAnalysis(AC);
if (AC.getCFG()) {
lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter);
}
}
// Check for violations of "called once" parameter properties.
if (S.getLangOpts().ObjC && !S.getLangOpts().CPlusPlus &&

View File

@ -265,10 +265,11 @@ Sema::DeclGroupPtrTy
Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
ModuleDeclKind MDK, ModuleIdPath Path,
ModuleIdPath Partition, ModuleImportState &ImportState,
bool IntroducerIsFirstPPToken) {
bool SeenNoTrivialPPDirective) {
assert(getLangOpts().CPlusPlusModules &&
"should only have module decl in standard C++ modules");
bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl;
bool SeenGMF = ImportState == ModuleImportState::GlobalFragment;
// If any of the steps here fail, we count that as invalidating C++20
// module state;
@ -336,7 +337,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
// In C++20, A module directive may only appear as the first preprocessing
// tokens in a file (excluding the global module fragment.).
if (getLangOpts().CPlusPlusModules && !IntroducerIsFirstPPToken && !SeenGMF) {
if (getLangOpts().CPlusPlusModules &&
(!IsFirstDecl || SeenNoTrivialPPDirective) && !SeenGMF) {
Diag(ModuleLoc, diag::err_module_decl_not_at_start);
SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc();
Diag(BeginLoc, diag::note_global_module_introducer_missing)

View File

@ -5669,7 +5669,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
};
Function->setDeclarationNameLoc(NameLocPointsToPattern());
EnterExpressionEvaluationContext EvalContext(
EnterExpressionEvaluationContextForFunction EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
Qualifiers ThisTypeQuals;

View File

@ -21,6 +21,27 @@
#error "huh?"
#endif
inline constexpr void* operator new(__SIZE_TYPE__, void* p) noexcept { return p; }
namespace std {
using size_t = decltype(sizeof(0));
template<typename T> struct allocator {
constexpr T *allocate(size_t N) {
return (T*)__builtin_operator_new(sizeof(T) * N); // #alloc
}
constexpr void deallocate(void *p, __SIZE_TYPE__) {
__builtin_operator_delete(p);
}
};
template<typename T, typename... Args>
constexpr T* construct_at(T* p, Args&&... args) { return ::new((void*)p) T(static_cast<Args&&>(args)...); }
template<typename T>
constexpr void destroy_at(T* p) {
p->~T();
}
}
extern "C" {
typedef decltype(sizeof(int)) size_t;
extern size_t wcslen(const wchar_t *p);
@ -1767,6 +1788,28 @@ namespace WithinLifetime {
}
} xstd; // both-error {{is not a constant expression}} \
// both-note {{in call to}}
consteval bool test_dynamic(bool read_after_deallocate) {
std::allocator<int> a;
int* p = a.allocate(1);
// a.allocate starts the lifetime of an array,
// the complete object of *p has started its lifetime
if (__builtin_is_within_lifetime(p))
return false;
std::construct_at(p);
if (!__builtin_is_within_lifetime(p))
return false;
std::destroy_at(p);
if (__builtin_is_within_lifetime(p))
return false;
a.deallocate(p, 1);
if (read_after_deallocate)
__builtin_is_within_lifetime(p); // both-note {{read of heap allocated object that has been deleted}}
return true;
}
static_assert(test_dynamic(false));
static_assert(test_dynamic(true)); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}
}
#ifdef __SIZEOF_INT128__

View File

@ -0,0 +1,87 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
void foo() {
struct A { char buf[16]; };
struct B : A {};
struct C { int i; B bs[1]; } *c;
int gi;
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
gi = __builtin_object_size(&c->bs[0], 0);
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
gi = __builtin_object_size(&c->bs[0], 1);
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
gi = __builtin_object_size(&c->bs[0], 2);
// CHECK: store i32 16
gi = __builtin_object_size(&c->bs[0], 3);
}
void foo2() {
struct A { int a; };
struct B { int b; };
struct C: public A, public B {};
C c;
int gi;
// CHECK: store i32 8
gi = __builtin_object_size(&c, 0);
// CHECK: store i32 8
gi = __builtin_object_size((A*)&c, 0);
// CHECK: store i32 4
gi = __builtin_object_size((B*)&c, 0);
// CHECK: store i32 8
gi = __builtin_object_size((char*)&c, 0);
// CHECK: store i32 8
gi = __builtin_object_size((char*)(A*)&c, 0);
// CHECK: store i32 4
gi = __builtin_object_size((char*)(B*)&c, 0);
}
typedef struct {
double c[0];
float f;
} foofoo0_t;
unsigned babar0(foofoo0_t *f) {
// CHECK: ret i32 0
return __builtin_object_size(f->c, 1);
}
void test2() {
struct A { char buf[16]; };
struct B : A {};
struct C { int i; B bs[1]; } *c;
int gi;
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
gi = __builtin_object_size(&c->bs[0], 0);
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
gi = __builtin_object_size(&c->bs[0], 1);
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
gi = __builtin_object_size(&c->bs[0], 2);
// CHECK: store i32 16
gi = __builtin_object_size(&c->bs[0], 3);
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
gi = __builtin_object_size((A*)&c->bs[0], 0);
// CHECK: store i32 16
gi = __builtin_object_size((A*)&c->bs[0], 1);
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
gi = __builtin_object_size(&c->bs[0].buf[0], 2);
// CHECK: store i32 16
gi = __builtin_object_size(&c->bs[0].buf[0], 3);
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
gi = __builtin_object_size(&c->bs[0].buf[0], 0);
// CHECK: store i32 16
gi = __builtin_object_size(&c->bs[0].buf[0], 1);
// CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
gi = __builtin_object_size(&c->bs[0].buf[0], 2);
// CHECK: store i32 16
gi = __builtin_object_size(&c->bs[0].buf[0], 3);
}

View File

@ -132,8 +132,50 @@ void Test_TemplatedFunctionVariadic(int arg, ...);
// CHECK-NEXT: ParagraphComment
// CHECK-NEXT: TextComment{{.*}} Text=" More arguments"
/// \param[out] Aaa <summary>Short summary</summary>
int Test_HTMLSummaryTag(int Aaa);
// CHECK: FunctionDecl{{.*}}Test_HTMLSummaryTag
// CHECK: ParamCommandComment{{.*}} [out] explicitly Param="Aaa"
// CHECK-NEXT: ParagraphComment
// CHECK: HTMLStartTagComment{{.*}} Name="summary"
// CHECK-NEXT: TextComment{{.*}} Text="Short summary"
// CHECK-NEXT: HTMLEndTagComment{{.*}} Name="summary"
/// \thread_safe test for underscore in special command
int Test_UnderscoreInSpecialCommand;
// CHECK: VarDecl{{.*}}Test_UnderscoreInSpecialCommand 'int'
// CHECK: InlineCommandComment{{.*}} Name="thread_safe" RenderNormal
// CHECK-NEXT: TextComment{{.*}} Text=" test for underscore in special command"
/// <details>
/// <summary>
/// Summary
/// </summary>
/// <p>Details</p>
/// </details>
///
/// Some <mark>highlighting</mark>
///
/// <figure>
/// <img src="pic.jpg">
/// <figcaption>Figure 1</figcaption>
/// </figure>
int Test_AdditionalHTMLTags(int Aaa);
// CHECK: FunctionDecl{{.*}}Test_AdditionalHTMLTags 'int (int)'
// CHECK: HTMLStartTagComment{{.*}} Name="details"
// CHECK: HTMLStartTagComment{{.*}} Name="summary"
// CHECK-NEXT: TextComment{{.*}} Text=" Summary"
// CHECK: HTMLEndTagComment{{.*}} Name="summary"
// CHECK: HTMLStartTagComment{{.*}} Name="p"
// CHECK-NEXT: TextComment{{.*}} Text="Details"
// CHECK-NEXT: HTMLEndTagComment{{.*}} Name="p"
// CHECK: HTMLEndTagComment{{.*}} Name="details"
// CHECK: HTMLStartTagComment{{.*}} Name="mark"
// CHECK-NEXT: TextComment{{.*}} Text="highlighting"
// CHECK-NEXT: HTMLEndTagComment{{.*}} Name="mark"
// CHECK: HTMLStartTagComment{{.*}} Name="figure"
// CHECK: HTMLStartTagComment{{.*}} Name="img" Attrs: "src="pic.jpg"
// CHECK: HTMLStartTagComment{{.*}} Name="figcaption"
// CHECK-NEXT: TextComment{{.*}} Text="Figure 1"
// CHECK-NEXT: HTMLEndTagComment{{.*}} Name="figcaption"
// CHECK: HTMLEndTagComment{{.*}} Name="figure"

View File

@ -0,0 +1,571 @@
// RUN: %clang_cc1 -fopenacc -triple x86_64-linux-gnu -Wno-openacc-self-if-potential-conflict -emit-cir -fclangir -triple x86_64-linux-pc %s -o - | FileCheck %s
struct NoCopyConstruct {};
struct CopyConstruct {
CopyConstruct() = default;
CopyConstruct(const CopyConstruct&);
};
struct NonDefaultCtor {
NonDefaultCtor();
};
struct HasDtor {
~HasDtor();
};
// CHECK: acc.firstprivate.recipe @firstprivatization__ZTSA5_7HasDtor : !cir.ptr<!cir.array<!rec_HasDtor x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!rec_HasDtor x 5>, !cir.ptr<!cir.array<!rec_HasDtor x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
//
// CHECK-NEXT: } destroy {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
// CHECK-NEXT: %[[LAST_IDX:.*]] = cir.const #cir.int<4> : !u64i
// CHECK-NEXT: %[[ARRPTR:.*]] = cir.cast(array_to_ptrdecay, %[[ARG]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>), !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: %[[ELEM:.*]] = cir.ptr_stride(%[[ARRPTR]] : !cir.ptr<!rec_HasDtor>, %[[LAST_IDX]] : !u64i), !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: %[[ITR:.*]] = cir.alloca !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>, ["__array_idx"]
// CHECK-NEXT: cir.store %[[ELEM]], %[[ITR]] : !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>
// CHECK-NEXT: cir.do {
// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ELEM_LOAD]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
// CHECK-NEXT: %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
// CHECK-NEXT: %[[PREVELEM:.*]] = cir.ptr_stride(%[[ELEM_LOAD]] : !cir.ptr<!rec_HasDtor>, %[[NEG_ONE]] : !s64i), !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: cir.store %[[PREVELEM]], %[[ITR]] : !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>
// CHECK-NEXT: cir.yield
// CHECK-NEXT: } while {
// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: %[[CMP:.*]] = cir.cmp(ne, %[[ELEM_LOAD]], %[[ARRPTR]]) : !cir.ptr<!rec_HasDtor>, !cir.bool
// CHECK-NEXT: cir.condition(%[[CMP]])
// CHECK-NEXT: }
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_14NonDefaultCtor : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_13CopyConstruct : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!rec_CopyConstruct x 5>, !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_15NoCopyConstruct : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!rec_NoCopyConstruct x 5>, !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_f : !cir.ptr<!cir.array<!cir.float x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!cir.float x 5>, !cir.ptr<!cir.array<!cir.float x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_i : !cir.ptr<!cir.array<!s32i x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!s32i x 5>, !cir.ptr<!cir.array<!s32i x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS7HasDtor : !cir.ptr<!rec_HasDtor> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
// CHECK-NEXT: cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } destroy {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ARG]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS14NonDefaultCtor : !cir.ptr<!rec_NonDefaultCtor> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS13CopyConstruct : !cir.ptr<!rec_CopyConstruct> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
// CHECK-NEXT: cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS15NoCopyConstruct : !cir.ptr<!rec_NoCopyConstruct> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}):
// CHECK-NEXT: cir.alloca !rec_NoCopyConstruct, !cir.ptr<!rec_NoCopyConstruct>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSf : !cir.ptr<!cir.float> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.float> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.float, !cir.ptr<!cir.float>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!cir.float> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.float> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSi : !cir.ptr<!s32i> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!s32i> {{.*}}):
// CHECK-NEXT: cir.alloca !s32i, !cir.ptr<!s32i>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!s32i> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!s32i> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
extern "C" void acc_combined() {
// CHECK: cir.func{{.*}} @acc_combined() {
int someInt;
// CHECK-NEXT: %[[SOMEINT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["someInt"]
float someFloat;
// CHECK-NEXT: %[[SOMEFLOAT:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["someFloat"]
NoCopyConstruct noCopy;
// CHECK-NEXT: %[[NOCOPY:.*]] = cir.alloca !rec_NoCopyConstruct, !cir.ptr<!rec_NoCopyConstruct>, ["noCopy"]
CopyConstruct hasCopy;
// CHECK-NEXT: %[[HASCOPY:.*]] = cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["hasCopy"]
NonDefaultCtor notDefCtor;
// CHECK-NEXT: %[[NOTDEFCTOR:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["notDefCtor", init]
HasDtor dtor;
// CHECK-NEXT: %[[DTOR:.*]] = cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["dtor"]
int someIntArr[5];
// CHECK-NEXT: %[[INTARR:.*]] = cir.alloca !cir.array<!s32i x 5>, !cir.ptr<!cir.array<!s32i x 5>>, ["someIntArr"]
float someFloatArr[5];
// CHECK-NEXT: %[[FLOATARR:.*]] = cir.alloca !cir.array<!cir.float x 5>, !cir.ptr<!cir.array<!cir.float x 5>>, ["someFloatArr"]
NoCopyConstruct noCopyArr[5];
// CHECK-NEXT: %[[NOCOPYARR:.*]] = cir.alloca !cir.array<!rec_NoCopyConstruct x 5>, !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>, ["noCopyArr"]
CopyConstruct hasCopyArr[5];
// CHECK-NEXT: %[[HASCOPYARR:.*]] = cir.alloca !cir.array<!rec_CopyConstruct x 5>, !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>, ["hasCopyArr"]
NonDefaultCtor notDefCtorArr[5];
// CHECK-NEXT: %[[NOTDEFCTORARR:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["notDefCtorArr", init]
HasDtor dtorArr[5];
// CHECK-NEXT: %[[DTORARR:.*]] = cir.alloca !cir.array<!rec_HasDtor x 5>, !cir.ptr<!cir.array<!rec_HasDtor x 5>>, ["dtorArr"]
// CHECK-NEXT: cir.call @_ZN14NonDefaultCtorC1Ev(%[[NOTDEFCTOR]]) : (!cir.ptr<!rec_NonDefaultCtor>) -> ()
#pragma acc parallel loop firstprivate(someInt)
for(int i = 0; i < 5; ++i);
// CHECK: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[SOMEINT]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSi -> %[[PRIVATE]] : !cir.ptr<!s32i>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial loop firstprivate(someFloat)
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[SOMEFLOAT]] : !cir.ptr<!cir.float>) -> !cir.ptr<!cir.float> {name = "someFloat"}
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSf -> %[[PRIVATE]] : !cir.ptr<!cir.float>) {
// CHECK-NEXT: acc.loop combined(serial)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(noCopy)
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPY]] : !cir.ptr<!rec_NoCopyConstruct>) -> !cir.ptr<!rec_NoCopyConstruct> {name = "noCopy"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTS15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!rec_NoCopyConstruct>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial loop firstprivate(hasCopy)
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPY]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "hasCopy"}
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!rec_CopyConstruct>) {
// CHECK-NEXT: acc.loop combined(serial)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial loop firstprivate(notDefCtor)
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTOR]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "notDefCtor"}
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!rec_NonDefaultCtor>) {
// CHECK-NEXT: acc.loop combined(serial)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial loop firstprivate(dtor)
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTOR]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTS7HasDtor -> %[[PRIVATE]] : !cir.ptr<!rec_HasDtor>) {
// CHECK-NEXT: acc.loop combined(serial)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(someInt, someFloat, noCopy, hasCopy, notDefCtor, dtor)
for(int i = 0; i < 5; ++i);
// CHECK: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[SOMEINT]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[SOMEFLOAT]] : !cir.ptr<!cir.float>) -> !cir.ptr<!cir.float> {name = "someFloat"}
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPY]] : !cir.ptr<!rec_NoCopyConstruct>) -> !cir.ptr<!rec_NoCopyConstruct> {name = "noCopy"}
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPY]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "hasCopy"}
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTOR]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "notDefCtor"}
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTOR]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
// CHECK: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSi -> %[[PRIVATE1]] : !cir.ptr<!s32i>,
// CHECK-SAME: @firstprivatization__ZTSf -> %[[PRIVATE2]] : !cir.ptr<!cir.float>,
// CHECK-SAME: @firstprivatization__ZTS15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!rec_NoCopyConstruct>,
// CHECK-SAME: @firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!rec_CopyConstruct>,
// CHECK-SAME: @firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!rec_NonDefaultCtor>,
// CHECK-SAME: @firstprivatization__ZTS7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!rec_HasDtor>)
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial loop firstprivate(someIntArr[1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1]"}
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE]] : !cir.ptr<!cir.array<!s32i x 5>>) {
// CHECK-NEXT: acc.loop combined(serial)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(someFloatArr[1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1]"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_f -> %[[PRIVATE]] : !cir.ptr<!cir.array<!cir.float x 5>>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial loop firstprivate(noCopyArr[1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1]"}
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) {
// CHECK-NEXT: acc.loop combined(serial)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(hasCopyArr[1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1]"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(notDefCtorArr[1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1]"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(dtorArr[1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1]"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial loop firstprivate(someIntArr[1], someFloatArr[1], noCopyArr[1], hasCopyArr[1], notDefCtorArr[1], dtorArr[1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1]"}
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE1]] : !cir.ptr<!cir.array<!s32i x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_f -> %[[PRIVATE2]] : !cir.ptr<!cir.array<!cir.float x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
// CHECK-NEXT: acc.loop combined(serial)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(someIntArr[1:1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1:1]"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE]] : !cir.ptr<!cir.array<!s32i x 5>>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial loop firstprivate(someFloatArr[1:1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1:1]"}
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_f -> %[[PRIVATE]] : !cir.ptr<!cir.array<!cir.float x 5>>) {
// CHECK-NEXT: acc.loop combined(serial)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(noCopyArr[1:1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1:1]"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial loop firstprivate(hasCopyArr[1:1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1:1]"}
// CHECK-NEXT: acc.serial combined(loop) firstprivate(@firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) {
// CHECK-NEXT: acc.loop combined(serial)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(notDefCtorArr[1:1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1:1]"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(dtorArr[1:1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1:1]"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) {
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel loop firstprivate(someIntArr[1:1], someFloatArr[1:1], noCopyArr[1:1], hasCopyArr[1:1], notDefCtorArr[1:1], dtorArr[1:1])
for(int i = 0; i < 5; ++i);
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1:1]"}
// CHECK-NEXT: acc.parallel combined(loop) firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE1]] : !cir.ptr<!cir.array<!s32i x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_f -> %[[PRIVATE2]] : !cir.ptr<!cir.array<!cir.float x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
// CHECK-NEXT: acc.loop combined(parallel)
// CHECK: acc.yield
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
}

View File

@ -0,0 +1,90 @@
// RUN: %clang_cc1 -fopenacc -triple x86_64-linux-gnu -Wno-openacc-self-if-potential-conflict -emit-cir -fclangir -triple x86_64-linux-pc %s -o - | FileCheck %s
struct CopyConstruct {
CopyConstruct() = default;
CopyConstruct(const CopyConstruct&);
};
struct NonDefaultCtor {
NonDefaultCtor();
};
struct HasDtor {
~HasDtor();
};
// CHECK: acc.firstprivate.recipe @firstprivatization__ZTSi : !cir.ptr<!s32i> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!s32i> {{.*}}):
// CHECK-NEXT: cir.alloca !s32i, !cir.ptr<!s32i>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!s32i> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!s32i> {{.*}}):
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS7HasDtor : !cir.ptr<!rec_HasDtor> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
// CHECK-NEXT: cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } destroy {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ARG]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS14NonDefaultCtor : !cir.ptr<!rec_NonDefaultCtor> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS13CopyConstruct : !cir.ptr<!rec_CopyConstruct> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
// CHECK-NEXT: cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
template<typename T, typename U, typename V, typename W>
void dependent_version(const T &cc, const U &ndc, const V &dtor, const W &someInt) {
// CHECK: cir.func {{.*}}@_Z17dependent_versionI13CopyConstruct14NonDefaultCtor7HasDtoriEvRKT_RKT0_RKT1_RKT2_(%[[ARG0:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}, %[[ARG1:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}, %[[ARG2:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}, %[[ARG3:.*]]: !cir.ptr<!s32i> {{.*}}) {
// CHECK-NEXT: %[[CC:.*]] = cir.alloca !cir.ptr<!rec_CopyConstruct>, !cir.ptr<!cir.ptr<!rec_CopyConstruct>>, ["cc", init, const]
// CHECK-NEXT: %[[NDC:.*]] = cir.alloca !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, ["ndc", init, const]
// CHECK-NEXT: %[[DTOR:.*]] = cir.alloca !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>, ["dtor", init, const]
// CHECK-NEXT: %[[SOMEINT:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["someInt", init, const]
// % 3 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["someInt", init, const]
#pragma acc parallel firstprivate(cc, ndc, dtor, someInt)
;
// CHECK: %[[PRIV_LOAD:.*]] = cir.load %[[CC]] : !cir.ptr<!cir.ptr<!rec_CopyConstruct>>, !cir.ptr<!rec_CopyConstruct>
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[PRIV_LOAD]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "cc"}
// CHECK-NEXT: %[[PRIV_LOAD:.*]] = cir.load %[[NDC]] : !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, !cir.ptr<!rec_NonDefaultCtor>
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[PRIV_LOAD]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "ndc"}
// CHECK-NEXT: %[[PRIV_LOAD:.*]] = cir.load %[[DTOR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[PRIV_LOAD]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
// CHECK-NEXT: %[[PRIV_LOAD:.*]] = cir.load %[[SOMEINT]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[PRIV_LOAD]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE1]] : !cir.ptr<!rec_CopyConstruct>,
// CHECK-SAME: @firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE2]] : !cir.ptr<!rec_NonDefaultCtor>,
// CHECK-SAME: @firstprivatization__ZTS7HasDtor -> %[[PRIVATE3]] : !cir.ptr<!rec_HasDtor>,
// CHECK-SAME: @firstprivatization__ZTSi -> %[[PRIVATE4]] : !cir.ptr<!s32i>) {
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
}
void use() {
CopyConstruct cc;
NonDefaultCtor ndc;
HasDtor dtor;
int i;
dependent_version(cc, ndc, dtor, i);
}

View File

@ -0,0 +1,508 @@
// RUN: %clang_cc1 -fopenacc -triple x86_64-linux-gnu -Wno-openacc-self-if-potential-conflict -emit-cir -fclangir -triple x86_64-linux-pc %s -o - | FileCheck %s
struct NoCopyConstruct {};
struct CopyConstruct {
CopyConstruct() = default;
CopyConstruct(const CopyConstruct&);
};
struct NonDefaultCtor {
NonDefaultCtor();
};
struct HasDtor {
~HasDtor();
};
// CHECK: acc.firstprivate.recipe @firstprivatization__ZTSA5_7HasDtor : !cir.ptr<!cir.array<!rec_HasDtor x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!rec_HasDtor x 5>, !cir.ptr<!cir.array<!rec_HasDtor x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
//
// CHECK-NEXT: } destroy {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_HasDtor x 5>> {{.*}}):
// CHECK-NEXT: %[[LAST_IDX:.*]] = cir.const #cir.int<4> : !u64i
// CHECK-NEXT: %[[ARRPTR:.*]] = cir.cast(array_to_ptrdecay, %[[ARG]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>), !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: %[[ELEM:.*]] = cir.ptr_stride(%[[ARRPTR]] : !cir.ptr<!rec_HasDtor>, %[[LAST_IDX]] : !u64i), !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: %[[ITR:.*]] = cir.alloca !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>, ["__array_idx"]
// CHECK-NEXT: cir.store %[[ELEM]], %[[ITR]] : !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>
// CHECK-NEXT: cir.do {
// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ELEM_LOAD]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
// CHECK-NEXT: %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
// CHECK-NEXT: %[[PREVELEM:.*]] = cir.ptr_stride(%[[ELEM_LOAD]] : !cir.ptr<!rec_HasDtor>, %[[NEG_ONE]] : !s64i), !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: cir.store %[[PREVELEM]], %[[ITR]] : !cir.ptr<!rec_HasDtor>, !cir.ptr<!cir.ptr<!rec_HasDtor>>
// CHECK-NEXT: cir.yield
// CHECK-NEXT: } while {
// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_HasDtor>>, !cir.ptr<!rec_HasDtor>
// CHECK-NEXT: %[[CMP:.*]] = cir.cmp(ne, %[[ELEM_LOAD]], %[[ARRPTR]]) : !cir.ptr<!rec_HasDtor>, !cir.bool
// CHECK-NEXT: cir.condition(%[[CMP]])
// CHECK-NEXT: }
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_14NonDefaultCtor : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_13CopyConstruct : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!rec_CopyConstruct x 5>, !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_15NoCopyConstruct : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!rec_NoCopyConstruct x 5>, !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_f : !cir.ptr<!cir.array<!cir.float x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!cir.float x 5>, !cir.ptr<!cir.array<!cir.float x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!cir.float x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSA5_i : !cir.ptr<!cir.array<!s32i x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.array<!s32i x 5>, !cir.ptr<!cir.array<!s32i x 5>>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FORM:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.array<!s32i x 5>> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS7HasDtor : !cir.ptr<!rec_HasDtor> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
// CHECK-NEXT: cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } destroy {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_HasDtor> {{.*}}):
// CHECK-NEXT: cir.call @_ZN7HasDtorD1Ev(%[[ARG]]) nothrow : (!cir.ptr<!rec_HasDtor>) -> ()
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS14NonDefaultCtor : !cir.ptr<!rec_NonDefaultCtor> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NonDefaultCtor> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS13CopyConstruct : !cir.ptr<!rec_CopyConstruct> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
// CHECK-NEXT: cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_CopyConstruct> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTS15NoCopyConstruct : !cir.ptr<!rec_NoCopyConstruct> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}):
// CHECK-NEXT: cir.alloca !rec_NoCopyConstruct, !cir.ptr<!rec_NoCopyConstruct>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!rec_NoCopyConstruct> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSf : !cir.ptr<!cir.float> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.float> {{.*}}):
// CHECK-NEXT: cir.alloca !cir.float, !cir.ptr<!cir.float>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!cir.float> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!cir.float> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
//
// CHECK-NEXT: acc.firstprivate.recipe @firstprivatization__ZTSi : !cir.ptr<!s32i> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!s32i> {{.*}}):
// CHECK-NEXT: cir.alloca !s32i, !cir.ptr<!s32i>, ["openacc.private.init"]
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } copy {
// CHECK-NEXT: ^bb0(%[[ARG_FROM:.*]]: !cir.ptr<!s32i> {{.*}}, %[[ARG_TO:.*]]: !cir.ptr<!s32i> {{.*}}):
//
// CHECK-NEXT: acc.yield
// CHECK-NEXT: }
extern "C" void acc_compute() {
// CHECK: cir.func{{.*}} @acc_compute() {
int someInt;
// CHECK-NEXT: %[[SOMEINT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["someInt"]
float someFloat;
// CHECK-NEXT: %[[SOMEFLOAT:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["someFloat"]
NoCopyConstruct noCopy;
// CHECK-NEXT: %[[NOCOPY:.*]] = cir.alloca !rec_NoCopyConstruct, !cir.ptr<!rec_NoCopyConstruct>, ["noCopy"]
CopyConstruct hasCopy;
// CHECK-NEXT: %[[HASCOPY:.*]] = cir.alloca !rec_CopyConstruct, !cir.ptr<!rec_CopyConstruct>, ["hasCopy"]
NonDefaultCtor notDefCtor;
// CHECK-NEXT: %[[NOTDEFCTOR:.*]] = cir.alloca !rec_NonDefaultCtor, !cir.ptr<!rec_NonDefaultCtor>, ["notDefCtor", init]
HasDtor dtor;
// CHECK-NEXT: %[[DTOR:.*]] = cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>, ["dtor"]
int someIntArr[5];
// CHECK-NEXT: %[[INTARR:.*]] = cir.alloca !cir.array<!s32i x 5>, !cir.ptr<!cir.array<!s32i x 5>>, ["someIntArr"]
float someFloatArr[5];
// CHECK-NEXT: %[[FLOATARR:.*]] = cir.alloca !cir.array<!cir.float x 5>, !cir.ptr<!cir.array<!cir.float x 5>>, ["someFloatArr"]
NoCopyConstruct noCopyArr[5];
// CHECK-NEXT: %[[NOCOPYARR:.*]] = cir.alloca !cir.array<!rec_NoCopyConstruct x 5>, !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>, ["noCopyArr"]
CopyConstruct hasCopyArr[5];
// CHECK-NEXT: %[[HASCOPYARR:.*]] = cir.alloca !cir.array<!rec_CopyConstruct x 5>, !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>, ["hasCopyArr"]
NonDefaultCtor notDefCtorArr[5];
// CHECK-NEXT: %[[NOTDEFCTORARR:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["notDefCtorArr", init]
HasDtor dtorArr[5];
// CHECK-NEXT: %[[DTORARR:.*]] = cir.alloca !cir.array<!rec_HasDtor x 5>, !cir.ptr<!cir.array<!rec_HasDtor x 5>>, ["dtorArr"]
// CHECK-NEXT: cir.call @_ZN14NonDefaultCtorC1Ev(%[[NOTDEFCTOR]]) : (!cir.ptr<!rec_NonDefaultCtor>) -> ()
#pragma acc parallel firstprivate(someInt)
;
// CHECK: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[SOMEINT]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSi -> %[[PRIVATE]] : !cir.ptr<!s32i>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial firstprivate(someFloat)
;
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[SOMEFLOAT]] : !cir.ptr<!cir.float>) -> !cir.ptr<!cir.float> {name = "someFloat"}
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSf -> %[[PRIVATE]] : !cir.ptr<!cir.float>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(noCopy)
;
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPY]] : !cir.ptr<!rec_NoCopyConstruct>) -> !cir.ptr<!rec_NoCopyConstruct> {name = "noCopy"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTS15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!rec_NoCopyConstruct>
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial firstprivate(hasCopy)
;
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPY]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "hasCopy"}
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!rec_CopyConstruct>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial firstprivate(notDefCtor)
;
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTOR]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "notDefCtor"}
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!rec_NonDefaultCtor>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial firstprivate(dtor)
;
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTOR]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTS7HasDtor -> %[[PRIVATE]] : !cir.ptr<!rec_HasDtor>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(someInt, someFloat, noCopy, hasCopy, notDefCtor, dtor)
;
// CHECK: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[SOMEINT]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {name = "someInt"}
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[SOMEFLOAT]] : !cir.ptr<!cir.float>) -> !cir.ptr<!cir.float> {name = "someFloat"}
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPY]] : !cir.ptr<!rec_NoCopyConstruct>) -> !cir.ptr<!rec_NoCopyConstruct> {name = "noCopy"}
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPY]] : !cir.ptr<!rec_CopyConstruct>) -> !cir.ptr<!rec_CopyConstruct> {name = "hasCopy"}
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTOR]] : !cir.ptr<!rec_NonDefaultCtor>) -> !cir.ptr<!rec_NonDefaultCtor> {name = "notDefCtor"}
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTOR]] : !cir.ptr<!rec_HasDtor>) -> !cir.ptr<!rec_HasDtor> {name = "dtor"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSi -> %[[PRIVATE1]] : !cir.ptr<!s32i>,
// CHECK-SAME: @firstprivatization__ZTSf -> %[[PRIVATE2]] : !cir.ptr<!cir.float>,
// CHECK-SAME: @firstprivatization__ZTS15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!rec_NoCopyConstruct>,
// CHECK-SAME: @firstprivatization__ZTS13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!rec_CopyConstruct>,
// CHECK-SAME: @firstprivatization__ZTS14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!rec_NonDefaultCtor>,
// CHECK-SAME: @firstprivatization__ZTS7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!rec_HasDtor>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial firstprivate(someIntArr[1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1]"}
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE]] : !cir.ptr<!cir.array<!s32i x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(someFloatArr[1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1]"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_f -> %[[PRIVATE]] : !cir.ptr<!cir.array<!cir.float x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial firstprivate(noCopyArr[1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1]"}
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(hasCopyArr[1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1]"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(notDefCtorArr[1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1]"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(dtorArr[1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1]"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial firstprivate(someIntArr[1], someFloatArr[1], noCopyArr[1], hasCopyArr[1], notDefCtorArr[1], dtorArr[1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE_CONST:.*]] = arith.constant 1
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CONST]] : i64) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1]"}
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE1]] : !cir.ptr<!cir.array<!s32i x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_f -> %[[PRIVATE2]] : !cir.ptr<!cir.array<!cir.float x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(someIntArr[1:1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1:1]"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE]] : !cir.ptr<!cir.array<!s32i x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial firstprivate(someFloatArr[1:1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1:1]"}
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_f -> %[[PRIVATE]] : !cir.ptr<!cir.array<!cir.float x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(noCopyArr[1:1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1:1]"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc serial firstprivate(hasCopyArr[1:1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1:1]"}
// CHECK-NEXT: acc.serial firstprivate(@firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(notDefCtorArr[1:1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1:1]"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(dtorArr[1:1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1:1]"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
#pragma acc parallel firstprivate(someIntArr[1:1], someFloatArr[1:1], noCopyArr[1:1], hasCopyArr[1:1], notDefCtorArr[1:1], dtorArr[1:1])
;
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE1:.*]] = acc.firstprivate varPtr(%[[INTARR]] : !cir.ptr<!cir.array<!s32i x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!s32i x 5>> {name = "someIntArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE2:.*]] = acc.firstprivate varPtr(%[[FLOATARR]] : !cir.ptr<!cir.array<!cir.float x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!cir.float x 5>> {name = "someFloatArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE3:.*]] = acc.firstprivate varPtr(%[[NOCOPYARR]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>> {name = "noCopyArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE4:.*]] = acc.firstprivate varPtr(%[[HASCOPYARR]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_CopyConstruct x 5>> {name = "hasCopyArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE5:.*]] = acc.firstprivate varPtr(%[[NOTDEFCTORARR]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {name = "notDefCtorArr[1:1]"}
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT: %[[ONE_CAST2:.*]] = builtin.unrealized_conversion_cast %[[ONE]] : !s32i to si32
// CHECK-NEXT: %[[ZERO_CONST:.*]] = arith.constant 0
// CHECK-NEXT: %[[ONE_CONST2:.*]] = arith.constant 1
// CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ONE_CAST]] : si32) extent(%[[ONE_CAST2]] : si32) stride(%[[ONE_CONST2]] : i64) startIdx(%[[ZERO_CONST]] : i64)
// CHECK-NEXT: %[[PRIVATE6:.*]] = acc.firstprivate varPtr(%[[DTORARR]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.array<!rec_HasDtor x 5>> {name = "dtorArr[1:1]"}
// CHECK-NEXT: acc.parallel firstprivate(@firstprivatization__ZTSA5_i -> %[[PRIVATE1]] : !cir.ptr<!cir.array<!s32i x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_f -> %[[PRIVATE2]] : !cir.ptr<!cir.array<!cir.float x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_15NoCopyConstruct -> %[[PRIVATE3]] : !cir.ptr<!cir.array<!rec_NoCopyConstruct x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_13CopyConstruct -> %[[PRIVATE4]] : !cir.ptr<!cir.array<!rec_CopyConstruct x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_14NonDefaultCtor -> %[[PRIVATE5]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>,
// CHECK-SAME: @firstprivatization__ZTSA5_7HasDtor -> %[[PRIVATE6]] : !cir.ptr<!cir.array<!rec_HasDtor x 5>>)
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } loc
}

View File

@ -10,9 +10,6 @@ void HelloWorld(int *A, int *B, int *C, int N) {
// expected-error@+1{{ClangIR code gen Not Yet Implemented: OpenACC Declare Construct}}
#pragma acc declare create(A)
// expected-error@+1{{ClangIR code gen Not Yet Implemented: OpenACC Clause: firstprivate}}
#pragma acc parallel loop firstprivate(A)
for(int i = 0; i <5; ++i);
// expected-error@+1{{ClangIR code gen Not Yet Implemented: OpenACC Clause: reduction}}
#pragma acc parallel loop reduction(+:A)
for(int i = 0; i <5; ++i);

View File

@ -115,7 +115,7 @@ void usage() {
S(); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
S('A'); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}}
S(1);
S(2.2);
S(2.2); // expected-warning {{ignoring temporary created by a constructor declared with 'gnu::warn_unused_result' attribute}}
Y(); // expected-warning {{ignoring temporary of type 'Y' declared with 'nodiscard' attribute: Don't throw me away either!}}
S s;
ConvertTo{}; // expected-warning {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}

View File

@ -1,8 +1,147 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -verify -o %t/M.pcm
// RUN: split-file %s %t
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/line.cpp -verify -o %t/line.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/gnu_line_marker.cpp -verify -o %t/gnu_line_marker.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/include.cpp -verify -o %t/include.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/ident.cpp -verify -o %t/ident.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_comment.cpp -verify -o %t/pragma_comment.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_mark.cpp -verify -o %t/pragma_mark.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_detect_mismatch.cpp -verify -o %t/pragma_detect_mismatch.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_clang_debug.cpp -verify -o %t/pragma_clang_debug.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_message.cpp -verify -o %t/pragma_message.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_gcc_warn.cpp -verify -o %t/pragma_gcc_warn.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_gcc_error.cpp -verify -o %t/pragma_gcc_error.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_diag_push_pop.cpp -verify -o %t/pragma_diag_push_pop.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_diag_ignore.cpp -verify -o %t/pragma_diag_ignore.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_opencl_ext.cpp -verify -o %t/pragma_opencl_ext.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_push_pop.cpp -verify -o %t/pragma_push_pop.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_exec_charset.cpp -verify -o %t/pragma_exec_charset.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_clang_assume_nonnull.cpp -verify -o %t/pragma_clang_assume_nonnull.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/marco_expand.cpp -DMACRO="" -verify -o %t/marco_expand.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/define.cpp -verify -o %t/define.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/undef.cpp -verify -o %t/undef.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/defined.cpp -verify -o %t/defined.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/has_embed.cpp -verify -o %t/has_embed.pcm
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/has_include.cpp -verify -o %t/has_include.pcm
//--- header.h
#ifndef HEADER_H
#define HEADER_H
#endif // HEADER_H
//--- line.cpp
// expected-no-diagnostics
#line 3
export module M;
//--- gnu_line_marker.cpp
// expected-no-diagnostics
# 1 __FILE__ 1 3
export module M;
//--- include.cpp
#include "header.h" // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
//--- ident.cpp
// expected-no-diagnostics
#ident "$Header:$"
export module M;
//--- pragma_comment.cpp
// expected-no-diagnostics
#pragma comment(lib, "msvcrt.lib")
export module M;
//--- pragma_mark.cpp
// expected-no-diagnostics
#pragma mark LLVM's world
export module M;
//--- pragma_detect_mismatch.cpp
// expected-no-diagnostics
#pragma detect_mismatch("test", "1")
export module M;
//--- pragma_clang_debug.cpp
// expected-no-diagnostics
#pragma clang __debug dump Test
export module M;
//--- pragma_message.cpp
#pragma message "test" // expected-warning {{test}}
export module M;
//--- pragma_gcc_warn.cpp
#pragma GCC warning "Foo" // expected-warning {{Foo}}
export module M;
//--- pragma_gcc_error.cpp
#pragma GCC error "Foo" // expected-error {{Foo}}
export module M;
//--- pragma_diag_push_pop.cpp
// expected-no-diagnostics
#pragma gcc diagnostic push
#pragma gcc diagnostic pop
export module M;
//--- pragma_diag_ignore.cpp
// expected-no-diagnostics
#pragma GCC diagnostic ignored "-Wframe-larger-than"
export module M;
//--- pragma_opencl_ext.cpp
// expected-no-diagnostics
#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
export module M;
//--- pragma_push_pop.cpp
// expected-no-diagnostics
#pragma warning(push)
#pragma warning(pop)
export module M;
//--- pragma_exec_charset.cpp
// expected-no-diagnostics
#pragma execution_character_set(push, "UTF-8")
#pragma execution_character_set(pop)
export module M;
//--- pragma_clang_assume_nonnull.cpp
// expected-no-diagnostics
#pragma clang assume_nonnull begin
#pragma clang assume_nonnull end
export module M;
//--- marco_expand.cpp
MACRO // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
//--- define.cpp
// This is a comment
#define I32 int // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
export I32 i32;
//--- undef.cpp
#undef FOO // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
//--- defined.cpp
#if defined(FOO) // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
#endif
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
//--- has_embed.cpp
#if __has_embed(__FILE__ ext::token(0xB055)) // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}}
#endif
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}
//--- has_include.cpp
#if __has_include(<stdio.h>) || __has_include_next(<stdlib.h>) // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}} \
// expected-warning {{#include_next in primary source file; will search from start of include path}}
#endif
export module M; // expected-error {{module declaration must occur at the start of the translation unit}}

View File

@ -239,5 +239,21 @@ void f2() {
}
namespace GH153884 {
bool f1() {
auto f = [](auto) { return true; };
if constexpr (0)
return f(1);
return false;
}
bool f2() {
auto f = [](auto x) { if (x) return 1.5; else return "wat"; };
// expected-error@-1 {{'auto' in return type deduced as 'const char *' here but deduced as 'double' in earlier return statement}}
if constexpr (0)
return f(1);
// expected-note@-1 {{in instantiation of function template specialization 'GH153884::f2()}}
return false;
}
}
#endif

View File

@ -0,0 +1,66 @@
// REQUIRES: riscv-registered-target
// RUN: %clang_cc1 -triple riscv32 -target-feature +v \
// RUN: -mvscale-min=2 -mvscale-max=2 -O2 -emit-llvm %s -o - \
// RUN: | FileCheck %s
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
// RUN: -mvscale-min=2 -mvscale-max=2 -O2 -emit-llvm %s -o - \
// RUN: | FileCheck %s
// Test RISC-V V-extension fixed-length vector inline assembly constraints.
#include <riscv_vector.h>
#include <stdbool.h>
typedef vbool1_t fixed_bool1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
typedef vint32m1_t fixed_i32m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
typedef vint8mf2_t fixed_i8mf2_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen / 2)));
typedef bool bx2 __attribute__((ext_vector_type(16)));
typedef int i32x2 __attribute__((ext_vector_type(2)));
typedef char i8x4 __attribute__((ext_vector_type(4)));
fixed_i32m1_t test_vr(fixed_i32m1_t a) {
// CHECK-LABEL: define{{.*}} @test_vr
// CHECK: %0 = tail call <4 x i32> asm sideeffect "vadd.vv $0, $1, $2", "=^vr,^vr,^vr"(<4 x i32> %a, <4 x i32> %a)
fixed_i32m1_t ret;
asm volatile ("vadd.vv %0, %1, %2" : "=vr"(ret) : "vr"(a), "vr"(a));
return ret;
}
i32x2 test_vr2(i32x2 a) {
// CHECK-LABEL: define{{.*}} @test_vr2
// CHECK: %1 = tail call <2 x i32> asm sideeffect "vadd.vv $0, $1, $2", "=^vr,^vr,^vr"(<2 x i32> %0, <2 x i32> %0)
i32x2 ret;
asm volatile ("vadd.vv %0, %1, %2" : "=vr"(ret) : "vr"(a), "vr"(a));
return ret;
}
fixed_i8mf2_t test_vd(fixed_i8mf2_t a) {
// CHECK-LABEL: define{{.*}} @test_vd
// CHECK: %0 = tail call <8 x i8> asm sideeffect "vadd.vv $0, $1, $2", "=^vd,^vr,^vr"(<8 x i8> %a, <8 x i8> %a)
fixed_i8mf2_t ret;
asm volatile ("vadd.vv %0, %1, %2" : "=vd"(ret) : "vr"(a), "vr"(a));
return ret;
}
i8x4 test_vd2(i8x4 a) {
// CHECK-LABEL: define{{.*}} @test_vd2
// CHECK: %1 = tail call <4 x i8> asm sideeffect "vadd.vv $0, $1, $2", "=^vd,^vr,^vr"(<4 x i8> %0, <4 x i8> %0)
i8x4 ret;
asm volatile ("vadd.vv %0, %1, %2" : "=vd"(ret) : "vr"(a), "vr"(a));
return ret;
}
fixed_bool1_t test_vm(fixed_bool1_t a) {
// CHECK-LABEL: define{{.*}} @test_vm
// CHECK: %1 = tail call <16 x i8> asm sideeffect "vmand.mm $0, $1, $2", "=^vm,^vm,^vm"(<16 x i8> %a, <16 x i8> %a)
fixed_bool1_t ret;
asm volatile ("vmand.mm %0, %1, %2" : "=vm"(ret) : "vm"(a), "vm"(a));
return ret;
}
void test_vm2(bx2 a) {
// CHECK-LABEL: define{{.*}} @test_vm2
// CHECK: tail call void asm sideeffect "dummy $0", "^vm"(<16 x i1> %a1)
asm volatile ("dummy %0" :: "vm"(a));
}

View File

@ -920,6 +920,7 @@ __m256i test_mm256_mul_epi32(__m256i a, __m256i b) {
// CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
return _mm256_mul_epi32(a, b);
}
TEST_CONSTEXPR(match_m256i(_mm256_mul_epi32((__m256i)(__v8si){+1, -2, +3, -4, +5, -6, +7, -8}, (__m256i)(__v8si){-16, -14, +12, +10, -8, +6, -4, +2}), -16, 36, -40, -28));
__m256i test_mm256_mul_epu32(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_mul_epu32
@ -928,6 +929,7 @@ __m256i test_mm256_mul_epu32(__m256i a, __m256i b) {
// CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
return _mm256_mul_epu32(a, b);
}
TEST_CONSTEXPR(match_m256i(_mm256_mul_epu32((__m256i)(__v8si){+1, -2, +3, -4, +5, -6, +7, -8}, (__m256i)(__v8si){-16, -14, +12, +10, -8, +6, -4, +2}), 4294967280, 36, 21474836440, 30064771044));
__m256i test_mm256_mulhi_epu16(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_mulhi_epu16

View File

@ -19,12 +19,15 @@ __m512i test_mm512_mask_popcnt_epi16(__m512i __A, __mmask32 __U, __m512i __B) {
// CHECK: select <32 x i1> %{{[0-9]+}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_popcnt_epi16(__A, __U, __B);
}
TEST_CONSTEXPR(match_v32hi(_mm512_mask_popcnt_epi16(_mm512_set1_epi16(-1), 0xF0F0F0F0, (__m512i)(__v32hi){+5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025, +5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025}), -1, -1, -1, -1, 0, 8, 1, 9, -1, -1, -1, -1, 6, 2, 9, 2, -1, -1, -1, -1, 0, 8, 1, 9, -1, -1, -1, -1, 6, 2, 9, 2));
__m512i test_mm512_maskz_popcnt_epi16(__mmask32 __U, __m512i __B) {
// CHECK-LABEL: test_mm512_maskz_popcnt_epi16
// CHECK: @llvm.ctpop.v32i16
// CHECK: select <32 x i1> %{{[0-9]+}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_popcnt_epi16(__U, __B);
}
TEST_CONSTEXPR(match_v32hi(_mm512_maskz_popcnt_epi16(0x0F0F0F0F, (__m512i)(__v32hi){+5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025, +5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025}), 2, 15, 14, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0, 2, 15, 14, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0));
__m512i test_mm512_popcnt_epi8(__m512i __A) {
// CHECK-LABEL: test_mm512_popcnt_epi8
@ -39,12 +42,15 @@ __m512i test_mm512_mask_popcnt_epi8(__m512i __A, __mmask64 __U, __m512i __B) {
// CHECK: select <64 x i1> %{{[0-9]+}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask_popcnt_epi8(__A, __U, __B);
}
TEST_CONSTEXPR(match_v64qi(_mm512_mask_popcnt_epi8(_mm512_set1_epi8(-1), 0xF0F0F0F00F0F0F0FULL, (__m512i)(__v64qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 2, 7, 6, 1, -1, -1, -1, -1, 2, 2, 4, 2, -1, -1, -1, -1, 2, 7, 6, 1, -1, -1, -1, -1, 2, 2, 4, 2, -1, -1, -1, -1, -1, -1, -1, -1, 0, 4, 1, 4, -1, -1, -1, -1, 6, 2, 4, 3, -1, -1, -1, -1, 0, 4, 1, 4, -1, -1, -1, -1, 6, 2, 4, 3));
__m512i test_mm512_maskz_popcnt_epi8(__mmask64 __U, __m512i __B) {
// CHECK-LABEL: test_mm512_maskz_popcnt_epi8
// CHECK: @llvm.ctpop.v64i8
// CHECK: select <64 x i1> %{{[0-9]+}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_popcnt_epi8(__U, __B);
}
TEST_CONSTEXPR(match_v64qi(_mm512_maskz_popcnt_epi8(0x0F0F0F0FF0F0F0F0ULL, (__m512i)(__v64qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 0, 0, 0, 0, 0, 4, 1, 4, 0, 0, 0, 0, 6, 2, 4, 3, 0, 0, 0, 0, 0, 4, 1, 4, 0, 0, 0, 0, 6, 2, 4, 3, 2, 7, 6, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0, 2, 7, 6, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0));
__mmask64 test_mm512_mask_bitshuffle_epi64_mask(__mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: test_mm512_mask_bitshuffle_epi64_mask

View File

@ -3027,6 +3027,7 @@ __m512i test_mm512_mul_epi32(__m512i __A, __m512i __B) {
//CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
return _mm512_mul_epi32(__A,__B);
}
TEST_CONSTEXPR(match_v8di(_mm512_mul_epi32((__m512i)(__v16si){+1, -2, +3, -4, +5, -6, +7, -8, +9, -10, +11, -12, +13, -14, +15, -16}, (__m512i)(__v16si){-32, -30, +28, +26, -24, -22, +20, +18, -16, -14, +12, +10, -8, +6, -4, +2}), -32, 84, -120, 140, -144, 132, -104, -60));
__m512i test_mm512_maskz_mul_epi32 (__mmask8 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: test_mm512_maskz_mul_epi32
@ -3057,6 +3058,7 @@ __m512i test_mm512_mul_epu32 (__m512i __A, __m512i __B) {
//CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
return _mm512_mul_epu32(__A,__B);
}
TEST_CONSTEXPR(match_m512i(_mm512_mul_epu32((__m512i)(__v16si){+1, -2, +3, -4, +5, -6, +7, -8, +9, -10, +11, -12, +13, -14, +15, -16}, (__m512i)(__v16si){-32, -30, +28, +26, -24, -22, +20, +18, -16, -14, +12, +10, -8, +6, -4, +2}), 4294967264, 84, 21474836360, 140, 38654705520, 132, 55834574744, 64424509380));
__m512i test_mm512_maskz_mul_epu32 (__mmask8 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: test_mm512_maskz_mul_epu32
@ -8953,29 +8955,34 @@ __m512d test_mm512_maskz_cvtps_pd(__mmask8 __U, __m256 __A) {
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_cvtps_pd(__U, __A);
}
__m512d test_mm512_mask_mov_pd(__m512d __W, __mmask8 __U, __m512d __A) {
// CHECK-LABEL: test_mm512_mask_mov_pd
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_mov_pd(__W, __U, __A);
}
TEST_CONSTEXPR(match_m512d(_mm512_mask_mov_pd((__m512d){-8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0}, 0xC3, (__m512d){+1.0, +2.0, +3.0, +4.0, +5.0, +6.0, +7.0, +8.0}), +1.0, +2.0, -6.0, -5.0, -4.0, -3.0, +7.0, +8.0));
__m512d test_mm512_maskz_mov_pd(__mmask8 __U, __m512d __A) {
// CHECK-LABEL: test_mm512_maskz_mov_pd
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_mov_pd(__U, __A);
}
TEST_CONSTEXPR(match_m512d(_mm512_maskz_mov_pd(0xC3, (__m512d){+1.0, +2.0, +3.0, +4.0, +5.0, +6.0, +7.0, +8.0}), +1.0, +2.0, +0.0, +0.0, +0.0, +0.0, +7.0, +8.0));
__m512 test_mm512_mask_mov_ps(__m512 __W, __mmask16 __U, __m512 __A) {
// CHECK-LABEL: test_mm512_mask_mov_ps
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_mov_ps(__W, __U, __A);
}
TEST_CONSTEXPR(match_m512(_mm512_mask_mov_ps((__m512){-16.0f, -15.0f, -14.0f, -13.0f, -12.0f, -11.0f, -10.0f, -9.0f, -8.0f, -7.0f, -6.0f, -5.0f, -4.0f, -3.0f, -2.0f, -1.0f}, 0x0FF0, (__m512){+1.0f, +2.0f, +3.0f, +4.0f, +5.0f, +6.0f, +7.0f, +8.0f, +9.0f, +10.0f, +11.0f, +12.0f, +13.0f, +14.0f, +15.0f, +16.0f}), -16.0f, -15.0f, -14.0f, -13.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, -4.0f, -3.0f, -2.0f, -1.0f));
__m512 test_mm512_maskz_mov_ps(__mmask16 __U, __m512 __A) {
// CHECK-LABEL: test_mm512_maskz_mov_ps
// CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_mov_ps(__U, __A);
}
TEST_CONSTEXPR(match_m512(_mm512_maskz_mov_ps(0xF3F3, (__m512){+1.0f, +2.0f, +3.0f, +4.0f, +5.0f, +6.0f, +7.0f, +8.0f, +9.0f, +10.0f, +11.0f, +12.0f, +13.0f, +14.0f, +15.0f, +16.0f}), +1.0f, +2.0f, 0.0f, 0.0f, +5.0f, +6.0f, +7.0f, +8.0f, +9.0f, +10.0f, 0.0f, 0.0f, +13.0f, +14.0f, +15.0f, +16.0f));
void test_mm512_mask_compressstoreu_pd(void *__P, __mmask8 __U, __m512d __A) {
// CHECK-LABEL: test_mm512_mask_compressstoreu_pd

View File

@ -9517,48 +9517,56 @@ __m128d test_mm_mask_mov_pd(__m128d __W, __mmask8 __U, __m128d __A) {
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_mov_pd(__W, __U, __A);
}
TEST_CONSTEXPR(match_m128d(_mm_mask_mov_pd((__m128d){-2.0, -1.0}, 0x2, (__m128d){+1.0, +2.0}), -2.0, +2.0));
__m128d test_mm_maskz_mov_pd(__mmask8 __U, __m128d __A) {
// CHECK-LABEL: test_mm_maskz_mov_pd
// CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_mov_pd(__U, __A);
}
TEST_CONSTEXPR(match_m128d(_mm_maskz_mov_pd(0x1, (__m128d){+1.0, +2.0}), +1.0, +0.0));
__m256d test_mm256_mask_mov_pd(__m256d __W, __mmask8 __U, __m256d __A) {
// CHECK-LABEL: test_mm256_mask_mov_pd
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_mov_pd(__W, __U, __A);
}
TEST_CONSTEXPR(match_m256d(_mm256_mask_mov_pd((__m256d){-4.0, -3.0, -2.0, -1.0}, 0x3, (__m256d){+1.0, +2.0, +3.0, +4.0}), +1.0, +2.0, -2.0, -1.0));
__m256d test_mm256_maskz_mov_pd(__mmask8 __U, __m256d __A) {
// CHECK-LABEL: test_mm256_maskz_mov_pd
// CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_mov_pd(__U, __A);
}
TEST_CONSTEXPR(match_m256d(_mm256_maskz_mov_pd(0xC, (__m256d){+1.0, +2.0, +3.0, +4.0}), 0.0, 0.0, +3.0, +4.0));
__m128 test_mm_mask_mov_ps(__m128 __W, __mmask8 __U, __m128 __A) {
// CHECK-LABEL: test_mm_mask_mov_ps
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_mov_ps(__W, __U, __A);
}
TEST_CONSTEXPR(match_m128(_mm_mask_mov_ps((__m128){-4.0f, -3.0f, -2.0f, -1.0f}, 0x3, (__m128){+1.0f, +2.0f, +3.0f, +4.0f}), +1.0f, +2.0f, -2.0f, -1.0f));
__m128 test_mm_maskz_mov_ps(__mmask8 __U, __m128 __A) {
// CHECK-LABEL: test_mm_maskz_mov_ps
// CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_mov_ps(__U, __A);
}
TEST_CONSTEXPR(match_m128(_mm_maskz_mov_ps(0xC, (__m128){+1.0f, +2.0f, +3.0f, +4.0f}), 0.0f, 0.0f, +3.0f, +4.0f));
__m256 test_mm256_mask_mov_ps(__m256 __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: test_mm256_mask_mov_ps
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_mov_ps(__W, __U, __A);
}
TEST_CONSTEXPR(match_m256(_mm256_mask_mov_ps((__m256){-8.0f, -7.0f, -6.0f, -5.0f, -4.0f, -3.0f, -2.0f, -1.0f}, 0xC3, (__m256){+1.0f, +2.0f, +3.0f, +4.0f, +5.0f, +6.0f, +7.0f, +8.0f}), +1.0f, +2.0f, -6.0f, -5.0f, -4.0f, -3.0f, +7.0f, +8.0f));
__m256 test_mm256_maskz_mov_ps(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: test_mm256_maskz_mov_ps
// CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_mov_ps(__U, __A);
}
TEST_CONSTEXPR(match_m256(_mm256_maskz_mov_ps(0xC3, (__m256){+1.0f, +2.0f, +3.0f, +4.0f, +5.0f, +6.0f, +7.0f, +8.0f}), +1.0f, +2.0f, 0.0f, 0.0f, 0.0f, 0.0f, +7.0f, +8.0f));
__m128 test_mm_mask_cvtph_ps(__m128 __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: test_mm_mask_cvtph_ps

View File

@ -19,12 +19,15 @@ __m256i test_mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B) {
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_popcnt_epi16(__A, __U, __B);
}
TEST_CONSTEXPR(match_v16hi(_mm256_mask_popcnt_epi16(_mm256_set1_epi16(-1), 0xF0F0, (__m256i)(__v16hi){+5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025}), -1, -1, -1, -1, 0, 8, 1, 9, -1, -1, -1, -1, 6, 2, 9, 2));
__m256i test_mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B) {
// CHECK-LABEL: test_mm256_maskz_popcnt_epi16
// CHECK: @llvm.ctpop.v16i16
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_popcnt_epi16(__U, __B);
}
TEST_CONSTEXPR(match_v16hi(_mm256_maskz_popcnt_epi16(0x0F0F, (__m256i)(__v16hi){+5, -3, -10, +8, 0, -256, +256, -128, +3, +9, +15, +33, +63, +129, +511, +1025}), 2, 15, 14, 1, 0, 0, 0, 0, 2, 2, 4, 2, 0, 0, 0, 0));
__m128i test_mm_popcnt_epi16(__m128i __A) {
// CHECK-LABEL: test_mm_popcnt_epi16
@ -39,12 +42,15 @@ __m128i test_mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B) {
// CHECK: select <8 x i1> %{{[0-9]+}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_popcnt_epi16(__A, __U, __B);
}
TEST_CONSTEXPR(match_v8hi(_mm_mask_popcnt_epi16(_mm_set1_epi16(-1), 0xF0, (__m128i)(__v8hi){+5, -3, -10, +8, 0, -256, +256, -128}), -1, -1, -1, -1, 0, 8, 1, 9));
__m128i test_mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B) {
// CHECK-LABEL: test_mm_maskz_popcnt_epi16
// CHECK: @llvm.ctpop.v8i16
// CHECK: select <8 x i1> %{{[0-9]+}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_popcnt_epi16(__U, __B);
}
TEST_CONSTEXPR(match_v8hi(_mm_maskz_popcnt_epi16(0x0F, (__m128i)(__v8hi){+5, -3, -10, +8, 0, -256, +256, -128}), 2, 15, 14, 1, 0, 0, 0, 0));
__m256i test_mm256_popcnt_epi8(__m256i __A) {
// CHECK-LABEL: test_mm256_popcnt_epi8
@ -59,12 +65,15 @@ __m256i test_mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B) {
// CHECK: select <32 x i1> %{{[0-9]+}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_popcnt_epi8(__A, __U, __B);
}
TEST_CONSTEXPR(match_v32qi(_mm256_mask_popcnt_epi8(_mm256_set1_epi8(-1), 0xF00F, (__m256i)(__v32qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 2, 7, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 2, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1));
__m256i test_mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B) {
// CHECK-LABEL: test_mm256_maskz_popcnt_epi8
// CHECK: @llvm.ctpop.v32i8
// CHECK: select <32 x i1> %{{[0-9]+}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_popcnt_epi8(__U, __B);
}
TEST_CONSTEXPR(match_v32qi(_mm256_maskz_popcnt_epi8(0x0FF0, (__m256i)(__v32qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73, +5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 0, 0, 0, 0, 0, 4, 1, 4, 2, 2, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
__m128i test_mm_popcnt_epi8(__m128i __A) {
// CHECK-LABEL: test_mm_popcnt_epi8
@ -79,12 +88,15 @@ __m128i test_mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B) {
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_popcnt_epi8(__A, __U, __B);
}
TEST_CONSTEXPR(match_v16qi(_mm_mask_popcnt_epi8(_mm_set1_epi8(-1), 0xF00F, (__m128i)(__v16qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 2, 7, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 2, 4, 3));
__m128i test_mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B) {
// CHECK-LABEL: test_mm_maskz_popcnt_epi8
// CHECK: @llvm.ctpop.v16i8
// CHECK: select <16 x i1> %{{[0-9]+}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_popcnt_epi8(__U, __B);
}
TEST_CONSTEXPR(match_v16qi(_mm_maskz_popcnt_epi8(0x0FF0, (__m128i)(__v16qi){+5, -3, -10, +8, 0, -16, +16, -16, +3, +9, +15, +33, +63, +33, +53, +73}), 0, 0, 0, 0, 0, 4, 1, 4, 2, 2, 4, 2, 0, 0, 0, 0));
__mmask32 test_mm256_mask_bitshuffle_epi64_mask(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: test_mm256_mask_bitshuffle_epi64_mask

File diff suppressed because it is too large Load Diff

View File

@ -1,420 +1,426 @@
// RUN: %clang_cc1 -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
// RUN: %clang_cc1 -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
// RUN: %clang_cc1 -x c -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
// RUN: %clang_cc1 -x c++ -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
// RUN: %clang_cc1 -x c++ -ffreestanding %s -O0 -triple=x86_64 -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
// RUN: %clang_cc1 -x c++ -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
// RUN: %clang_cc1 -x c++ -ffreestanding %s -O0 -triple=i386 -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
#include <immintrin.h>
short test_mm_reduce_add_epi16(__m128i __W){
// CHECK-LABEL: @test_mm_reduce_add_epi16(
// CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %{{.*}})
// CHECK-LABEL: test_mm_reduce_add_epi16
// CHECK: call {{.*}}i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %{{.*}})
return _mm_reduce_add_epi16(__W);
}
short test_mm_reduce_mul_epi16(__m128i __W){
// CHECK-LABEL: @test_mm_reduce_mul_epi16(
// CHECK: call i16 @llvm.vector.reduce.mul.v8i16(<8 x i16> %{{.*}})
// CHECK-LABEL: test_mm_reduce_mul_epi16
// CHECK: call {{.*}}i16 @llvm.vector.reduce.mul.v8i16(<8 x i16> %{{.*}})
return _mm_reduce_mul_epi16(__W);
}
short test_mm_reduce_or_epi16(__m128i __W){
// CHECK-LABEL: @test_mm_reduce_or_epi16(
// CHECK: call i16 @llvm.vector.reduce.or.v8i16(<8 x i16> %{{.*}})
// CHECK-LABEL: test_mm_reduce_or_epi16
// CHECK: call {{.*}}i16 @llvm.vector.reduce.or.v8i16(<8 x i16> %{{.*}})
return _mm_reduce_or_epi16(__W);
}
short test_mm_reduce_and_epi16(__m128i __W){
// CHECK-LABEL: @test_mm_reduce_and_epi16(
// CHECK: call i16 @llvm.vector.reduce.and.v8i16(<8 x i16> %{{.*}})
// CHECK-LABEL: test_mm_reduce_and_epi16
// CHECK: call {{.*}}i16 @llvm.vector.reduce.and.v8i16(<8 x i16> %{{.*}})
return _mm_reduce_and_epi16(__W);
}
short test_mm_mask_reduce_add_epi16(__mmask8 __M, __m128i __W){
// CHECK-LABEL: @test_mm_mask_reduce_add_epi16(
// CHECK-LABEL: test_mm_mask_reduce_add_epi16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %{{.*}})
return _mm_mask_reduce_add_epi16(__M, __W);
}
short test_mm_mask_reduce_mul_epi16(__mmask8 __M, __m128i __W){
// CHECK-LABEL: @test_mm_mask_reduce_mul_epi16(
// CHECK-LABEL: test_mm_mask_reduce_mul_epi16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.mul.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.mul.v8i16(<8 x i16> %{{.*}})
return _mm_mask_reduce_mul_epi16(__M, __W);
}
short test_mm_mask_reduce_and_epi16(__mmask8 __M, __m128i __W){
// CHECK-LABEL: @test_mm_mask_reduce_and_epi16(
// CHECK-LABEL: test_mm_mask_reduce_and_epi16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.and.v8i16(<8 x i16> %{{.*}}
// CHECK: call {{.*}}i16 @llvm.vector.reduce.and.v8i16(<8 x i16> %{{.*}}
return _mm_mask_reduce_and_epi16(__M, __W);
}
short test_mm_mask_reduce_or_epi16(__mmask8 __M, __m128i __W){
// CHECK-LABEL: @test_mm_mask_reduce_or_epi16(
// CHECK-LABEL: test_mm_mask_reduce_or_epi16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.or.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.or.v8i16(<8 x i16> %{{.*}})
return _mm_mask_reduce_or_epi16(__M, __W);
}
short test_mm256_reduce_add_epi16(__m256i __W){
// CHECK-LABEL: @test_mm256_reduce_add_epi16(
// CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %{{.*}})
// CHECK-LABEL: test_mm256_reduce_add_epi16
// CHECK: call {{.*}}i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %{{.*}})
return _mm256_reduce_add_epi16(__W);
}
short test_mm256_reduce_mul_epi16(__m256i __W){
// CHECK-LABEL: @test_mm256_reduce_mul_epi16(
// CHECK: call i16 @llvm.vector.reduce.mul.v16i16(<16 x i16> %{{.*}})
// CHECK-LABEL: test_mm256_reduce_mul_epi16
// CHECK: call {{.*}}i16 @llvm.vector.reduce.mul.v16i16(<16 x i16> %{{.*}})
return _mm256_reduce_mul_epi16(__W);
}
short test_mm256_reduce_or_epi16(__m256i __W){
// CHECK-LABEL: @test_mm256_reduce_or_epi16(
// CHECK: call i16 @llvm.vector.reduce.or.v16i16(<16 x i16> %{{.*}})
// CHECK-LABEL: test_mm256_reduce_or_epi16
// CHECK: call {{.*}}i16 @llvm.vector.reduce.or.v16i16(<16 x i16> %{{.*}})
return _mm256_reduce_or_epi16(__W);
}
short test_mm256_reduce_and_epi16(__m256i __W){
// CHECK-LABEL: @test_mm256_reduce_and_epi16(
// CHECK: call i16 @llvm.vector.reduce.and.v16i16(<16 x i16> %{{.*}})
// CHECK-LABEL: test_mm256_reduce_and_epi16
// CHECK: call {{.*}}i16 @llvm.vector.reduce.and.v16i16(<16 x i16> %{{.*}})
return _mm256_reduce_and_epi16(__W);
}
short test_mm256_mask_reduce_add_epi16(__mmask16 __M, __m256i __W){
// CHECK-LABEL: @test_mm256_mask_reduce_add_epi16(
// CHECK-LABEL: test_mm256_mask_reduce_add_epi16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %{{.*}})
return _mm256_mask_reduce_add_epi16(__M, __W);
}
short test_mm256_mask_reduce_mul_epi16(__mmask16 __M, __m256i __W){
// CHECK-LABEL: @test_mm256_mask_reduce_mul_epi16(
// CHECK-LABEL: test_mm256_mask_reduce_mul_epi16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.mul.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.mul.v16i16(<16 x i16> %{{.*}})
return _mm256_mask_reduce_mul_epi16(__M, __W);
}
short test_mm256_mask_reduce_and_epi16(__mmask16 __M, __m256i __W){
// CHECK-LABEL: @test_mm256_mask_reduce_and_epi16(
// CHECK-LABEL: test_mm256_mask_reduce_and_epi16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.and.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.and.v16i16(<16 x i16> %{{.*}})
return _mm256_mask_reduce_and_epi16(__M, __W);
}
short test_mm256_mask_reduce_or_epi16(__mmask16 __M, __m256i __W){
// CHECK-LABEL: @test_mm256_mask_reduce_or_epi16(
// CHECK-LABEL: test_mm256_mask_reduce_or_epi16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.or.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.or.v16i16(<16 x i16> %{{.*}})
return _mm256_mask_reduce_or_epi16(__M, __W);
}
signed char test_mm_reduce_add_epi8(__m128i __W){
// CHECK-LABEL: @test_mm_reduce_add_epi8(
// CHECK: call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %{{.*}})
// CHECK-LABEL: test_mm_reduce_add_epi8
// CHECK: call {{.*}}i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %{{.*}})
return _mm_reduce_add_epi8(__W);
}
signed char test_mm_reduce_mul_epi8(__m128i __W){
// CHECK-LABEL: @test_mm_reduce_mul_epi8(
// CHECK: call i8 @llvm.vector.reduce.mul.v16i8(<16 x i8> %{{.*}})
// CHECK-LABEL: test_mm_reduce_mul_epi8
// CHECK: call {{.*}}i8 @llvm.vector.reduce.mul.v16i8(<16 x i8> %{{.*}})
return _mm_reduce_mul_epi8(__W);
}
signed char test_mm_reduce_and_epi8(__m128i __W){
// CHECK-LABEL: @test_mm_reduce_and_epi8(
// CHECK: call i8 @llvm.vector.reduce.and.v16i8(<16 x i8> %{{.*}})
// CHECK-LABEL: test_mm_reduce_and_epi8
// CHECK: call {{.*}}i8 @llvm.vector.reduce.and.v16i8(<16 x i8> %{{.*}})
return _mm_reduce_and_epi8(__W);
}
signed char test_mm_reduce_or_epi8(__m128i __W){
// CHECK-LABEL: @test_mm_reduce_or_epi8(
// CHECK: call i8 @llvm.vector.reduce.or.v16i8(<16 x i8> %{{.*}})
// CHECK-LABEL: test_mm_reduce_or_epi8
// CHECK: call {{.*}}i8 @llvm.vector.reduce.or.v16i8(<16 x i8> %{{.*}})
return _mm_reduce_or_epi8(__W);
}
signed char test_mm_mask_reduce_add_epi8(__mmask16 __M, __m128i __W){
// CHECK-LABEL: @test_mm_mask_reduce_add_epi8(
// CHECK-LABEL: test_mm_mask_reduce_add_epi8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %{{.*}})
return _mm_mask_reduce_add_epi8(__M, __W);
}
signed char test_mm_mask_reduce_mul_epi8(__mmask16 __M, __m128i __W){
// CHECK-LABEL: @test_mm_mask_reduce_mul_epi8(
// CHECK-LABEL: test_mm_mask_reduce_mul_epi8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.mul.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.mul.v16i8(<16 x i8> %{{.*}})
return _mm_mask_reduce_mul_epi8(__M, __W);
}
signed char test_mm_mask_reduce_and_epi8(__mmask16 __M, __m128i __W){
// CHECK-LABEL: @test_mm_mask_reduce_and_epi8(
// CHECK-LABEL: test_mm_mask_reduce_and_epi8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.and.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.and.v16i8(<16 x i8> %{{.*}})
return _mm_mask_reduce_and_epi8(__M, __W);
}
signed char test_mm_mask_reduce_or_epi8(__mmask16 __M, __m128i __W){
// CHECK-LABEL: @test_mm_mask_reduce_or_epi8(
// CHECK-LABEL: test_mm_mask_reduce_or_epi8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.or.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.or.v16i8(<16 x i8> %{{.*}})
return _mm_mask_reduce_or_epi8(__M, __W);
}
signed char test_mm256_reduce_add_epi8(__m256i __W){
// CHECK-LABEL: @test_mm256_reduce_add_epi8(
// CHECK: call i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %{{.*}})
// CHECK-LABEL: test_mm256_reduce_add_epi8
// CHECK: call {{.*}}i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %{{.*}})
return _mm256_reduce_add_epi8(__W);
}
signed char test_mm256_reduce_mul_epi8(__m256i __W){
// CHECK-LABEL: @test_mm256_reduce_mul_epi8(
// CHECK: call i8 @llvm.vector.reduce.mul.v32i8(<32 x i8> %{{.*}})
// CHECK-LABEL: test_mm256_reduce_mul_epi8
// CHECK: call {{.*}}i8 @llvm.vector.reduce.mul.v32i8(<32 x i8> %{{.*}})
return _mm256_reduce_mul_epi8(__W);
}
signed char test_mm256_reduce_and_epi8(__m256i __W){
// CHECK-LABEL: @test_mm256_reduce_and_epi8(
// CHECK: call i8 @llvm.vector.reduce.and.v32i8(<32 x i8> %{{.*}})
// CHECK-LABEL: test_mm256_reduce_and_epi8
// CHECK: call {{.*}}i8 @llvm.vector.reduce.and.v32i8(<32 x i8> %{{.*}})
return _mm256_reduce_and_epi8(__W);
}
signed char test_mm256_reduce_or_epi8(__m256i __W){
// CHECK-LABEL: @test_mm256_reduce_or_epi8(
// CHECK: call i8 @llvm.vector.reduce.or.v32i8(<32 x i8> %{{.*}})
// CHECK-LABEL: test_mm256_reduce_or_epi8
// CHECK: call {{.*}}i8 @llvm.vector.reduce.or.v32i8(<32 x i8> %{{.*}})
return _mm256_reduce_or_epi8(__W);
}
signed char test_mm256_mask_reduce_add_epi8(__mmask32 __M, __m256i __W){
// CHECK-LABEL: @test_mm256_mask_reduce_add_epi8(
// CHECK-LABEL: test_mm256_mask_reduce_add_epi8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.add.v32i8(<32 x i8> %{{.*}})
return _mm256_mask_reduce_add_epi8(__M, __W);
}
signed char test_mm256_mask_reduce_mul_epi8(__mmask32 __M, __m256i __W){
// CHECK-LABEL: @test_mm256_mask_reduce_mul_epi8(
// CHECK-LABEL: test_mm256_mask_reduce_mul_epi8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.mul.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.mul.v32i8(<32 x i8> %{{.*}})
return _mm256_mask_reduce_mul_epi8(__M, __W);
}
signed char test_mm256_mask_reduce_and_epi8(__mmask32 __M, __m256i __W){
// CHECK-LABEL: @test_mm256_mask_reduce_and_epi8(
// CHECK-LABEL: test_mm256_mask_reduce_and_epi8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.and.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.and.v32i8(<32 x i8> %{{.*}})
return _mm256_mask_reduce_and_epi8(__M, __W);
}
signed char test_mm256_mask_reduce_or_epi8(__mmask32 __M, __m256i __W){
// CHECK-LABEL: @test_mm256_mask_reduce_or_epi8(
// CHECK-LABEL: test_mm256_mask_reduce_or_epi8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.or.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.or.v32i8(<32 x i8> %{{.*}})
return _mm256_mask_reduce_or_epi8(__M, __W);
}
short test_mm_reduce_max_epi16(__m128i __W){
// CHECK-LABEL: test_mm_reduce_max_epi16
// CHECK: call i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> %{{.*}})
return _mm_reduce_max_epi16(__W);
}
short test_mm_reduce_min_epi16(__m128i __W){
// CHECK-LABEL: test_mm_reduce_min_epi16
// CHECK: call i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> %{{.*}})
return _mm_reduce_min_epi16(__W);
}
unsigned short test_mm_reduce_max_epu16(__m128i __W){
// CHECK-LABEL: test_mm_reduce_max_epu16
// CHECK: call i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %{{.*}})
return _mm_reduce_max_epu16(__W);
}
unsigned short test_mm_reduce_min_epu16(__m128i __W){
// CHECK-LABEL: test_mm_reduce_min_epu16
// CHECK: call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> %{{.*}})
return _mm_reduce_min_epu16(__W);
}
short test_mm_mask_reduce_max_epi16(__mmask8 __M, __m128i __W){
// CHECK-LABEL: test_mm_mask_reduce_max_epi16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> %{{.*}})
return _mm_mask_reduce_max_epi16(__M, __W);
}
short test_mm_mask_reduce_min_epi16(__mmask8 __M, __m128i __W){
// CHECK-LABEL: test_mm_mask_reduce_min_epi16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> %{{.*}})
return _mm_mask_reduce_min_epi16(__M, __W);
}
unsigned short test_mm_mask_reduce_max_epu16(__mmask8 __M, __m128i __W){
// CHECK-LABEL: test_mm_mask_reduce_max_epu16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %{{.*}})
return _mm_mask_reduce_max_epu16(__M, __W);
}
unsigned short test_mm_mask_reduce_min_epu16(__mmask8 __M, __m128i __W){
// CHECK-LABEL: test_mm_mask_reduce_min_epu16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> %{{.*}})
return _mm_mask_reduce_min_epu16(__M, __W);
}
short test_mm256_reduce_max_epi16(__m256i __W){
// CHECK-LABEL: test_mm256_reduce_max_epi16
// CHECK: call i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> %{{.*}})
return _mm256_reduce_max_epi16(__W);
}
short test_mm256_reduce_min_epi16(__m256i __W){
// CHECK-LABEL: test_mm256_reduce_min_epi16
// CHECK: call i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> %{{.*}})
return _mm256_reduce_min_epi16(__W);
}
unsigned short test_mm256_reduce_max_epu16(__m256i __W){
// CHECK-LABEL: test_mm256_reduce_max_epu16
// CHECK: call i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> %{{.*}})
return _mm256_reduce_max_epu16(__W);
}
unsigned short test_mm256_reduce_min_epu16(__m256i __W){
// CHECK-LABEL: test_mm256_reduce_min_epu16
// CHECK: call i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> %{{.*}})
return _mm256_reduce_min_epu16(__W);
}
short test_mm256_mask_reduce_max_epi16(__mmask16 __M, __m256i __W){
// CHECK-LABEL: test_mm256_mask_reduce_max_epi16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> %{{.*}})
return _mm256_mask_reduce_max_epi16(__M, __W);
}
short test_mm256_mask_reduce_min_epi16(__mmask16 __M, __m256i __W){
// CHECK-LABEL: test_mm256_mask_reduce_min_epi16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> %{{.*}})
return _mm256_mask_reduce_min_epi16(__M, __W);
}
unsigned short test_mm256_mask_reduce_max_epu16(__mmask16 __M, __m256i __W){
// CHECK-LABEL: test_mm256_mask_reduce_max_epu16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> %{{.*}})
return _mm256_mask_reduce_max_epu16(__M, __W);
}
unsigned short test_mm256_mask_reduce_min_epu16(__mmask16 __M, __m256i __W){
// CHECK-LABEL: test_mm256_mask_reduce_min_epu16
// CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
// CHECK: call i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> %{{.*}})
// CHECK: call {{.*}}i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> %{{.*}})
return _mm256_mask_reduce_min_epu16(__M, __W);
}
signed char test_mm_reduce_max_epi8(__m128i __W){
// CHECK-LABEL: test_mm_reduce_max_epi8
// CHECK: call i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> %{{.*}})
return _mm_reduce_max_epi8(__W);
}
signed char test_mm_reduce_min_epi8(__m128i __W){
// CHECK-LABEL: test_mm_reduce_min_epi8
// CHECK: call i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> %{{.*}})
return _mm_reduce_min_epi8(__W);
}
unsigned char test_mm_reduce_max_epu8(__m128i __W){
// CHECK-LABEL: test_mm_reduce_max_epu8
// CHECK: call i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %{{.*}})
return _mm_reduce_max_epu8(__W);
}
unsigned char test_mm_reduce_min_epu8(__m128i __W){
// CHECK-LABEL: test_mm_reduce_min_epu8
// CHECK: call i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> %{{.*}})
return _mm_reduce_min_epu8(__W);
}
signed char test_mm_mask_reduce_max_epi8(__mmask16 __M, __m128i __W){
// CHECK-LABEL: test_mm_mask_reduce_max_epi8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> %{{.*}})
return _mm_mask_reduce_max_epi8(__M, __W);
}
signed char test_mm_mask_reduce_min_epi8(__mmask16 __M, __m128i __W){
// CHECK-LABEL: test_mm_mask_reduce_min_epi8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> %{{.*}})
return _mm_mask_reduce_min_epi8(__M, __W);
}
unsigned char test_mm_mask_reduce_max_epu8(__mmask16 __M, __m128i __W){
// CHECK-LABEL: test_mm_mask_reduce_max_epu8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %{{.*}})
return _mm_mask_reduce_max_epu8(__M, __W);
}
unsigned char test_mm_mask_reduce_min_epu8(__mmask16 __M, __m128i __W){
// CHECK-LABEL: test_mm_mask_reduce_min_epu8
// CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> %{{.*}})
return _mm_mask_reduce_min_epu8(__M, __W);
}
signed char test_mm256_reduce_max_epi8(__m256i __W){
// CHECK-LABEL: test_mm256_reduce_max_epi8
// CHECK: call i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> %{{.*}})
return _mm256_reduce_max_epi8(__W);
}
signed char test_mm256_reduce_min_epi8(__m256i __W){
// CHECK-LABEL: test_mm256_reduce_min_epi8
// CHECK: call i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> %{{.*}})
return _mm256_reduce_min_epi8(__W);
}
unsigned char test_mm256_reduce_max_epu8(__m256i __W){
// CHECK-LABEL: test_mm256_reduce_max_epu8
// CHECK: call i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %{{.*}})
return _mm256_reduce_max_epu8(__W);
}
unsigned char test_mm256_reduce_min_epu8(__m256i __W){
// CHECK-LABEL: test_mm256_reduce_min_epu8
// CHECK: call i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> %{{.*}})
return _mm256_reduce_min_epu8(__W);
}
signed char test_mm256_mask_reduce_max_epi8(__mmask32 __M, __m256i __W){
// CHECK-LABEL: test_mm256_mask_reduce_max_epi8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> %{{.*}})
return _mm256_mask_reduce_max_epi8(__M, __W);
}
signed char test_mm256_mask_reduce_min_epi8(__mmask32 __M, __m256i __W){
// CHECK-LABEL: test_mm256_mask_reduce_min_epi8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> %{{.*}})
return _mm256_mask_reduce_min_epi8(__M, __W);
}
unsigned char test_mm256_mask_reduce_max_epu8(__mmask32 __M, __m256i __W){
// CHECK-LABEL: test_mm256_mask_reduce_max_epu8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %{{.*}})
return _mm256_mask_reduce_max_epu8(__M, __W);
}
unsigned char test_mm256_mask_reduce_min_epu8(__mmask32 __M, __m256i __W){
// CHECK-LABEL: test_mm256_mask_reduce_min_epu8
// CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
// CHECK: call i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> %{{.*}})
// CHECK: call {{.*}}i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> %{{.*}})
return _mm256_mask_reduce_min_epu8(__M, __W);
}

Some files were not shown because too many files have changed in this diff Show More